├── .dagger ├── .gitattributes ├── .gitignore ├── go.mod ├── go.sum ├── main.go └── versions.go ├── .editorconfig ├── .envrc ├── .github ├── .editorconfig ├── dependabot.yaml └── workflows │ ├── analysis-scorecard.yaml │ └── ci.yaml ├── .gitignore ├── .golangci.yaml ├── Caddyfile ├── LICENSE ├── README.md ├── Taskfile.yaml ├── dagger.json ├── docker-compose.yaml ├── flake.lock ├── flake.nix ├── go.mod ├── go.sum ├── justfile └── module.go /.dagger/.gitattributes: -------------------------------------------------------------------------------- 1 | /dagger.gen.go linguist-generated 2 | /internal/dagger/** linguist-generated 3 | /internal/querybuilder/** linguist-generated 4 | /internal/telemetry/** linguist-generated 5 | -------------------------------------------------------------------------------- /.dagger/.gitignore: -------------------------------------------------------------------------------- 1 | /dagger.gen.go 2 | /internal/dagger 3 | /internal/querybuilder 4 | /internal/telemetry 5 | -------------------------------------------------------------------------------- /.dagger/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/sagikazarmark/caddy-fs-s3/.dagger 2 | 3 | go 1.23.6 4 | 5 | require ( 6 | github.com/99designs/gqlgen v0.17.70 7 | github.com/Khan/genqlient v0.8.0 8 | github.com/sagikazarmark/dagx v0.1.0 9 | github.com/vektah/gqlparser/v2 v2.5.23 10 | go.opentelemetry.io/otel v1.34.0 11 | go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.8.0 12 | go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.8.0 13 | go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.32.0 14 | go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.32.0 15 | go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.32.0 16 | go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.32.0 17 | go.opentelemetry.io/otel/log v0.8.0 18 | go.opentelemetry.io/otel/metric v1.34.0 19 | go.opentelemetry.io/otel/sdk v1.34.0 20 | go.opentelemetry.io/otel/sdk/log v0.8.0 21 | go.opentelemetry.io/otel/sdk/metric v1.34.0 22 | go.opentelemetry.io/otel/trace v1.34.0 23 | go.opentelemetry.io/proto/otlp v1.3.1 24 | golang.org/x/sync v0.12.0 25 | google.golang.org/grpc v1.71.0 26 | ) 27 | 28 | require ( 29 | github.com/cenkalti/backoff/v4 v4.3.0 // indirect 30 | github.com/go-logr/logr v1.4.2 // indirect 31 | github.com/go-logr/stdr v1.2.2 // indirect 32 | github.com/google/uuid v1.6.0 // indirect 33 | github.com/grpc-ecosystem/grpc-gateway/v2 v2.23.0 // indirect 34 | github.com/sosodev/duration v1.3.1 // indirect 35 | github.com/sourcegraph/conc v0.3.0 // indirect 36 | go.opentelemetry.io/auto/sdk v1.1.0 // indirect 37 | go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.32.0 // indirect 38 | go.uber.org/atomic v1.7.0 // indirect 39 | go.uber.org/multierr v1.9.0 // indirect 40 | golang.org/x/net v0.38.0 // indirect 41 | golang.org/x/sys v0.31.0 // indirect 42 | golang.org/x/text v0.23.0 // indirect 43 | google.golang.org/genproto/googleapis/api v0.0.0-20250106144421-5f5ef82da422 // indirect 44 | google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f // indirect 45 | google.golang.org/protobuf v1.36.6 // indirect 46 | ) 47 | 48 | replace go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc => go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.8.0 49 | 50 | replace go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp => go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.8.0 51 | 52 | replace go.opentelemetry.io/otel/log => go.opentelemetry.io/otel/log v0.8.0 53 | 54 | replace go.opentelemetry.io/otel/sdk/log => go.opentelemetry.io/otel/sdk/log v0.8.0 55 | -------------------------------------------------------------------------------- /.dagger/go.sum: -------------------------------------------------------------------------------- 1 | github.com/99designs/gqlgen v0.17.70 h1:xgLIgQuG+Q2L/AE9cW595CT7xCWCe/bpPIFGSfsGSGs= 2 | github.com/99designs/gqlgen v0.17.70/go.mod h1:fvCiqQAu2VLhKXez2xFvLmE47QgAPf/KTPN5XQ4rsHQ= 3 | github.com/Khan/genqlient v0.8.0 h1:Hd1a+E1CQHYbMEKakIkvBH3zW0PWEeiX6Hp1i2kP2WE= 4 | github.com/Khan/genqlient v0.8.0/go.mod h1:hn70SpYjWteRGvxTwo0kfaqg4wxvndECGkfa1fdDdYI= 5 | github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883 h1:bvNMNQO63//z+xNgfBlViaCIJKLlCJ6/fmUseuG0wVQ= 6 | github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= 7 | github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= 8 | github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= 9 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 10 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 11 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 12 | github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= 13 | github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= 14 | github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= 15 | github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= 16 | github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= 17 | github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= 18 | github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= 19 | github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= 20 | github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= 21 | github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= 22 | github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 23 | github.com/grpc-ecosystem/grpc-gateway/v2 v2.23.0 h1:ad0vkEBuk23VJzZR9nkLVG0YAoN9coASF1GusYX6AlU= 24 | github.com/grpc-ecosystem/grpc-gateway/v2 v2.23.0/go.mod h1:igFoXX2ELCW06bol23DWPB5BEWfZISOzSP5K2sbLea0= 25 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 26 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 27 | github.com/sagikazarmark/dagx v0.1.0 h1:5UXEMZagAfQ1HDKYMKaea97xGWSPMZX0UJih9+Dy0cs= 28 | github.com/sagikazarmark/dagx v0.1.0/go.mod h1:JXN8/8GnRtiYGRbFI3UzyiUnqHzy8D+6eppQWZIRLSo= 29 | github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8= 30 | github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I= 31 | github.com/sosodev/duration v1.3.1 h1:qtHBDMQ6lvMQsL15g4aopM4HEfOaYuhWBw3NPTtlqq4= 32 | github.com/sosodev/duration v1.3.1/go.mod h1:RQIBBX0+fMLc/D9+Jb/fwvVmo0eZvDDEERAikUR6SDg= 33 | github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= 34 | github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= 35 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 36 | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= 37 | github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= 38 | github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= 39 | github.com/vektah/gqlparser/v2 v2.5.23 h1:PurJ9wpgEVB7tty1seRUwkIDa/QH5RzkzraiKIjKLfA= 40 | github.com/vektah/gqlparser/v2 v2.5.23/go.mod h1:D1/VCZtV3LPnQrcPBeR/q5jkSQIPti0uYCP/RI0gIeo= 41 | go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= 42 | go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= 43 | go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY= 44 | go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI= 45 | go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.8.0 h1:WzNab7hOOLzdDF/EoWCt4glhrbMPVMOO5JYTmpz36Ls= 46 | go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.8.0/go.mod h1:hKvJwTzJdp90Vh7p6q/9PAOd55dI6WA6sWj62a/JvSs= 47 | go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.8.0 h1:S+LdBGiQXtJdowoJoQPEtI52syEP/JYBUpjO49EQhV8= 48 | go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.8.0/go.mod h1:5KXybFvPGds3QinJWQT7pmXf+TN5YIa7CNYObWRkj50= 49 | go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.32.0 h1:j7ZSD+5yn+lo3sGV69nW04rRR0jhYnBwjuX3r0HvnK0= 50 | go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.32.0/go.mod h1:WXbYJTUaZXAbYd8lbgGuvih0yuCfOFC5RJoYnoLcGz8= 51 | go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.32.0 h1:t/Qur3vKSkUCcDVaSumWF2PKHt85pc7fRvFuoVT8qFU= 52 | go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.32.0/go.mod h1:Rl61tySSdcOJWoEgYZVtmnKdA0GeKrSqkHC1t+91CH8= 53 | go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.32.0 h1:IJFEoHiytixx8cMiVAO+GmHR6Frwu+u5Ur8njpFO6Ac= 54 | go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.32.0/go.mod h1:3rHrKNtLIoS0oZwkY2vxi+oJcwFRWdtUyRII+so45p8= 55 | go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.32.0 h1:9kV11HXBHZAvuPUZxmMWrH8hZn/6UnHX4K0mu36vNsU= 56 | go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.32.0/go.mod h1:JyA0FHXe22E1NeNiHmVp7kFHglnexDQ7uRWDiiJ1hKQ= 57 | go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.32.0 h1:cMyu9O88joYEaI47CnQkxO1XZdpoTF9fEnW2duIddhw= 58 | go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.32.0/go.mod h1:6Am3rn7P9TVVeXYG+wtcGE7IE1tsQ+bP3AuWcKt/gOI= 59 | go.opentelemetry.io/otel/log v0.8.0 h1:egZ8vV5atrUWUbnSsHn6vB8R21G2wrKqNiDt3iWertk= 60 | go.opentelemetry.io/otel/log v0.8.0/go.mod h1:M9qvDdUTRCopJcGRKg57+JSQ9LgLBrwwfC32epk5NX8= 61 | go.opentelemetry.io/otel/metric v1.34.0 h1:+eTR3U0MyfWjRDhmFMxe2SsW64QrZ84AOhvqS7Y+PoQ= 62 | go.opentelemetry.io/otel/metric v1.34.0/go.mod h1:CEDrp0fy2D0MvkXE+dPV7cMi8tWZwX3dmaIhwPOaqHE= 63 | go.opentelemetry.io/otel/sdk v1.34.0 h1:95zS4k/2GOy069d321O8jWgYsW3MzVV+KuSPKp7Wr1A= 64 | go.opentelemetry.io/otel/sdk v1.34.0/go.mod h1:0e/pNiaMAqaykJGKbi+tSjWfNNHMTxoC9qANsCzbyxU= 65 | go.opentelemetry.io/otel/sdk/log v0.8.0 h1:zg7GUYXqxk1jnGF/dTdLPrK06xJdrXgqgFLnI4Crxvs= 66 | go.opentelemetry.io/otel/sdk/log v0.8.0/go.mod h1:50iXr0UVwQrYS45KbruFrEt4LvAdCaWWgIrsN3ZQggo= 67 | go.opentelemetry.io/otel/sdk/metric v1.34.0 h1:5CeK9ujjbFVL5c1PhLuStg1wxA7vQv7ce1EK0Gyvahk= 68 | go.opentelemetry.io/otel/sdk/metric v1.34.0/go.mod h1:jQ/r8Ze28zRKoNRdkjCZxfs6YvBTG1+YIqyFVFYec5w= 69 | go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k= 70 | go.opentelemetry.io/otel/trace v1.34.0/go.mod h1:Svm7lSjQD7kG7KJ/MUHPVXSDGz2OX4h0M2jHBhmSfRE= 71 | go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0= 72 | go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8= 73 | go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= 74 | go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= 75 | go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= 76 | go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= 77 | go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI= 78 | go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ= 79 | golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8= 80 | golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= 81 | golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw= 82 | golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= 83 | golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= 84 | golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= 85 | golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= 86 | golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= 87 | google.golang.org/genproto/googleapis/api v0.0.0-20250106144421-5f5ef82da422 h1:GVIKPyP/kLIyVOgOnTwFOrvQaQUzOzGMCxgFUOEmm24= 88 | google.golang.org/genproto/googleapis/api v0.0.0-20250106144421-5f5ef82da422/go.mod h1:b6h1vNKhxaSoEI+5jc3PJUCustfli/mRab7295pY7rw= 89 | google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f h1:OxYkA3wjPsZyBylwymxSHa7ViiW1Sml4ToBrncvFehI= 90 | google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f/go.mod h1:+2Yz8+CLJbIfL9z73EW45avw8Lmge3xVElCP9zEKi50= 91 | google.golang.org/grpc v1.71.0 h1:kF77BGdPTQ4/JZWMlb9VpJ5pa25aqvVqogsxNHHdeBg= 92 | google.golang.org/grpc v1.71.0/go.mod h1:H0GRtasmQOh9LkFoCPDu3ZrwUtD1YGE+b2vYBYd/8Ec= 93 | google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= 94 | google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= 95 | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= 96 | gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 97 | -------------------------------------------------------------------------------- /.dagger/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/sagikazarmark/dagx/pipeline" 7 | 8 | "github.com/sagikazarmark/caddy-fs-s3/.dagger/internal/dagger" 9 | ) 10 | 11 | type CaddyFsS3 struct { 12 | // Project source directory 13 | // 14 | // +private 15 | Source *dagger.Directory 16 | } 17 | 18 | func New( 19 | // Project source directory. 20 | // 21 | // +defaultPath="/" 22 | // +ignore=[".devenv", ".direnv", ".github"] 23 | source *dagger.Directory, 24 | ) *CaddyFsS3 { 25 | return &CaddyFsS3{ 26 | Source: source, 27 | } 28 | } 29 | 30 | var supportedGoVersions = []string{"1.24"} 31 | 32 | func (m *CaddyFsS3) Check(ctx context.Context) error { 33 | p := pipeline.New(ctx) 34 | 35 | for _, goVersion := range supportedGoVersions { 36 | pipeline.AddSyncStep(p, m.Build(goVersion)) 37 | } 38 | 39 | pipeline.AddSyncStep(p, m.Test()) 40 | pipeline.AddSyncStep(p, m.Lint()) 41 | 42 | return pipeline.Run(p) 43 | } 44 | 45 | func (m *CaddyFsS3) Build( 46 | // Go version to use. 47 | // 48 | // +optional 49 | goVersion string, 50 | ) *dagger.Container { 51 | if goVersion == "" { 52 | goVersion = defaultGoVersion 53 | } 54 | 55 | return dag.Xcaddy(dagger.XcaddyOpts{ 56 | GoVersion: goVersion, 57 | }).Build(). 58 | Plugin("github.com/sagikazarmark/caddy-fs-s3", dagger.XcaddyBuildPluginOpts{Replacement: m.Source}). 59 | Container() 60 | } 61 | 62 | func (m *CaddyFsS3) Test() *dagger.Container { 63 | return dag.Go(dagger.GoOpts{ 64 | Version: defaultGoVersion, 65 | }). 66 | WithSource(m.Source). 67 | Exec([]string{"go", "test", "-race", "-v", "./..."}) 68 | } 69 | 70 | // TODO: add e2e test 71 | func (m *CaddyFsS3) Run() *dagger.Service { 72 | return m.Build(""). 73 | WithEnvVariable("AWS_ACCESS_KEY_ID", "admin"). 74 | WithEnvVariable("AWS_SECRET_ACCESS_KEY", "admin1234"). 75 | WithServiceBinding("minio", minio()). 76 | WithMountedFile("/etc/caddy/Caddyfile", m.Source.File("Caddyfile")). 77 | WithExposedPort(80). 78 | AsService() 79 | } 80 | 81 | func minio() *dagger.Service { 82 | return dag.Container(). 83 | From("quay.io/minio/minio"). 84 | WithEnvVariable("MINIO_ROOT_USER", "admin"). 85 | WithEnvVariable("MINIO_ROOT_PASSWORD", "admin1234"). 86 | WithExposedPort(9000). 87 | WithExposedPort(9090). 88 | AsService(dagger.ContainerAsServiceOpts{ 89 | Args: []string{"server", "/data", "--console-address", ":9090"}, 90 | UseEntrypoint: true, 91 | }) 92 | } 93 | 94 | func (m *CaddyFsS3) Lint() *dagger.Container { 95 | return dag.GolangciLint(dagger.GolangciLintOpts{ 96 | Version: golangciLintVersion, 97 | GoVersion: defaultGoVersion, 98 | }). 99 | Run(m.Source, dagger.GolangciLintRunOpts{Verbose: true}) 100 | } 101 | -------------------------------------------------------------------------------- /.dagger/versions.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | const ( 4 | defaultGoVersion = "1.24.2" 5 | 6 | golangciLintVersion = "v2.1.1" 7 | ) 8 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | end_of_line = lf 6 | indent_size = 4 7 | indent_style = space 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [{Makefile,*.mk}] 12 | indent_style = tab 13 | 14 | [*.nix] 15 | indent_size = 2 16 | 17 | [*.go] 18 | indent_style = tab 19 | 20 | [.golangci.yaml] 21 | indent_size = 2 22 | -------------------------------------------------------------------------------- /.envrc: -------------------------------------------------------------------------------- 1 | if ! has nix_direnv_version || ! nix_direnv_version 3.0.4; then 2 | source_url "https://raw.githubusercontent.com/nix-community/nix-direnv/3.0.4/direnvrc" "sha256-DzlYZ33mWF/Gs8DDeyjr8mnVmQGx7ASYqA5WlxwvBG4=" 3 | fi 4 | use flake . --impure 5 | -------------------------------------------------------------------------------- /.github/.editorconfig: -------------------------------------------------------------------------------- 1 | [{*.yaml,*.yml}] 2 | indent_size = 2 3 | -------------------------------------------------------------------------------- /.github/dependabot.yaml: -------------------------------------------------------------------------------- 1 | version: 2 2 | 3 | updates: 4 | - package-ecosystem: gomod 5 | directory: / 6 | schedule: 7 | interval: daily 8 | groups: 9 | aws: 10 | patterns: 11 | - "github.com/aws/aws-sdk-go-v2" 12 | - "github.com/aws/aws-sdk-go-v2/*" 13 | 14 | - package-ecosystem: github-actions 15 | directory: / 16 | schedule: 17 | interval: daily 18 | -------------------------------------------------------------------------------- /.github/workflows/analysis-scorecard.yaml: -------------------------------------------------------------------------------- 1 | name: OpenSSF Scorecard 2 | 3 | on: 4 | branch_protection_rule: 5 | push: 6 | branches: [main] 7 | schedule: 8 | - cron: "30 0 * * 5" 9 | 10 | permissions: 11 | contents: read 12 | 13 | jobs: 14 | analyze: 15 | name: Analyze 16 | runs-on: ubuntu-latest 17 | 18 | permissions: 19 | actions: read 20 | contents: read 21 | id-token: write 22 | security-events: write 23 | 24 | steps: 25 | - name: Checkout repository 26 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 27 | with: 28 | persist-credentials: false 29 | 30 | - name: Run analysis 31 | uses: ossf/scorecard-action@f49aabe0b5af0936a0987cfb85d86b75731b0186 # v2.4.1 32 | with: 33 | results_file: results.sarif 34 | results_format: sarif 35 | publish_results: true 36 | 37 | - name: Upload results as artifact 38 | uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 39 | with: 40 | name: OpenSSF Scorecard results 41 | path: results.sarif 42 | retention-days: 5 43 | 44 | - name: Upload results to GitHub Security tab 45 | uses: github/codeql-action/upload-sarif@28deaeda66b76a05916b6923827895f2b14ab387 # v3.28.16 46 | with: 47 | sarif_file: results.sarif 48 | -------------------------------------------------------------------------------- /.github/workflows/ci.yaml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: [main] 6 | pull_request: 7 | 8 | permissions: 9 | contents: read 10 | 11 | env: 12 | DAGGER_VERSION: 0.18.3 13 | 14 | jobs: 15 | build: 16 | name: Build 17 | runs-on: ubuntu-latest 18 | 19 | strategy: 20 | fail-fast: false 21 | matrix: 22 | go: ["1.24"] 23 | 24 | steps: 25 | - name: Checkout repository 26 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 27 | 28 | - name: Run pipeline 29 | uses: dagger/dagger-for-github@e47aba410ef9bb9ed81a4d2a97df31061e5e842e # v8.0.0 30 | with: 31 | verb: call 32 | args: build --go-version ${{ matrix.go }} 33 | version: ${{ env.DAGGER_VERSION }} 34 | test: 35 | name: Test 36 | runs-on: ubuntu-latest 37 | 38 | steps: 39 | - name: Checkout repository 40 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 41 | 42 | - name: Run pipeline 43 | uses: dagger/dagger-for-github@e47aba410ef9bb9ed81a4d2a97df31061e5e842e # v8.0.0 44 | with: 45 | verb: call 46 | args: test 47 | version: ${{ env.DAGGER_VERSION }} 48 | 49 | lint: 50 | name: Lint 51 | runs-on: ubuntu-latest 52 | 53 | steps: 54 | - name: Checkout repository 55 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 56 | 57 | - name: Run pipeline 58 | uses: dagger/dagger-for-github@e47aba410ef9bb9ed81a4d2a97df31061e5e842e # v8.0.0 59 | with: 60 | verb: call 61 | args: lint 62 | version: ${{ env.DAGGER_VERSION }} 63 | 64 | dependency-review: 65 | name: Dependency review 66 | runs-on: ubuntu-latest 67 | if: github.event_name == 'pull_request' 68 | 69 | steps: 70 | - name: Checkout repository 71 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 72 | 73 | - name: Dependency Review 74 | uses: actions/dependency-review-action@ce3cf9537a52e8119d91fd484ab5b8a807627bf8 # v4.6.0 75 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.devenv/ 2 | /.direnv/ 3 | /.task/ 4 | /bin/ 5 | /build/ 6 | /tmp/ 7 | /var/ 8 | /vendor/ 9 | -------------------------------------------------------------------------------- /.golangci.yaml: -------------------------------------------------------------------------------- 1 | version: "2" 2 | 3 | run: 4 | timeout: 10m 5 | 6 | linters: 7 | enable: 8 | - errcheck 9 | - govet 10 | - ineffassign 11 | - misspell 12 | - nolintlint 13 | - revive 14 | - staticcheck 15 | - unused 16 | 17 | settings: 18 | misspell: 19 | locale: US 20 | nolintlint: 21 | allow-unused: false # report any unused nolint directives 22 | require-specific: false # don't require nolint directives to be specific about which linter is being skipped 23 | 24 | formatters: 25 | enable: 26 | - gci 27 | - gofmt 28 | - gofumpt 29 | - goimports 30 | - golines 31 | 32 | settings: 33 | gci: 34 | sections: 35 | - standard 36 | - default 37 | - localmodule 38 | -------------------------------------------------------------------------------- /Caddyfile: -------------------------------------------------------------------------------- 1 | { 2 | auto_https off 3 | 4 | filesystem my-s3-fs s3 { 5 | bucket "default" 6 | region "us-east-1" 7 | endpoint "http://localhost:9000" 8 | use_path_style 9 | } 10 | } 11 | 12 | localhost:80 13 | 14 | log { 15 | level DEBUG 16 | } 17 | 18 | route /assets/* { 19 | uri strip_prefix /assets 20 | 21 | file_server { 22 | fs my-s3-fs 23 | pass_thru 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2022 Márk Sági-Kazár 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is furnished 8 | to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Caddy FS module for AWS S3 2 | 3 | ![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/sagikazarmark/caddy-fs-s3/ci.yaml?style=flat-square) 4 | ![Caddy Version](https://img.shields.io/badge/caddy%20version-%3E=2.10.x-61CFDD.svg?style=flat-square) 5 | ![GitHub go.mod Go version](https://img.shields.io/github/go-mod/go-version/sagikazarmark/caddy-fs-s3?style=flat-square&color=61CFDD) 6 | [![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/sagikazarmark/caddy-fs-s3/badge?style=flat-square)](https://deps.dev/go/github.com%252Fsagikazarmark%252Fcaddy-fs-s3) 7 | 8 | ## Installation 9 | 10 | Build Caddy using [xcaddy](https://github.com/caddyserver/xcaddy): 11 | 12 | ```shell 13 | xcaddy build --with github.com/sagikazarmark/caddy-fs-s3 14 | ``` 15 | 16 | ## Usage 17 | 18 | ```caddyfile 19 | { 20 | filesystem my-s3-fs s3 { 21 | bucket mybucket 22 | region us-east-1 23 | 24 | # endpoint 25 | # profile 26 | # use_path_style 27 | } 28 | } 29 | 30 | example.com { 31 | file_server { 32 | fs my-s3-fs 33 | } 34 | } 35 | ``` 36 | 37 | > [!NOTE] 38 | > For a full parameter reference, check out the module [documentation page](https://caddyserver.com/docs/modules/caddy.fs.s3). 39 | 40 | ### Authentication 41 | 42 | The module uses the AWS SDK [default credential chain](https://docs.aws.amazon.com/sdkref/latest/guide/standardized-credentials.html) to find valid credentials. 43 | 44 | The easiest way to try the module is setting [static credentials](https://docs.aws.amazon.com/sdkref/latest/guide/feature-static-credentials.html) either in your AWS credentials file or as environment variables: 45 | 46 | ```shell 47 | export AWS_ACCESS_KEY_ID=... 48 | export AWS_SECRET_ACCESS_KEY=... 49 | ``` 50 | 51 | Caddy will pick up the credentials automatically. 52 | 53 | ## Development 54 | 55 | **For an optimal developer experience, it is recommended to install [Nix](https://nixos.org/download.html) and [direnv](https://direnv.net/docs/installation.html).** 56 | 57 | Run Caddy with the following command: 58 | 59 | ```shell 60 | just run up --ports 8080:80 61 | ``` 62 | 63 | When all coding and testing is done, please run the test suite: 64 | 65 | ```shell 66 | just check 67 | ``` 68 | 69 | ## License 70 | 71 | The project is licensed under the [MIT License](LICENSE). 72 | -------------------------------------------------------------------------------- /Taskfile.yaml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | 3 | vars: 4 | BUILD_DIR: build 5 | 6 | tasks: 7 | build: 8 | cmds: 9 | - cmd: mkdir -p {{.BUILD_DIR}} 10 | silent: true 11 | - xcaddy build --output {{.BUILD_DIR}}/caddy --with github.com/sagikazarmark/caddy-fs-s3=. 12 | sources: 13 | - "*.go" 14 | - "**/*.go" 15 | 16 | run: 17 | deps: [build] 18 | cmds: 19 | - "{{.BUILD_DIR}}/caddy run --watch" 20 | env: 21 | AWS_ACCESS_KEY_ID: admin 22 | AWS_SECRET_ACCESS_KEY: admin1234 23 | 24 | check: 25 | deps: [build] 26 | cmds: 27 | - task: lint 28 | - task: test 29 | 30 | lint: 31 | cmds: 32 | - golangci-lint run --timeout 10m $LINT_ARGS 33 | 34 | fix: 35 | cmds: 36 | - golangci-lint run --fix 37 | 38 | test: 39 | cmds: 40 | - cmd: mkdir -p {{.BUILD_DIR}} 41 | silent: true 42 | - go test 43 | -------------------------------------------------------------------------------- /dagger.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "caddy-fs-s3", 3 | "engineVersion": "v0.18.3", 4 | "sdk": { 5 | "source": "go" 6 | }, 7 | "dependencies": [ 8 | { 9 | "name": "go", 10 | "source": "github.com/sagikazarmark/daggerverse/go@go/v0.9.0", 11 | "pin": "d9ba06776c4c1ccf6f329bd862b9b439c4582ab6" 12 | }, 13 | { 14 | "name": "golangci-lint", 15 | "source": "github.com/sagikazarmark/daggerverse/golangci-lint@golangci-lint/v0.9.0", 16 | "pin": "e6c14178bcaaff9e102e2a89173ca31479b80629" 17 | }, 18 | { 19 | "name": "xcaddy", 20 | "source": "github.com/sagikazarmark/daggerverse/xcaddy@xcaddy/v0.6.0", 21 | "pin": "ceffda4aebd349a24fc00e591b4ed9b801535b65" 22 | } 23 | ], 24 | "source": ".dagger" 25 | } 26 | -------------------------------------------------------------------------------- /docker-compose.yaml: -------------------------------------------------------------------------------- 1 | version: "3.10" 2 | 3 | services: 4 | minio: 5 | image: quay.io/minio/minio 6 | command: server /data --console-address ":9090" 7 | environment: 8 | MINIO_ROOT_USER: admin 9 | MINIO_ROOT_PASSWORD: admin1234 10 | volumes: 11 | - ./var/minio:/data 12 | ports: 13 | - 127.0.0.1:9000:9000 14 | - 127.0.0.1:9090:9090 15 | -------------------------------------------------------------------------------- /flake.lock: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "cachix": { 4 | "inputs": { 5 | "devenv": [ 6 | "devenv" 7 | ], 8 | "flake-compat": [ 9 | "devenv" 10 | ], 11 | "git-hooks": [ 12 | "devenv" 13 | ], 14 | "nixpkgs": "nixpkgs" 15 | }, 16 | "locked": { 17 | "lastModified": 1742042642, 18 | "narHash": "sha256-D0gP8srrX0qj+wNYNPdtVJsQuFzIng3q43thnHXQ/es=", 19 | "owner": "cachix", 20 | "repo": "cachix", 21 | "rev": "a624d3eaf4b1d225f918de8543ed739f2f574203", 22 | "type": "github" 23 | }, 24 | "original": { 25 | "owner": "cachix", 26 | "ref": "latest", 27 | "repo": "cachix", 28 | "type": "github" 29 | } 30 | }, 31 | "dagger": { 32 | "inputs": { 33 | "nixpkgs": [ 34 | "nixpkgs" 35 | ] 36 | }, 37 | "locked": { 38 | "lastModified": 1744640986, 39 | "narHash": "sha256-u+cUMJjfpw7HTbp/nXlD8ib+gmlvgrgeRxM8B5/JiHM=", 40 | "owner": "dagger", 41 | "repo": "nix", 42 | "rev": "0b0d25ff7f0e951c402c04ccab9d62b9e7da30cb", 43 | "type": "github" 44 | }, 45 | "original": { 46 | "owner": "dagger", 47 | "repo": "nix", 48 | "type": "github" 49 | } 50 | }, 51 | "devenv": { 52 | "inputs": { 53 | "cachix": "cachix", 54 | "flake-compat": "flake-compat", 55 | "git-hooks": "git-hooks", 56 | "nix": "nix", 57 | "nixpkgs": "nixpkgs_3" 58 | }, 59 | "locked": { 60 | "lastModified": 1744588088, 61 | "narHash": "sha256-jymEVhRPzvzVP8XrXJcnVFUmle/FKLZIfSq+9EiobQE=", 62 | "owner": "cachix", 63 | "repo": "devenv", 64 | "rev": "1e6c06a058dae3791c0303eb99636cee9605c8d9", 65 | "type": "github" 66 | }, 67 | "original": { 68 | "owner": "cachix", 69 | "repo": "devenv", 70 | "type": "github" 71 | } 72 | }, 73 | "flake-compat": { 74 | "flake": false, 75 | "locked": { 76 | "lastModified": 1733328505, 77 | "narHash": "sha256-NeCCThCEP3eCl2l/+27kNNK7QrwZB1IJCrXfrbv5oqU=", 78 | "owner": "edolstra", 79 | "repo": "flake-compat", 80 | "rev": "ff81ac966bb2cae68946d5ed5fc4994f96d0ffec", 81 | "type": "github" 82 | }, 83 | "original": { 84 | "owner": "edolstra", 85 | "repo": "flake-compat", 86 | "type": "github" 87 | } 88 | }, 89 | "flake-parts": { 90 | "inputs": { 91 | "nixpkgs-lib": [ 92 | "devenv", 93 | "nix", 94 | "nixpkgs" 95 | ] 96 | }, 97 | "locked": { 98 | "lastModified": 1712014858, 99 | "narHash": "sha256-sB4SWl2lX95bExY2gMFG5HIzvva5AVMJd4Igm+GpZNw=", 100 | "owner": "hercules-ci", 101 | "repo": "flake-parts", 102 | "rev": "9126214d0a59633752a136528f5f3b9aa8565b7d", 103 | "type": "github" 104 | }, 105 | "original": { 106 | "owner": "hercules-ci", 107 | "repo": "flake-parts", 108 | "type": "github" 109 | } 110 | }, 111 | "flake-parts_2": { 112 | "inputs": { 113 | "nixpkgs-lib": "nixpkgs-lib" 114 | }, 115 | "locked": { 116 | "lastModified": 1743550720, 117 | "narHash": "sha256-hIshGgKZCgWh6AYJpJmRgFdR3WUbkY04o82X05xqQiY=", 118 | "owner": "hercules-ci", 119 | "repo": "flake-parts", 120 | "rev": "c621e8422220273271f52058f618c94e405bb0f5", 121 | "type": "github" 122 | }, 123 | "original": { 124 | "owner": "hercules-ci", 125 | "repo": "flake-parts", 126 | "type": "github" 127 | } 128 | }, 129 | "git-hooks": { 130 | "inputs": { 131 | "flake-compat": [ 132 | "devenv" 133 | ], 134 | "gitignore": "gitignore", 135 | "nixpkgs": [ 136 | "devenv", 137 | "nixpkgs" 138 | ] 139 | }, 140 | "locked": { 141 | "lastModified": 1742649964, 142 | "narHash": "sha256-DwOTp7nvfi8mRfuL1escHDXabVXFGT1VlPD1JHrtrco=", 143 | "owner": "cachix", 144 | "repo": "git-hooks.nix", 145 | "rev": "dcf5072734cb576d2b0c59b2ac44f5050b5eac82", 146 | "type": "github" 147 | }, 148 | "original": { 149 | "owner": "cachix", 150 | "repo": "git-hooks.nix", 151 | "type": "github" 152 | } 153 | }, 154 | "gitignore": { 155 | "inputs": { 156 | "nixpkgs": [ 157 | "devenv", 158 | "git-hooks", 159 | "nixpkgs" 160 | ] 161 | }, 162 | "locked": { 163 | "lastModified": 1709087332, 164 | "narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=", 165 | "owner": "hercules-ci", 166 | "repo": "gitignore.nix", 167 | "rev": "637db329424fd7e46cf4185293b9cc8c88c95394", 168 | "type": "github" 169 | }, 170 | "original": { 171 | "owner": "hercules-ci", 172 | "repo": "gitignore.nix", 173 | "type": "github" 174 | } 175 | }, 176 | "libgit2": { 177 | "flake": false, 178 | "locked": { 179 | "lastModified": 1697646580, 180 | "narHash": "sha256-oX4Z3S9WtJlwvj0uH9HlYcWv+x1hqp8mhXl7HsLu2f0=", 181 | "owner": "libgit2", 182 | "repo": "libgit2", 183 | "rev": "45fd9ed7ae1a9b74b957ef4f337bc3c8b3df01b5", 184 | "type": "github" 185 | }, 186 | "original": { 187 | "owner": "libgit2", 188 | "repo": "libgit2", 189 | "type": "github" 190 | } 191 | }, 192 | "nix": { 193 | "inputs": { 194 | "flake-compat": [ 195 | "devenv" 196 | ], 197 | "flake-parts": "flake-parts", 198 | "libgit2": "libgit2", 199 | "nixpkgs": "nixpkgs_2", 200 | "nixpkgs-23-11": [ 201 | "devenv" 202 | ], 203 | "nixpkgs-regression": [ 204 | "devenv" 205 | ], 206 | "pre-commit-hooks": [ 207 | "devenv" 208 | ] 209 | }, 210 | "locked": { 211 | "lastModified": 1741798497, 212 | "narHash": "sha256-E3j+3MoY8Y96mG1dUIiLFm2tZmNbRvSiyN7CrSKuAVg=", 213 | "owner": "domenkozar", 214 | "repo": "nix", 215 | "rev": "f3f44b2baaf6c4c6e179de8cbb1cc6db031083cd", 216 | "type": "github" 217 | }, 218 | "original": { 219 | "owner": "domenkozar", 220 | "ref": "devenv-2.24", 221 | "repo": "nix", 222 | "type": "github" 223 | } 224 | }, 225 | "nixpkgs": { 226 | "locked": { 227 | "lastModified": 1733212471, 228 | "narHash": "sha256-M1+uCoV5igihRfcUKrr1riygbe73/dzNnzPsmaLCmpo=", 229 | "owner": "NixOS", 230 | "repo": "nixpkgs", 231 | "rev": "55d15ad12a74eb7d4646254e13638ad0c4128776", 232 | "type": "github" 233 | }, 234 | "original": { 235 | "owner": "NixOS", 236 | "ref": "nixos-unstable", 237 | "repo": "nixpkgs", 238 | "type": "github" 239 | } 240 | }, 241 | "nixpkgs-lib": { 242 | "locked": { 243 | "lastModified": 1743296961, 244 | "narHash": "sha256-b1EdN3cULCqtorQ4QeWgLMrd5ZGOjLSLemfa00heasc=", 245 | "owner": "nix-community", 246 | "repo": "nixpkgs.lib", 247 | "rev": "e4822aea2a6d1cdd36653c134cacfd64c97ff4fa", 248 | "type": "github" 249 | }, 250 | "original": { 251 | "owner": "nix-community", 252 | "repo": "nixpkgs.lib", 253 | "type": "github" 254 | } 255 | }, 256 | "nixpkgs_2": { 257 | "locked": { 258 | "lastModified": 1717432640, 259 | "narHash": "sha256-+f9c4/ZX5MWDOuB1rKoWj+lBNm0z0rs4CK47HBLxy1o=", 260 | "owner": "NixOS", 261 | "repo": "nixpkgs", 262 | "rev": "88269ab3044128b7c2f4c7d68448b2fb50456870", 263 | "type": "github" 264 | }, 265 | "original": { 266 | "owner": "NixOS", 267 | "ref": "release-24.05", 268 | "repo": "nixpkgs", 269 | "type": "github" 270 | } 271 | }, 272 | "nixpkgs_3": { 273 | "locked": { 274 | "lastModified": 1733477122, 275 | "narHash": "sha256-qamMCz5mNpQmgBwc8SB5tVMlD5sbwVIToVZtSxMph9s=", 276 | "owner": "cachix", 277 | "repo": "devenv-nixpkgs", 278 | "rev": "7bd9e84d0452f6d2e63b6e6da29fe73fac951857", 279 | "type": "github" 280 | }, 281 | "original": { 282 | "owner": "cachix", 283 | "ref": "rolling", 284 | "repo": "devenv-nixpkgs", 285 | "type": "github" 286 | } 287 | }, 288 | "nixpkgs_4": { 289 | "locked": { 290 | "lastModified": 1744536153, 291 | "narHash": "sha256-awS2zRgF4uTwrOKwwiJcByDzDOdo3Q1rPZbiHQg/N38=", 292 | "owner": "NixOS", 293 | "repo": "nixpkgs", 294 | "rev": "18dd725c29603f582cf1900e0d25f9f1063dbf11", 295 | "type": "github" 296 | }, 297 | "original": { 298 | "owner": "NixOS", 299 | "ref": "nixpkgs-unstable", 300 | "repo": "nixpkgs", 301 | "type": "github" 302 | } 303 | }, 304 | "root": { 305 | "inputs": { 306 | "dagger": "dagger", 307 | "devenv": "devenv", 308 | "flake-parts": "flake-parts_2", 309 | "nixpkgs": "nixpkgs_4" 310 | } 311 | } 312 | }, 313 | "root": "root", 314 | "version": 7 315 | } 316 | -------------------------------------------------------------------------------- /flake.nix: -------------------------------------------------------------------------------- 1 | { 2 | inputs = { 3 | nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; 4 | flake-parts.url = "github:hercules-ci/flake-parts"; 5 | devenv.url = "github:cachix/devenv"; 6 | dagger.url = "github:dagger/nix"; 7 | dagger.inputs.nixpkgs.follows = "nixpkgs"; 8 | }; 9 | 10 | outputs = 11 | inputs@{ flake-parts, ... }: 12 | flake-parts.lib.mkFlake { inherit inputs; } { 13 | imports = [ 14 | inputs.devenv.flakeModule 15 | ]; 16 | 17 | systems = [ 18 | "x86_64-linux" 19 | "x86_64-darwin" 20 | "aarch64-darwin" 21 | ]; 22 | 23 | perSystem = 24 | { 25 | inputs', 26 | pkgs, 27 | system, 28 | ... 29 | }: 30 | rec { 31 | _module.args.pkgs = import inputs.nixpkgs { 32 | inherit system; 33 | 34 | overlays = [ 35 | (final: prev: { 36 | dagger = inputs'.dagger.packages.dagger; 37 | }) 38 | ]; 39 | }; 40 | 41 | devenv.shells = { 42 | default = { 43 | languages = { 44 | go.enable = true; 45 | }; 46 | 47 | packages = with pkgs; [ 48 | git 49 | dagger 50 | just 51 | xcaddy 52 | golangci-lint 53 | ]; 54 | 55 | # https://github.com/cachix/devenv/issues/528#issuecomment-1556108767 56 | containers = pkgs.lib.mkForce { }; 57 | }; 58 | 59 | ci = devenv.shells.default; 60 | }; 61 | }; 62 | }; 63 | } 64 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/sagikazarmark/caddy-fs-s3 2 | 3 | go 1.24.0 4 | 5 | require ( 6 | github.com/aws/aws-sdk-go-v2 v1.36.3 7 | github.com/aws/aws-sdk-go-v2/config v1.29.14 8 | github.com/aws/aws-sdk-go-v2/service/s3 v1.79.3 9 | github.com/caddyserver/caddy/v2 v2.10.0 10 | github.com/jszwec/s3fs/v2 v2.0.0 11 | ) 12 | 13 | require ( 14 | github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.10 // indirect 15 | github.com/aws/aws-sdk-go-v2/credentials v1.17.67 // indirect 16 | github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.30 // indirect 17 | github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.34 // indirect 18 | github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.34 // indirect 19 | github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 // indirect 20 | github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.34 // indirect 21 | github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.3 // indirect 22 | github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.7.1 // indirect 23 | github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.15 // indirect 24 | github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.15 // indirect 25 | github.com/aws/aws-sdk-go-v2/service/sso v1.25.3 // indirect 26 | github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.1 // indirect 27 | github.com/aws/aws-sdk-go-v2/service/sts v1.33.19 // indirect 28 | github.com/aws/smithy-go v1.22.2 // indirect 29 | github.com/beorn7/perks v1.0.1 // indirect 30 | github.com/caddyserver/certmagic v0.23.0 // indirect 31 | github.com/caddyserver/zerossl v0.1.3 // indirect 32 | github.com/cespare/xxhash/v2 v2.3.0 // indirect 33 | github.com/francoispqt/gojay v1.2.13 // indirect 34 | github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect 35 | github.com/google/pprof v0.0.0-20231212022811-ec68065c825e // indirect 36 | github.com/google/uuid v1.6.0 // indirect 37 | github.com/klauspost/cpuid/v2 v2.2.10 // indirect 38 | github.com/libdns/libdns v1.0.0-beta.1 // indirect 39 | github.com/mholt/acmez/v3 v3.1.2 // indirect 40 | github.com/miekg/dns v1.1.63 // indirect 41 | github.com/onsi/ginkgo/v2 v2.13.2 // indirect 42 | github.com/prometheus/client_golang v1.19.1 // indirect 43 | github.com/prometheus/client_model v0.5.0 // indirect 44 | github.com/prometheus/common v0.48.0 // indirect 45 | github.com/prometheus/procfs v0.12.0 // indirect 46 | github.com/quic-go/qpack v0.5.1 // indirect 47 | github.com/quic-go/quic-go v0.50.1 // indirect 48 | github.com/zeebo/blake3 v0.2.4 // indirect 49 | go.uber.org/mock v0.5.0 // indirect 50 | go.uber.org/multierr v1.11.0 // indirect 51 | go.uber.org/zap v1.27.0 // indirect 52 | go.uber.org/zap/exp v0.3.0 // indirect 53 | golang.org/x/crypto v0.36.0 // indirect 54 | golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 // indirect 55 | golang.org/x/mod v0.24.0 // indirect 56 | golang.org/x/net v0.38.0 // indirect 57 | golang.org/x/sync v0.12.0 // indirect 58 | golang.org/x/sys v0.31.0 // indirect 59 | golang.org/x/term v0.30.0 // indirect 60 | golang.org/x/text v0.23.0 // indirect 61 | golang.org/x/time v0.11.0 // indirect 62 | golang.org/x/tools v0.31.0 // indirect 63 | google.golang.org/protobuf v1.35.1 // indirect 64 | ) 65 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 2 | cloud.google.com/go v0.31.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 3 | cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 4 | cloud.google.com/go v0.37.0/go.mod h1:TS1dMSSfndXH133OKGwekG838Om/cQT0BUHV3HcBgoo= 5 | dmitri.shuralyov.com/app/changes v0.0.0-20180602232624-0a106ad413e3/go.mod h1:Yl+fi1br7+Rr3LqpNJf1/uxUdtRUV+Tnj0o93V2B9MU= 6 | dmitri.shuralyov.com/html/belt v0.0.0-20180602232347-f7d459c86be0/go.mod h1:JLBrvjyP0v+ecvNYvCpyZgu5/xkfAUhi6wJj28eUfSU= 7 | dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1:a1inKt/atXimZ4Mv927x+r7UpyzRUf4emIoiiSC2TN4= 8 | dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU= 9 | git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg= 10 | github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= 11 | github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= 12 | github.com/aws/aws-sdk-go-v2 v1.36.3 h1:mJoei2CxPutQVxaATCzDUjcZEjVRdpsiiXi2o38yqWM= 13 | github.com/aws/aws-sdk-go-v2 v1.36.3/go.mod h1:LLXuLpgzEbD766Z5ECcRmi8AzSwfZItDtmABVkRLGzg= 14 | github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.10 h1:zAybnyUQXIZ5mok5Jqwlf58/TFE7uvd3IAsa1aF9cXs= 15 | github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.10/go.mod h1:qqvMj6gHLR/EXWZw4ZbqlPbQUyenf4h82UQUlKc+l14= 16 | github.com/aws/aws-sdk-go-v2/config v1.29.14 h1:f+eEi/2cKCg9pqKBoAIwRGzVb70MRKqWX4dg1BDcSJM= 17 | github.com/aws/aws-sdk-go-v2/config v1.29.14/go.mod h1:wVPHWcIFv3WO89w0rE10gzf17ZYy+UVS1Geq8Iei34g= 18 | github.com/aws/aws-sdk-go-v2/credentials v1.17.67 h1:9KxtdcIA/5xPNQyZRgUSpYOE6j9Bc4+D7nZua0KGYOM= 19 | github.com/aws/aws-sdk-go-v2/credentials v1.17.67/go.mod h1:p3C44m+cfnbv763s52gCqrjaqyPikj9Sg47kUVaNZQQ= 20 | github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.30 h1:x793wxmUWVDhshP8WW2mlnXuFrO4cOd3HLBroh1paFw= 21 | github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.30/go.mod h1:Jpne2tDnYiFascUEs2AWHJL9Yp7A5ZVy3TNyxaAjD6M= 22 | github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.15.7 h1:FnLf60PtjXp8ZOzQfhJVsqF0OtYKQZWQfqOLshh8YXg= 23 | github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.15.7/go.mod h1:tDVvl8hyU6E9B8TrnNrZQEVkQlB8hjJwcgpPhgtlnNg= 24 | github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.34 h1:ZK5jHhnrioRkUNOc+hOgQKlUL5JeC3S6JgLxtQ+Rm0Q= 25 | github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.34/go.mod h1:p4VfIceZokChbA9FzMbRGz5OV+lekcVtHlPKEO0gSZY= 26 | github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.34 h1:SZwFm17ZUNNg5Np0ioo/gq8Mn6u9w19Mri8DnJ15Jf0= 27 | github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.34/go.mod h1:dFZsC0BLo346mvKQLWmoJxT+Sjp+qcVR1tRVHQGOH9Q= 28 | github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 h1:bIqFDwgGXXN1Kpp99pDOdKMTTb5d2KyU5X/BZxjOkRo= 29 | github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3/go.mod h1:H5O/EsxDWyU+LP/V8i5sm8cxoZgc2fdNR9bxlOFrQTo= 30 | github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.34 h1:ZNTqv4nIdE/DiBfUUfXcLZ/Spcuz+RjeziUtNJackkM= 31 | github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.34/go.mod h1:zf7Vcd1ViW7cPqYWEHLHJkS50X0JS2IKz9Cgaj6ugrs= 32 | github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.3 h1:eAh2A4b5IzM/lum78bZ590jy36+d/aFLgKF/4Vd1xPE= 33 | github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.3/go.mod h1:0yKJC/kb8sAnmlYa6Zs3QVYqaC8ug2AbnNChv5Ox3uA= 34 | github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.7.1 h1:4nm2G6A4pV9rdlWzGMPv4BNtQp22v1hg3yrtkYpeLl8= 35 | github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.7.1/go.mod h1:iu6FSzgt+M2/x3Dk8zhycdIcHjEFb36IS8HVUVFoMg0= 36 | github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.15 h1:dM9/92u2F1JbDaGooxTq18wmmFzbJRfXfVfy96/1CXM= 37 | github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.15/go.mod h1:SwFBy2vjtA0vZbjjaFtfN045boopadnoVPhu4Fv66vY= 38 | github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.15 h1:moLQUoVq91LiqT1nbvzDukyqAlCv89ZmwaHw/ZFlFZg= 39 | github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.15/go.mod h1:ZH34PJUc8ApjBIfgQCFvkWcUDBtl/WTD+uiYHjd8igA= 40 | github.com/aws/aws-sdk-go-v2/service/s3 v1.79.3 h1:BRXS0U76Z8wfF+bnkilA2QwpIch6URlm++yPUt9QPmQ= 41 | github.com/aws/aws-sdk-go-v2/service/s3 v1.79.3/go.mod h1:bNXKFFyaiVvWuR6O16h/I1724+aXe/tAkA9/QS01t5k= 42 | github.com/aws/aws-sdk-go-v2/service/sso v1.25.3 h1:1Gw+9ajCV1jogloEv1RRnvfRFia2cL6c9cuKV2Ps+G8= 43 | github.com/aws/aws-sdk-go-v2/service/sso v1.25.3/go.mod h1:qs4a9T5EMLl/Cajiw2TcbNt2UNo/Hqlyp+GiuG4CFDI= 44 | github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.1 h1:hXmVKytPfTy5axZ+fYbR5d0cFmC3JvwLm5kM83luako= 45 | github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.1/go.mod h1:MlYRNmYu/fGPoxBQVvBYr9nyr948aY/WLUvwBMBJubs= 46 | github.com/aws/aws-sdk-go-v2/service/sts v1.33.19 h1:1XuUZ8mYJw9B6lzAkXhqHlJd/XvaX32evhproijJEZY= 47 | github.com/aws/aws-sdk-go-v2/service/sts v1.33.19/go.mod h1:cQnB8CUnxbMU82JvlqjKR2HBOm3fe9pWorWBza6MBJ4= 48 | github.com/aws/smithy-go v1.22.2 h1:6D9hW43xKFrRx/tXXfAlIZc4JI+yQe6snnWcQyxSyLQ= 49 | github.com/aws/smithy-go v1.22.2/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg= 50 | github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= 51 | github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= 52 | github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= 53 | github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g= 54 | github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s= 55 | github.com/caddyserver/caddy/v2 v2.10.0 h1:fonubSaQKF1YANl8TXqGcn4IbIRUDdfAkpcsfI/vX5U= 56 | github.com/caddyserver/caddy/v2 v2.10.0/go.mod h1:q+dgBS3xtIJJGYI2H5Nyh9+4BvhQQ9yCGmECv4Ubdjo= 57 | github.com/caddyserver/certmagic v0.23.0 h1:CfpZ/50jMfG4+1J/u2LV6piJq4HOfO6ppOnOf7DkFEU= 58 | github.com/caddyserver/certmagic v0.23.0/go.mod h1:9mEZIWqqWoI+Gf+4Trh04MOVPD0tGSxtqsxg87hAIH4= 59 | github.com/caddyserver/zerossl v0.1.3 h1:onS+pxp3M8HnHpN5MMbOMyNjmTheJyWRaZYwn+YTAyA= 60 | github.com/caddyserver/zerossl v0.1.3/go.mod h1:CxA0acn7oEGO6//4rtrRjYgEoa4MFw/XofZnrYwGqG4= 61 | github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= 62 | github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= 63 | github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= 64 | github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= 65 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 66 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 67 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 68 | github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= 69 | github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= 70 | github.com/francoispqt/gojay v1.2.13 h1:d2m3sFjloqoIUQU3TsHBgj6qg/BVGlTBeHDUmyJnXKk= 71 | github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY= 72 | github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= 73 | github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= 74 | github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= 75 | github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= 76 | github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= 77 | github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= 78 | github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= 79 | github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= 80 | github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= 81 | github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= 82 | github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E= 83 | github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= 84 | github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= 85 | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 86 | github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 87 | github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= 88 | github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= 89 | github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= 90 | github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= 91 | github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= 92 | github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= 93 | github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= 94 | github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= 95 | github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= 96 | github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= 97 | github.com/google/pprof v0.0.0-20231212022811-ec68065c825e h1:bwOy7hAFd0C91URzMIEBfr6BAz29yk7Qj0cy6S7DJlU= 98 | github.com/google/pprof v0.0.0-20231212022811-ec68065c825e/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik= 99 | github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= 100 | github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 101 | github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY= 102 | github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg= 103 | github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= 104 | github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= 105 | github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw= 106 | github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU= 107 | github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= 108 | github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= 109 | github.com/jszwec/s3fs/v2 v2.0.0 h1:Y6UY8pW7KsJpx+hhYgmik9W3W2OiTYaY4r0J/8dGSh0= 110 | github.com/jszwec/s3fs/v2 v2.0.0/go.mod h1:juc0h9XDG+U/dDwOprq7p1VUFrumRA5B6XlBbuDysB8= 111 | github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= 112 | github.com/klauspost/cpuid/v2 v2.2.10 h1:tBs3QSyvjDyFTq3uoc/9xFpCuOsJQFNPiAhYdw2skhE= 113 | github.com/klauspost/cpuid/v2 v2.2.10/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0= 114 | github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= 115 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 116 | github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 117 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 118 | github.com/libdns/libdns v1.0.0-beta.1 h1:KIf4wLfsrEpXpZ3vmc/poM8zCATXT2klbdPe6hyOBjQ= 119 | github.com/libdns/libdns v1.0.0-beta.1/go.mod h1:4Bj9+5CQiNMVGf87wjX4CY3HQJypUHRuLvlsfsZqLWQ= 120 | github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI= 121 | github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= 122 | github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= 123 | github.com/mholt/acmez/v3 v3.1.2 h1:auob8J/0FhmdClQicvJvuDavgd5ezwLBfKuYmynhYzc= 124 | github.com/mholt/acmez/v3 v3.1.2/go.mod h1:L1wOU06KKvq7tswuMDwKdcHeKpFFgkppZy/y0DFxagQ= 125 | github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4= 126 | github.com/miekg/dns v1.1.63 h1:8M5aAw6OMZfFXTT7K5V0Eu5YiiL8l7nUAkyN6C9YwaY= 127 | github.com/miekg/dns v1.1.63/go.mod h1:6NGHfjhpmr5lt3XPLuyfDJi5AXbNIPM9PY6H6sF1Nfs= 128 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 129 | github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= 130 | github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo= 131 | github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM= 132 | github.com/onsi/ginkgo/v2 v2.13.2 h1:Bi2gGVkfn6gQcjNjZJVO8Gf0FHzMPf2phUei9tejVMs= 133 | github.com/onsi/ginkgo/v2 v2.13.2/go.mod h1:XStQ8QcGwLyF4HdfcZB8SFOS/MWCgDuXMSBe6zrvLgM= 134 | github.com/onsi/gomega v1.29.0 h1:KIA/t2t5UBzoirT4H9tsML45GEbo3ouUnBHsCfD2tVg= 135 | github.com/onsi/gomega v1.29.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ= 136 | github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8= 137 | github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 138 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 139 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 140 | github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= 141 | github.com/prometheus/client_golang v1.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE= 142 | github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho= 143 | github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= 144 | github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw= 145 | github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI= 146 | github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= 147 | github.com/prometheus/common v0.48.0 h1:QO8U2CdOzSn1BBsmXJXduaaW+dY/5QLjfB8svtSzKKE= 148 | github.com/prometheus/common v0.48.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc= 149 | github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= 150 | github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= 151 | github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= 152 | github.com/quic-go/qpack v0.5.1 h1:giqksBPnT/HDtZ6VhtFKgoLOWmlyo9Ei6u9PqzIMbhI= 153 | github.com/quic-go/qpack v0.5.1/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1ZgaEg= 154 | github.com/quic-go/quic-go v0.50.1 h1:unsgjFIUqW8a2oopkY7YNONpV1gYND6Nt9hnt1PN94Q= 155 | github.com/quic-go/quic-go v0.50.1/go.mod h1:Vim6OmUvlYdwBhXP9ZVrtGmCMWa3wEqhq3NgYrI8b4E= 156 | github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= 157 | github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= 158 | github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIlyj5a1fBNx5aJTbKoIq0mNaPvOagO+HjB3EtxrY= 159 | github.com/shurcooL/events v0.0.0-20181021180414-410e4ca65f48/go.mod h1:5u70Mqkb5O5cxEA8nxTsgrgLehJeAw6Oc4Ab1c/P1HM= 160 | github.com/shurcooL/github_flavored_markdown v0.0.0-20181002035957-2122de532470/go.mod h1:2dOwnU2uBioM+SGy2aZoq1f/Sd1l9OkAeAUvjSyvgU0= 161 | github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= 162 | github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ= 163 | github.com/shurcooL/gofontwoff v0.0.0-20180329035133-29b52fc0a18d/go.mod h1:05UtEgK5zq39gLST6uB0cf3NEHjETfB4Fgr3Gx5R9Vw= 164 | github.com/shurcooL/gopherjslib v0.0.0-20160914041154-feb6d3990c2c/go.mod h1:8d3azKNyqcHP1GaQE/c6dDgjkgSx2BZ4IoEi4F1reUI= 165 | github.com/shurcooL/highlight_diff v0.0.0-20170515013008-09bb4053de1b/go.mod h1:ZpfEhSmds4ytuByIcDnOLkTHGUI6KNqRNPDLHDk+mUU= 166 | github.com/shurcooL/highlight_go v0.0.0-20181028180052-98c3abbbae20/go.mod h1:UDKB5a1T23gOMUJrI+uSuH0VRDStOiUVSjBTRDVBVag= 167 | github.com/shurcooL/home v0.0.0-20181020052607-80b7ffcb30f9/go.mod h1:+rgNQw2P9ARFAs37qieuu7ohDNQ3gds9msbT2yn85sg= 168 | github.com/shurcooL/htmlg v0.0.0-20170918183704-d01228ac9e50/go.mod h1:zPn1wHpTIePGnXSHpsVPWEktKXHr6+SS6x/IKRb7cpw= 169 | github.com/shurcooL/httperror v0.0.0-20170206035902-86b7830d14cc/go.mod h1:aYMfkZ6DWSJPJ6c4Wwz3QtW22G7mf/PEgaB9k/ik5+Y= 170 | github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg= 171 | github.com/shurcooL/httpgzip v0.0.0-20180522190206-b1c53ac65af9/go.mod h1:919LwcH0M7/W4fcZ0/jy0qGght1GIhqyS/EgWGH2j5Q= 172 | github.com/shurcooL/issues v0.0.0-20181008053335-6292fdc1e191/go.mod h1:e2qWDig5bLteJ4fwvDAc2NHzqFEthkqn7aOZAOpj+PQ= 173 | github.com/shurcooL/issuesapp v0.0.0-20180602232740-048589ce2241/go.mod h1:NPpHK2TI7iSaM0buivtFUc9offApnI0Alt/K8hcHy0I= 174 | github.com/shurcooL/notifications v0.0.0-20181007000457-627ab5aea122/go.mod h1:b5uSkrEVM1jQUspwbixRBhaIjIzL2xazXp6kntxYle0= 175 | github.com/shurcooL/octicon v0.0.0-20181028054416-fa4f57f9efb2/go.mod h1:eWdoE5JD4R5UVWDucdOPg1g2fqQRq78IQa9zlOV1vpQ= 176 | github.com/shurcooL/reactions v0.0.0-20181006231557-f2e0b4ca5b82/go.mod h1:TCR1lToEk4d2s07G3XGfz2QrgHXg4RJBvjrOozvoWfk= 177 | github.com/shurcooL/sanitized_anchor_name v0.0.0-20170918181015-86672fcb3f95/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= 178 | github.com/shurcooL/users v0.0.0-20180125191416-49c67e49c537/go.mod h1:QJTqeLYEDaXHZDBsXlPCDqdhQuJkuw4NOtaxYe3xii4= 179 | github.com/shurcooL/webdavfs v0.0.0-20170829043945-18c3829fa133/go.mod h1:hKmq5kWdCj2z2KEozexVbfEZIWiTjhE0+UjmZgPqehw= 180 | github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE= 181 | github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA= 182 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 183 | github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 184 | github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 185 | github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= 186 | github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= 187 | github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA= 188 | github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU= 189 | github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM= 190 | github.com/zeebo/assert v1.1.0 h1:hU1L1vLTHsnO8x8c9KAR5GmM5QscxHg5RNU5z5qbUWY= 191 | github.com/zeebo/assert v1.1.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0= 192 | github.com/zeebo/blake3 v0.2.4 h1:KYQPkhpRtcqh0ssGYcKLG1JYvddkEA8QwCM/yBqhaZI= 193 | github.com/zeebo/blake3 v0.2.4/go.mod h1:7eeQ6d2iXWRGF6npfaxl2CU+xy2Fjo2gxeyZGCRUjcE= 194 | github.com/zeebo/pcg v1.0.1 h1:lyqfGeWiv4ahac6ttHs+I5hwtH/+1mrhlCtVNQM2kHo= 195 | github.com/zeebo/pcg v1.0.1/go.mod h1:09F0S9iiKrwn9rlI5yjLkmrug154/YRW6KnnXVDM/l4= 196 | go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA= 197 | go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= 198 | go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= 199 | go.uber.org/mock v0.5.0 h1:KAMbZvZPyBPWgD14IrIQ38QCyjwpvVVV6K/bHl1IwQU= 200 | go.uber.org/mock v0.5.0/go.mod h1:ge71pBPLYDk7QIi1LupWxdAykm7KIEFchiOqd6z7qMM= 201 | go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= 202 | go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= 203 | go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= 204 | go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= 205 | go.uber.org/zap/exp v0.3.0 h1:6JYzdifzYkGmTdRR59oYH+Ng7k49H9qVpWwNSsGJj3U= 206 | go.uber.org/zap/exp v0.3.0/go.mod h1:5I384qq7XGxYyByIhHm6jg5CHkGY0nsTfbDLgDDlgJQ= 207 | go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE= 208 | golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw= 209 | golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= 210 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 211 | golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 212 | golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34= 213 | golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc= 214 | golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= 215 | golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 h1:vr/HnozRka3pE4EsMEg1lgkXJkTFJCVUX+S/ZT6wYzM= 216 | golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842/go.mod h1:XtvwrStGgqGPLc4cjQfWqZHG1YFdYs6swckp8vpsjnc= 217 | golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= 218 | golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= 219 | golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= 220 | golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU= 221 | golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww= 222 | golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 223 | golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 224 | golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 225 | golang.org/x/net v0.0.0-20181029044818-c44066c5c816/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 226 | golang.org/x/net v0.0.0-20181106065722-10aee1819953/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 227 | golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 228 | golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 229 | golang.org/x/net v0.0.0-20190313220215-9f648a60d977/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 230 | golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8= 231 | golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= 232 | golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= 233 | golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= 234 | golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= 235 | golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 236 | golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852/go.mod h1:JLpeXjPJfIyPr5TlbXLkXWLhP8nz10XfvxElABhCtcw= 237 | golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 238 | golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 239 | golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 240 | golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 241 | golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw= 242 | golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= 243 | golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 244 | golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 245 | golang.org/x/sys v0.0.0-20181029174526-d69651ed3497/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 246 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 247 | golang.org/x/sys v0.0.0-20190316082340-a2f829d7f35f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 248 | golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= 249 | golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= 250 | golang.org/x/term v0.30.0 h1:PQ39fJZ+mfadBm0y5WlL4vlM7Sx1Hgf13sMIY2+QS9Y= 251 | golang.org/x/term v0.30.0/go.mod h1:NYYFdzHoI5wRh/h5tDMdMqCqPJZEuNqVR5xJLd/n67g= 252 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 253 | golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 254 | golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= 255 | golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= 256 | golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 257 | golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 258 | golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0= 259 | golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= 260 | golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 261 | golang.org/x/tools v0.0.0-20181030000716-a0a13e073c7b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 262 | golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 263 | golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= 264 | golang.org/x/tools v0.31.0 h1:0EedkvKDbh+qistFTd0Bcwe/YLh4vHwWEkiI0toFIBU= 265 | golang.org/x/tools v0.31.0/go.mod h1:naFTU+Cev749tSJRXJlna0T3WxKvb1kWEx15xA4SdmQ= 266 | google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= 267 | google.golang.org/api v0.0.0-20181030000543-1d582fd0359e/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= 268 | google.golang.org/api v0.1.0/go.mod h1:UGEZY7KEX120AnNLIHFMKIo4obdJhkp2tPbaPlQx13Y= 269 | google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= 270 | google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 271 | google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 272 | google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 273 | google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= 274 | google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= 275 | google.golang.org/genproto v0.0.0-20181029155118-b69ba1387ce2/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= 276 | google.golang.org/genproto v0.0.0-20181202183823-bd91e49a0898/go.mod h1:7Ep/1NZk928CDR8SjdVbjWNpdIf6nzjE3BTgJDr2Atg= 277 | google.golang.org/genproto v0.0.0-20190306203927-b5d61aea6440/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= 278 | google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= 279 | google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio= 280 | google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= 281 | google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= 282 | google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA= 283 | google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= 284 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 285 | gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= 286 | gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 287 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 288 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 289 | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= 290 | gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 291 | grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o= 292 | honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 293 | honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 294 | honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 295 | sourcegraph.com/sourcegraph/go-diff v0.5.0/go.mod h1:kuch7UrkMzY0X+p9CRK03kfuPQ2zzQcaEFbx8wA8rck= 296 | sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0= 297 | -------------------------------------------------------------------------------- /justfile: -------------------------------------------------------------------------------- 1 | [private] 2 | default: 3 | @just --list 4 | 5 | check: 6 | dagger call check 7 | 8 | test: 9 | dagger call test 10 | 11 | lint: 12 | dagger call lint 13 | 14 | fmt: 15 | golangci-lint fmt 16 | -------------------------------------------------------------------------------- /module.go: -------------------------------------------------------------------------------- 1 | // Package caddyfss3 implements a Caddy virtual filesystem module for AWS S3 (and compatible) object store. 2 | package caddyfss3 3 | 4 | import ( 5 | "errors" 6 | "io/fs" 7 | "log/slog" 8 | 9 | "github.com/aws/aws-sdk-go-v2/aws" 10 | "github.com/aws/aws-sdk-go-v2/config" 11 | "github.com/aws/aws-sdk-go-v2/service/s3" 12 | "github.com/caddyserver/caddy/v2" 13 | "github.com/caddyserver/caddy/v2/caddyconfig/caddyfile" 14 | "github.com/jszwec/s3fs/v2" 15 | ) 16 | 17 | func init() { 18 | caddy.RegisterModule(FS{}) 19 | } 20 | 21 | // Interface guards 22 | var ( 23 | _ fs.StatFS = (*FS)(nil) 24 | _ caddyfile.Unmarshaler = (*FS)(nil) 25 | ) 26 | 27 | // FS is a Caddy virtual filesystem module for AWS S3 (and compatible) object store. 28 | type FS struct { 29 | fs.StatFS `json:"-"` 30 | 31 | // The name of the S3 bucket. 32 | Bucket string `json:"bucket,omitempty"` 33 | 34 | // The AWS region the bucket is hosted in. 35 | Region string `json:"region,omitempty"` 36 | 37 | // The AWS profile to use if multiple profiles are specified. 38 | Profile string `json:"profile,omitempty"` 39 | 40 | // Use non-standard endpoint for S3. 41 | Endpoint string `json:"endpoint,omitempty"` 42 | 43 | // Set this to `true` to enable the client to use path-style addressing. 44 | UsePathStyle bool `json:"use_path_style,omitempty"` 45 | 46 | // DEPRECATED: please use 'use_path_style' instead. 47 | // Set this to `true` to force the request to use path-style addressing. 48 | S3ForcePathStyle bool `json:"force_path_style,omitempty"` 49 | } 50 | 51 | // CaddyModule returns the Caddy module information. 52 | func (FS) CaddyModule() caddy.ModuleInfo { 53 | return caddy.ModuleInfo{ 54 | ID: "caddy.fs.s3", 55 | New: func() caddy.Module { return new(FS) }, 56 | } 57 | } 58 | 59 | // Provision implements the [caddy.Provisioner] interface. 60 | func (fs *FS) Provision(ctx caddy.Context) error { 61 | if fs.Bucket == "" { 62 | return errors.New("bucket must be set") 63 | } 64 | 65 | if fs.S3ForcePathStyle { 66 | ctx.Logger().Warn("force_path_style is deprecated, please use use_path_style instead") 67 | } 68 | 69 | var configOpts []func(*config.LoadOptions) error 70 | 71 | if fs.Region != "" { 72 | configOpts = append(configOpts, config.WithRegion(fs.Region)) 73 | } 74 | 75 | if fs.Profile != "" { 76 | configOpts = append(configOpts, config.WithSharedConfigProfile(fs.Profile)) 77 | } 78 | 79 | cfg, err := config.LoadDefaultConfig(ctx.Context, configOpts...) 80 | if err != nil { 81 | ctx.Slogger().Error("could not create AWS config", slog.String("error", err.Error())) 82 | 83 | return err 84 | } 85 | 86 | client := s3.NewFromConfig(cfg, func(o *s3.Options) { 87 | if fs.Endpoint != "" { 88 | o.BaseEndpoint = aws.String(fs.Endpoint) 89 | } 90 | 91 | o.UsePathStyle = fs.UsePathStyle || fs.S3ForcePathStyle 92 | }) 93 | 94 | // ReadSeeker is required by Caddy 95 | fs.StatFS = s3fs.New(client, fs.Bucket, s3fs.WithReadSeeker) 96 | 97 | return nil 98 | } 99 | 100 | // UnmarshalCaddyfile unmarshals a caddyfile. 101 | func (fs *FS) UnmarshalCaddyfile(d *caddyfile.Dispenser) error { 102 | if !d.Next() { // skip block beginning 103 | return d.ArgErr() 104 | } 105 | 106 | for nesting := d.Nesting(); d.NextBlock(nesting); { 107 | switch d.Val() { 108 | case "bucket": 109 | if !d.AllArgs(&fs.Bucket) { 110 | return d.ArgErr() 111 | } 112 | case "region": 113 | if !d.AllArgs(&fs.Region) { 114 | return d.ArgErr() 115 | } 116 | case "profile": 117 | if !d.AllArgs(&fs.Profile) { 118 | return d.ArgErr() 119 | } 120 | case "endpoint": 121 | if !d.AllArgs(&fs.Endpoint) { 122 | return d.ArgErr() 123 | } 124 | case "use_path_style": 125 | fs.UsePathStyle = true 126 | case "force_path_style": 127 | fs.S3ForcePathStyle = true 128 | default: 129 | return d.Errf("%s not a valid caddy.fs.s3 option", d.Val()) 130 | } 131 | } 132 | 133 | return nil 134 | } 135 | --------------------------------------------------------------------------------