- commit
- 2340a56
- parent
- 67ea1f3
- author
- Eric Bower
- date
- 2026-01-16 22:14:04 -0500 EST
refactor: remove minio We haven't used minio in months and if we did choose another object storage it wouldn't minio
+0,
-79
1@@ -1,79 +0,0 @@
2-{
3- servers {
4- metrics
5- }
6-}
7-
8-*.minio.{$APP_DOMAIN}, *.{$APP_DOMAIN}, {$APP_DOMAIN} {
9- tls {$APP_EMAIL} {
10- dns cloudflare {$CF_API_TOKEN}
11- resolvers 1.1.1.1
12- }
13- encode zstd gzip
14-
15- header {
16- # disable FLoC tracking
17- Permissions-Policy interest-cohort=()
18-
19- # enable HSTS
20- Strict-Transport-Security max-age=31536000;
21-
22- # disable clients from sniffing the media type
23- X-Content-Type-Options nosniff
24-
25- # clickjacking protection
26- X-Frame-Options DENY
27-
28- # keep referrer data off of HTTP connections
29- Referrer-Policy no-referrer-when-downgrade
30-
31- Content-Security-Policy "default-src 'self'; img-src * 'unsafe-inline'; style-src * 'unsafe-inline'"
32-
33- X-XSS-Protection "1; mode=block"
34- }
35-
36- @caddymetrics {
37- host minio.{$APP_DOMAIN}
38- path /_caddy/metrics
39- }
40-
41- metrics @caddymetrics {
42- disable_openmetrics
43- }
44-
45- @console {
46- host console.minio.{$APP_DOMAIN}
47- }
48-
49- handle @console {
50- reverse_proxy minio:9001
51- }
52-
53- @imgproxy_prometheus {
54- host imgproxy.{$APP_DOMAIN}
55- path /metrics
56- }
57-
58- handle @imgproxy_prometheus {
59- reverse_proxy imgproxy:8081
60- }
61-
62- @imgproxy_root {
63- host imgproxy.{$APP_DOMAIN}
64- path /
65- }
66-
67- handle @imgproxy_root {
68- redir https://pico.sh
69- }
70-
71- @imgproxy {
72- host imgproxy.{$APP_DOMAIN}
73- }
74-
75- handle @imgproxy {
76- reverse_proxy imgproxy:8080
77- }
78-
79- reverse_proxy minio:9000
80-}
M
dev.md
+1,
-1
1@@ -7,7 +7,7 @@
2 cp ./.env.example .env
3 ```
4
5-If you are running apps outside of docker, remember to change the postgres, minio, and imgproxy hostnames to "localhost" in `.env`.
6+If you are running apps outside of docker, remember to change the postgres, and imgproxy hostnames to "localhost" in `.env`.
7
8 Initialize local env variables using direnv
9
+0,
-6
1@@ -5,12 +5,6 @@ services:
2 ports:
3 - "5432:5432"
4 command: -c log_statement=all -c log_destination=stderr
5- minio:
6- env_file:
7- - .env.example
8- ports:
9- - "9000:9000"
10- - "9001:9001"
11 imgproxy:
12 env_file:
13 - .env.example
+0,
-23
1@@ -7,29 +7,6 @@ services:
2 ports:
3 - "5432:5432"
4 command: -N 1024 -B 4096MB
5- minio-caddy:
6- image: ghcr.io/picosh/pico/caddy:latest
7- restart: always
8- env_file:
9- - .env.prod
10- environment:
11- APP_DOMAIN: pico.sh
12- APP_EMAIL: ${MINIO_EMAIL:-hello@pico.sh}
13- volumes:
14- - ${MINIO_CADDYFILE}:/etc/caddy/Caddyfile
15- - ./data/minio-caddy/data:/data
16- - ./data/minio-caddy/config:/config
17- ports:
18- - "80:80"
19- - "443:443"
20- profiles:
21- - minio
22- - all
23- minio:
24- env_file:
25- - .env.prod
26- volumes:
27- - ./data/minio-data:/data
28 pipemgr:
29 env_file:
30 - .env.prod
+0,
-8
1@@ -5,18 +5,10 @@ services:
2 profiles:
3 - db
4 - all
5- minio:
6- image: quay.io/minio/minio
7- command: server /data --console-address ":9001"
8- restart: always
9- profiles:
10- - minio
11- - all
12 imgproxy:
13 image: darthsim/imgproxy:latest
14 restart: always
15 profiles:
16- - minio
17 - all
18 - prose
19 - pgs
M
go.mod
+2,
-16
1@@ -42,8 +42,6 @@ require (
2 github.com/lib/pq v1.10.9
3 github.com/matryer/is v1.4.1
4 github.com/microcosm-cc/bluemonday v1.0.27
5- github.com/minio/madmin-go/v3 v3.0.102
6- github.com/minio/minio-go/v7 v7.0.89
7 github.com/mmcdole/gofeed v1.3.0
8 github.com/neurosnap/go-exif-remove v0.0.0-20221010134343-50d1e3c35577
9 github.com/picosh/go-rsync-receiver v0.0.0-20250304201040-fcc11dd22d79
10@@ -150,11 +148,11 @@ require (
11 github.com/felixge/httpsnoop v1.0.4 // indirect
12 github.com/forPelevin/gomoji v1.3.0 // indirect
13 github.com/francoispqt/gojay v1.2.13 // indirect
14+ github.com/fsnotify/fsnotify v1.8.0 // indirect
15 github.com/gammazero/deque v1.0.0 // indirect
16 github.com/gkampitakis/ciinfo v0.3.0 // indirect
17 github.com/gkampitakis/go-diff v1.3.2 // indirect
18 github.com/go-errors/errors v1.5.1 // indirect
19- github.com/go-ini/ini v1.67.0 // indirect
20 github.com/go-jose/go-jose/v3 v3.0.4 // indirect
21 github.com/go-jose/go-jose/v4 v4.0.5 // indirect
22 github.com/go-logr/logr v1.4.2 // indirect
23@@ -164,11 +162,9 @@ require (
24 github.com/go-sql-driver/mysql v1.9.1 // indirect
25 github.com/go-task/slim-sprig/v3 v3.0.0 // indirect
26 github.com/go-xmlfmt/xmlfmt v1.1.3 // indirect
27- github.com/goccy/go-json v0.10.5 // indirect
28 github.com/godbus/dbus/v5 v5.1.0 // indirect
29 github.com/gofrs/flock v0.12.1 // indirect
30 github.com/gogo/protobuf v1.3.2 // indirect
31- github.com/golang-jwt/jwt/v4 v4.5.2 // indirect
32 github.com/golang/geo v0.0.0-20250328065203-0b6e08c212fb // indirect
33 github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect
34 github.com/golang/protobuf v1.5.4 // indirect
35@@ -209,13 +205,10 @@ require (
36 github.com/mattn/go-isatty v0.0.20 // indirect
37 github.com/mattn/go-runewidth v0.0.16 // indirect
38 github.com/mattn/go-sixel v0.0.5 // indirect
39- github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
40 github.com/maypok86/otter v1.2.4 // indirect
41 github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect
42 github.com/mholt/acmez/v3 v3.1.2 // indirect
43 github.com/miekg/dns v1.1.64 // indirect
44- github.com/minio/crc64nvme v1.0.1 // indirect
45- github.com/minio/md5-simd v1.1.2 // indirect
46 github.com/mitchellh/copystructure v1.2.0 // indirect
47 github.com/mitchellh/go-ps v1.0.0 // indirect
48 github.com/mitchellh/reflectwalk v1.0.2 // indirect
49@@ -243,7 +236,6 @@ require (
50 github.com/opencontainers/go-digest v1.0.0 // indirect
51 github.com/opencontainers/image-spec v1.1.1 // indirect
52 github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 // indirect
53- github.com/philhofer/fwd v1.1.3-0.20240916144458-20a13a1f6b7c // indirect
54 github.com/pierrec/lz4/v4 v4.1.22 // indirect
55 github.com/pkg/errors v0.9.1 // indirect
56 github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
57@@ -252,8 +244,6 @@ require (
58 github.com/prometheus/client_model v0.6.2 // indirect
59 github.com/prometheus/common v0.63.0 // indirect
60 github.com/prometheus/procfs v0.16.0 // indirect
61- github.com/prometheus/prom2json v1.4.1 // indirect
62- github.com/prometheus/prometheus v0.302.1 // indirect
63 github.com/quic-go/qpack v0.5.1 // indirect
64 github.com/quic-go/quic-go v0.50.1 // indirect
65 github.com/redis/rueidis v1.0.56 // indirect
66@@ -262,12 +252,8 @@ require (
67 github.com/rogpeppe/go-internal v1.13.2-0.20241226121412-a5dc8ff20d0a // indirect
68 github.com/rs/xid v1.6.0 // indirect
69 github.com/russross/blackfriday/v2 v2.1.0 // indirect
70- github.com/safchain/ethtool v0.5.10 // indirect
71 github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 // indirect
72- github.com/secure-io/sio-go v0.3.1 // indirect
73- github.com/shirou/gopsutil/v3 v3.24.5 // indirect
74 github.com/shirou/gopsutil/v4 v4.25.6 // indirect
75- github.com/shoenig/go-m1cpu v0.1.6 // indirect
76 github.com/shopspring/decimal v1.4.0 // indirect
77 github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect
78 github.com/sirupsen/logrus v1.9.3 // indirect
79@@ -292,7 +278,6 @@ require (
80 github.com/tidwall/pretty v1.2.1 // indirect
81 github.com/tidwall/redcon v1.6.2 // indirect
82 github.com/tidwall/sjson v1.2.5 // indirect
83- github.com/tinylib/msgp v1.2.5 // indirect
84 github.com/tklauser/go-sysconf v0.3.15 // indirect
85 github.com/tklauser/numcpus v0.10.0 // indirect
86 github.com/urfave/cli v1.22.16 // indirect
87@@ -310,6 +295,7 @@ require (
88 go.opentelemetry.io/auto/sdk v1.1.0 // indirect
89 go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0 // indirect
90 go.opentelemetry.io/otel v1.35.0 // indirect
91+ go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.34.0 // indirect
92 go.opentelemetry.io/otel/metric v1.35.0 // indirect
93 go.opentelemetry.io/otel/trace v1.35.0 // indirect
94 go.step.sm/crypto v0.60.0 // indirect
M
go.sum
+0,
-38
1@@ -333,8 +333,6 @@ github.com/go-errors/errors v1.0.2/go.mod h1:psDX2osz5VnTOnFWbDeWwS7yejl+uV3FEWE
2 github.com/go-errors/errors v1.1.1/go.mod h1:psDX2osz5VnTOnFWbDeWwS7yejl+uV3FEWEp4lssFEs=
3 github.com/go-errors/errors v1.5.1 h1:ZwEMSLRCapFLflTpT7NKaAc7ukJ8ZPEjzlxt8rPN8bk=
4 github.com/go-errors/errors v1.5.1/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og=
5-github.com/go-ini/ini v1.67.0 h1:z6ZrTEZqSWOTyH2FlglNbNgARyHG8oLW9gMELqKr06A=
6-github.com/go-ini/ini v1.67.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=
7 github.com/go-jose/go-jose/v3 v3.0.4 h1:Wp5HA7bLQcKnf6YYao/4kpRpVMp/yf6+pJKV8WFSaNY=
8 github.com/go-jose/go-jose/v3 v3.0.4/go.mod h1:5b+7YgP7ZICgJDBdfjZaIt+H/9L9T/YQrVfLAMboGkQ=
9 github.com/go-jose/go-jose/v4 v4.0.5 h1:M6T8+mKZl/+fNNuFHvGIzDz7BTLQPIounk/b9dw3AaE=
10@@ -365,8 +363,6 @@ github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZ
11 github.com/go-xmlfmt/xmlfmt v0.0.0-20191208150333-d5b6f63a941b/go.mod h1:aUCEOzzezBEjDBbFBoSiya/gduyIiWYRP6CnSFIV8AM=
12 github.com/go-xmlfmt/xmlfmt v1.1.3 h1:t8Ey3Uy7jDSEisW2K3somuMKIpzktkWptA0iFCnRUWY=
13 github.com/go-xmlfmt/xmlfmt v1.1.3/go.mod h1:aUCEOzzezBEjDBbFBoSiya/gduyIiWYRP6CnSFIV8AM=
14-github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4=
15-github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
16 github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
17 github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk=
18 github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
19@@ -375,8 +371,6 @@ github.com/gofrs/flock v0.12.1/go.mod h1:9zxTsyu5xtJ9DK+1tFZyibEV7y3uwDxPPfbxeeH
20 github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
21 github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
22 github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
23-github.com/golang-jwt/jwt/v4 v4.5.2 h1:YtQM7lnr8iZ+j5q71MGKkNw9Mn7AjHM68uc9g5fXeUI=
24-github.com/golang-jwt/jwt/v4 v4.5.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
25 github.com/golang/geo v0.0.0-20190916061304-5b978397cfec/go.mod h1:QZ0nwyI2jOfgRAoBvP+ab5aRr7c9x7lhGEJrKvBwjWI=
26 github.com/golang/geo v0.0.0-20200319012246-673a6f80352d/go.mod h1:QZ0nwyI2jOfgRAoBvP+ab5aRr7c9x7lhGEJrKvBwjWI=
27 github.com/golang/geo v0.0.0-20250328065203-0b6e08c212fb h1:eqdj1jSZjgmPdSl2lr3rAwJykSe9jHxPN1zLuasKVh0=
28@@ -541,7 +535,6 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o
29 github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg=
30 github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
31 github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
32-github.com/klauspost/cpuid/v2 v2.0.1/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
33 github.com/klauspost/cpuid/v2 v2.2.10 h1:tBs3QSyvjDyFTq3uoc/9xFpCuOsJQFNPiAhYdw2skhE=
34 github.com/klauspost/cpuid/v2 v2.2.10/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0=
35 github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
36@@ -591,8 +584,6 @@ github.com/mattn/go-sixel v0.0.5/go.mod h1:h2Sss+DiUEHy0pUqcIB6PFXo5Cy8sTQEFr3a9
37 github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU=
38 github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
39 github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
40-github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo=
41-github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
42 github.com/maypok86/otter v1.2.4 h1:HhW1Pq6VdJkmWwcZZq19BlEQkHtI8xgsQzBVXJU0nfc=
43 github.com/maypok86/otter v1.2.4/go.mod h1:mKLfoI7v1HOmQMwFgX4QkRk23mX6ge3RDvjdHOWG4R4=
44 github.com/mdelapenya/tlscert v0.2.0 h1:7H81W6Z/4weDvZBNOfQte5GpIMo0lGYEeWbkGp5LJHI=
45@@ -608,14 +599,6 @@ github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKju
46 github.com/miekg/dns v1.1.45/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME=
47 github.com/miekg/dns v1.1.64 h1:wuZgD9wwCE6XMT05UU/mlSko71eRSXEAm2EbjQXLKnQ=
48 github.com/miekg/dns v1.1.64/go.mod h1:Dzw9769uoKVaLuODMDZz9M6ynFU6Em65csPuoi8G0ck=
49-github.com/minio/crc64nvme v1.0.1 h1:DHQPrYPdqK7jQG/Ls5CTBZWeex/2FMS3G5XGkycuFrY=
50-github.com/minio/crc64nvme v1.0.1/go.mod h1:eVfm2fAzLlxMdUGc0EEBGSMmPwmXD5XiNRpnu9J3bvg=
51-github.com/minio/madmin-go/v3 v3.0.102 h1:bqy15D6d9uQOh/3B/sLfzRtWSJgZeuKnAI5VRDhvRQw=
52-github.com/minio/madmin-go/v3 v3.0.102/go.mod h1:pMLdj9OtN0CANNs5tdm6opvOlDFfj0WhbztboZAjRWE=
53-github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34=
54-github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM=
55-github.com/minio/minio-go/v7 v7.0.89 h1:hx4xV5wwTUfyv8LarhJAwNecnXpoTsj9v3f3q/ZkiJU=
56-github.com/minio/minio-go/v7 v7.0.89/go.mod h1:2rFnGAp02p7Dddo1Fq4S2wYOfpF0MUTSeLTRC90I204=
57 github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
58 github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw=
59 github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s=
60@@ -709,8 +692,6 @@ github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58/go.mod h1:DXv8WO4yhM
61 github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
62 github.com/peterbourgon/diskv/v3 v3.0.1 h1:x06SQA46+PKIUftmEujdwSEpIx8kR+M9eLYsUxeYveU=
63 github.com/peterbourgon/diskv/v3 v3.0.1/go.mod h1:kJ5Ny7vLdARGU3WUuy6uzO6T0nb/2gWcT1JiBvRmb5o=
64-github.com/philhofer/fwd v1.1.3-0.20240916144458-20a13a1f6b7c h1:dAMKvw0MlJT1GshSTtih8C2gDs04w8dReiOGXrGLNoY=
65-github.com/philhofer/fwd v1.1.3-0.20240916144458-20a13a1f6b7c/go.mod h1:RqIHx9QI14HlwKwm98g9Re5prTQ6LdeRQn+gXJFxsJM=
66 github.com/picosh/go-rsync-receiver v0.0.0-20250304201040-fcc11dd22d79 h1:MyB9P43hlQ6A2FoP9LGeiTBL3WKToW4gcWd6lQPg/Zg=
67 github.com/picosh/go-rsync-receiver v0.0.0-20250304201040-fcc11dd22d79/go.mod h1:4ZICsr6bESoHP8He9DqROlZiMw4hHHjcbDzhtTTDQzA=
68 github.com/picosh/pubsub v0.0.0-20241114191831-ec8f16c0eb88 h1:hdxE6rquHHw1/eeqS1b+ojLaxGtN8zOiTUclPwaVbPg=
69@@ -765,10 +746,6 @@ github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4O
70 github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
71 github.com/prometheus/procfs v0.16.0 h1:xh6oHhKwnOJKMYiYBDWmkHqQPyiY40sny36Cmx2bbsM=
72 github.com/prometheus/procfs v0.16.0/go.mod h1:8veyXUu3nGP7oaCxhX6yeaM5u4stL2FeMXnCqhDthZg=
73-github.com/prometheus/prom2json v1.4.1 h1:7McxdrHgPEOtMwWjkKtd0v5AhpR2Q6QAnlHKVxq0+tQ=
74-github.com/prometheus/prom2json v1.4.1/go.mod h1:CzOQykSKFxXuC7ELUZHOHQvwKesQ3eN0p2PWLhFitQM=
75-github.com/prometheus/prometheus v0.302.1 h1:xqVdrwrB4WNpdgJqxsz5loqFWNUZitsK8myqLuSZ6Ag=
76-github.com/prometheus/prometheus v0.302.1/go.mod h1:YcyCoTbUR/TM8rY3Aoeqr0AWTu/pu1Ehh+trpX3eRzg=
77 github.com/quic-go/qpack v0.5.1 h1:giqksBPnT/HDtZ6VhtFKgoLOWmlyo9Ei6u9PqzIMbhI=
78 github.com/quic-go/qpack v0.5.1/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1ZgaEg=
79 github.com/quic-go/quic-go v0.50.1 h1:unsgjFIUqW8a2oopkY7YNONpV1gYND6Nt9hnt1PN94Q=
80@@ -792,24 +769,14 @@ github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQD
81 github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
82 github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06 h1:OkMGxebDjyw0ULyrTYWeN0UNCCkmCWfjPnIA2W6oviI=
83 github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06/go.mod h1:+ePHsJ1keEjQtpvf9HHw0f4ZeJ0TLRsxhunSI2hYJSs=
84-github.com/safchain/ethtool v0.5.10 h1:Im294gZtuf4pSGJRAOGKaASNi3wMeFaGaWuSaomedpc=
85-github.com/safchain/ethtool v0.5.10/go.mod h1:w9jh2Lx7YBR4UwzLkzCmWl85UY0W2uZdd7/DckVE5+c=
86 github.com/schollz/jsonstore v1.1.0 h1:WZBDjgezFS34CHI+myb4s8GGpir3UMpy7vWoCeO0n6E=
87 github.com/schollz/jsonstore v1.1.0/go.mod h1:15c6+9guw8vDRyozGjN3FoILt0wpruJk9Pi66vjaZfg=
88 github.com/scylladb/termtables v0.0.0-20191203121021-c4c0b6d42ff4/go.mod h1:C1a7PQSMz9NShzorzCiG2fk9+xuCgLkPeCvMHYR2OWg=
89 github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I=
90 github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
91-github.com/secure-io/sio-go v0.3.1 h1:dNvY9awjabXTYGsTF1PiCySl9Ltofk9GA3VdWlo7rRc=
92-github.com/secure-io/sio-go v0.3.1/go.mod h1:+xbkjDzPjwh4Axd07pRKSNriS9SCiYksWnZqdnfpQxs=
93 github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
94-github.com/shirou/gopsutil/v3 v3.24.5 h1:i0t8kL+kQTvpAYToeuiVk3TgDeKOFioZO3Ztz/iZ9pI=
95-github.com/shirou/gopsutil/v3 v3.24.5/go.mod h1:bsoOS1aStSs9ErQ1WWfxllSeS1K5D+U30r2NfcubMVk=
96 github.com/shirou/gopsutil/v4 v4.25.6 h1:kLysI2JsKorfaFPcYmcJqbzROzsBWEOAtw6A7dIfqXs=
97 github.com/shirou/gopsutil/v4 v4.25.6/go.mod h1:PfybzyydfZcN+JMMjkF6Zb8Mq1A/VcogFFg7hj50W9c=
98-github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM=
99-github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ=
100-github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU=
101-github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k=
102 github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k=
103 github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME=
104 github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIlyj5a1fBNx5aJTbKoIq0mNaPvOagO+HjB3EtxrY=
105@@ -926,8 +893,6 @@ github.com/tidwall/redcon v1.6.2 h1:5qfvrrybgtO85jnhSravmkZyC0D+7WstbfCs3MmPhow=
106 github.com/tidwall/redcon v1.6.2/go.mod h1:p5Wbsgeyi2VSTBWOcA5vRXrOb9arFTcU2+ZzFjqV75Y=
107 github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY=
108 github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28=
109-github.com/tinylib/msgp v1.2.5 h1:WeQg1whrXRFiZusidTQqzETkRpGjFjcIhW6uqWH09po=
110-github.com/tinylib/msgp v1.2.5/go.mod h1:ykjzy2wzgrlvpDCRc4LA8UXy6D8bzMSuAF3WD57Gok0=
111 github.com/tklauser/go-sysconf v0.3.15 h1:VE89k0criAymJ/Os65CSn1IXaol+1wrsFHEB8Ol49K4=
112 github.com/tklauser/go-sysconf v0.3.15/go.mod h1:Dmjwr6tYFIseJw7a3dRLJfsHAMXZ3nEnL/aZY+0IuI4=
113 github.com/tklauser/numcpus v0.10.0 h1:18njr6LDBk1zuna922MgdjQuJFjrdppsZG60sHGfjso=
114@@ -1032,7 +997,6 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
115 golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
116 golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY=
117 golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
118-golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
119 golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
120 golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
121 golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
122@@ -1154,7 +1118,6 @@ golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7w
123 golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
124 golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
125 golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
126-golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
127 golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
128 golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
129 golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
130@@ -1186,7 +1149,6 @@ golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
131 golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
132 golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
133 golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
134-golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
135 golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
136 golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ=
137 golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
+0,
-8
1@@ -3,9 +3,7 @@ package pobj
2 import (
3 "errors"
4 "io"
5- "net/http"
6
7- "github.com/minio/minio-go/v7"
8 "github.com/picosh/pico/pkg/send/utils"
9 )
10
11@@ -24,12 +22,6 @@ func (a *AllReaderAt) ReadAt(p []byte, off int64) (n int, err error) {
12 return
13 }
14
15- resp := minio.ToErrorResponse(err)
16-
17- if resp.StatusCode == http.StatusRequestedRangeNotSatisfiable {
18- err = io.EOF
19- }
20-
21 return
22 }
23
+0,
-1
1@@ -96,7 +96,6 @@ func (s *StorageFS) GetBucketQuota(bucket Bucket) (uint64, error) {
2 }
3
4 // DeleteBucket will delete all contents regardless if files exist inside of it.
5-// This is different from minio impl which requires all files be deleted first.
6 func (s *StorageFS) DeleteBucket(bucket Bucket) error {
7 return os.RemoveAll(bucket.Path)
8 }
+0,
-247
1@@ -1,247 +0,0 @@
2-package storage
3-
4-import (
5- "context"
6- "errors"
7- "fmt"
8- "io"
9- "log/slog"
10- "net/url"
11- "os"
12- "strconv"
13- "strings"
14- "time"
15-
16- "github.com/hashicorp/golang-lru/v2/expirable"
17- "github.com/minio/madmin-go/v3"
18- "github.com/minio/minio-go/v7"
19- "github.com/minio/minio-go/v7/pkg/credentials"
20- "github.com/picosh/pico/pkg/cache"
21- "github.com/picosh/pico/pkg/send/utils"
22-)
23-
24-type StorageMinio struct {
25- Client *minio.Client
26- Admin *madmin.AdminClient
27- BucketCache *expirable.LRU[string, CachedBucket]
28- Logger *slog.Logger
29-}
30-
31-type CachedBucket struct {
32- Bucket
33- Error error
34-}
35-
36-type CachedObjectInfo struct {
37- *ObjectInfo
38- Error error
39-}
40-
41-var (
42- _ ObjectStorage = &StorageMinio{}
43- _ ObjectStorage = (*StorageMinio)(nil)
44-)
45-
46-func NewStorageMinio(logger *slog.Logger, address, user, pass string) (*StorageMinio, error) {
47- endpoint, err := url.Parse(address)
48- if err != nil {
49- return nil, err
50- }
51- ssl := endpoint.Scheme == "https"
52-
53- mClient, err := minio.New(endpoint.Host, &minio.Options{
54- Creds: credentials.NewStaticV4(user, pass, ""),
55- Secure: ssl,
56- })
57- if err != nil {
58- return nil, err
59- }
60-
61- aClient, err := madmin.NewWithOptions(
62- endpoint.Host,
63- &madmin.Options{
64- Creds: credentials.NewStaticV4(user, pass, ""),
65- Secure: ssl,
66- },
67- )
68- if err != nil {
69- return nil, err
70- }
71-
72- mini := &StorageMinio{
73- Client: mClient,
74- Admin: aClient,
75- BucketCache: expirable.NewLRU[string, CachedBucket](2048, nil, cache.CacheTimeout),
76- Logger: logger,
77- }
78- return mini, err
79-}
80-
81-func (s *StorageMinio) GetBucket(name string) (Bucket, error) {
82- if cachedBucket, found := s.BucketCache.Get(name); found {
83- s.Logger.Info("bucket found in lru cache", "name", name)
84- return cachedBucket.Bucket, cachedBucket.Error
85- }
86-
87- s.Logger.Info("bucket not found in lru cache", "name", name)
88-
89- bucket := Bucket{
90- Name: name,
91- }
92-
93- exists, err := s.Client.BucketExists(context.TODO(), bucket.Name)
94- if err != nil || !exists {
95- if err == nil {
96- err = errors.New("bucket does not exist")
97- }
98-
99- s.BucketCache.Add(name, CachedBucket{bucket, err})
100- return bucket, err
101- }
102-
103- s.BucketCache.Add(name, CachedBucket{bucket, nil})
104-
105- return bucket, nil
106-}
107-
108-func (s *StorageMinio) UpsertBucket(name string) (Bucket, error) {
109- bucket, err := s.GetBucket(name)
110- if err == nil {
111- return bucket, nil
112- }
113-
114- err = s.Client.MakeBucket(context.TODO(), name, minio.MakeBucketOptions{})
115- if err != nil {
116- return bucket, err
117- }
118-
119- s.BucketCache.Remove(name)
120-
121- return bucket, nil
122-}
123-
124-func (s *StorageMinio) GetBucketQuota(bucket Bucket) (uint64, error) {
125- info, err := s.Admin.AccountInfo(context.TODO(), madmin.AccountOpts{})
126- if err != nil {
127- return 0, nil
128- }
129- for _, b := range info.Buckets {
130- if b.Name == bucket.Name {
131- return b.Size, nil
132- }
133- }
134-
135- return 0, fmt.Errorf("%s bucket not found in account info", bucket.Name)
136-}
137-
138-func (s *StorageMinio) ListBuckets() ([]string, error) {
139- bcks := []string{}
140- buckets, err := s.Client.ListBuckets(context.Background())
141- if err != nil {
142- return bcks, err
143- }
144- for _, bucket := range buckets {
145- bcks = append(bcks, bucket.Name)
146- }
147-
148- return bcks, nil
149-}
150-
151-func (s *StorageMinio) ListObjects(bucket Bucket, dir string, recursive bool) ([]os.FileInfo, error) {
152- var fileList []os.FileInfo
153-
154- resolved := strings.TrimPrefix(dir, "/")
155-
156- opts := minio.ListObjectsOptions{Prefix: resolved, Recursive: recursive, WithMetadata: true}
157- for obj := range s.Client.ListObjects(context.Background(), bucket.Name, opts) {
158- if obj.Err != nil {
159- return fileList, obj.Err
160- }
161-
162- isDir := strings.HasSuffix(obj.Key, string(os.PathSeparator))
163-
164- modTime := obj.LastModified
165-
166- if mtime, ok := obj.UserMetadata["Mtime"]; ok {
167- mtimeUnix, err := strconv.Atoi(mtime)
168- if err == nil {
169- modTime = time.Unix(int64(mtimeUnix), 0)
170- }
171- }
172-
173- info := &utils.VirtualFile{
174- FName: strings.TrimSuffix(strings.TrimPrefix(obj.Key, resolved), "/"),
175- FIsDir: isDir,
176- FSize: obj.Size,
177- FModTime: modTime,
178- }
179- fileList = append(fileList, info)
180- }
181-
182- return fileList, nil
183-}
184-
185-func (s *StorageMinio) DeleteBucket(bucket Bucket) error {
186- return s.Client.RemoveBucket(context.TODO(), bucket.Name)
187-}
188-
189-func (s *StorageMinio) GetObject(bucket Bucket, fpath string) (utils.ReadAndReaderAtCloser, *ObjectInfo, error) {
190- objInfo := &ObjectInfo{
191- Size: 0,
192- LastModified: time.Time{},
193- ETag: "",
194- }
195-
196- info, err := s.Client.StatObject(context.Background(), bucket.Name, fpath, minio.StatObjectOptions{})
197- if err != nil {
198- return nil, objInfo, err
199- }
200-
201- objInfo.LastModified = info.LastModified
202- objInfo.ETag = info.ETag
203- objInfo.Metadata = info.Metadata
204- objInfo.Size = info.Size
205-
206- if mtime, ok := info.UserMetadata["Mtime"]; ok {
207- mtimeUnix, err := strconv.Atoi(mtime)
208- if err == nil {
209- objInfo.LastModified = time.Unix(int64(mtimeUnix), 0)
210- }
211- }
212-
213- obj, err := s.Client.GetObject(context.Background(), bucket.Name, fpath, minio.GetObjectOptions{})
214- if err != nil {
215- return nil, objInfo, err
216- }
217-
218- return obj, objInfo, nil
219-}
220-
221-func (s *StorageMinio) PutObject(bucket Bucket, fpath string, contents io.Reader, entry *utils.FileEntry) (string, int64, error) {
222- opts := minio.PutObjectOptions{
223- UserMetadata: map[string]string{
224- "Mtime": fmt.Sprint(time.Now().Unix()),
225- },
226- }
227-
228- if entry.Mtime > 0 {
229- opts.UserMetadata["Mtime"] = fmt.Sprint(entry.Mtime)
230- }
231-
232- var objSize int64 = -1
233- if entry.Size > 0 {
234- objSize = entry.Size
235- }
236- info, err := s.Client.PutObject(context.TODO(), bucket.Name, fpath, contents, objSize, opts)
237-
238- if err != nil {
239- return "", 0, err
240- }
241-
242- return fmt.Sprintf("%s/%s", info.Bucket, info.Key), info.Size, nil
243-}
244-
245-func (s *StorageMinio) DeleteObject(bucket Bucket, fpath string) error {
246- err := s.Client.RemoveObject(context.TODO(), bucket.Name, fpath, minio.RemoveObjectOptions{})
247- return err
248-}
+0,
-10
1@@ -21,16 +21,6 @@ func EnvDriverDetector(logger *slog.Logger) (storage.ObjectStorage, error) {
2 switch driver {
3 case "memory":
4 return storage.NewStorageMemory(map[string]map[string]string{})
5- case "minio":
6- url := GetEnv("MINIO_URL", "")
7- user := GetEnv("MINIO_ROOT_USER", "")
8- pass := GetEnv("MINIO_ROOT_PASSWORD", "")
9- logger.Info(
10- "object config detected",
11- "url", url,
12- "user", user,
13- )
14- return storage.NewStorageMinio(logger, url, user, pass)
15 }
16
17 // implied driver == "fs"
+1,
-2
1@@ -69,8 +69,7 @@ func (f *handler) Filelist(r *sftp.Request) (sftp.ListerAt, error) {
2 return nil, err
3 }
4
5- // an empty string from minio or exact match from filepath base name is what we want
6-
7+ // an empty string or exact match from filepath base name is what we want
8 if !list {
9 listData = slices.DeleteFunc(listData, func(f os.FileInfo) bool {
10 return f.Name() != "" && f.Name() != filepath.Base(r.Filepath)
1@@ -8,18 +8,12 @@ import (
2 )
3
4 func GetStorageTypeFromEnv() string {
5- return utils.GetEnv("STORAGE_ADAPTER", "minio")
6+ return utils.GetEnv("STORAGE_ADAPTER", "fs")
7 }
8
9 func NewStorage(logger *slog.Logger, adapter string) (StorageServe, error) {
10 logger.Info("storage adapter", "adapter", adapter)
11 switch adapter {
12- case "minio":
13- minioURL := utils.GetEnv("MINIO_URL", "")
14- minioUser := utils.GetEnv("MINIO_ROOT_USER", "")
15- minioPass := utils.GetEnv("MINIO_ROOT_PASSWORD", "")
16- logger.Info("using minio storage", "url", minioURL, "user", minioUser)
17- return NewStorageMinio(logger, minioURL, minioUser, minioPass)
18 case "fs":
19 fsPath := utils.GetEnv("FS_STORAGE_DIR", "/tmp/pico_storage")
20 logger.Info("using filesystem storage", "path", fsPath)
1@@ -1,49 +0,0 @@
2-package storage
3-
4-import (
5- "fmt"
6- "io"
7- "log/slog"
8- "net/http"
9- "os"
10- "path/filepath"
11- "strings"
12-
13- sst "github.com/picosh/pico/pkg/pobj/storage"
14- "github.com/picosh/pico/pkg/shared/mime"
15-)
16-
17-type StorageMinio struct {
18- *sst.StorageMinio
19-}
20-
21-func NewStorageMinio(logger *slog.Logger, address, user, pass string) (*StorageMinio, error) {
22- st, err := sst.NewStorageMinio(logger, address, user, pass)
23- if err != nil {
24- return nil, err
25- }
26- return &StorageMinio{st}, nil
27-}
28-
29-func (s *StorageMinio) ServeObject(r *http.Request, bucket sst.Bucket, fpath string, opts *ImgProcessOpts) (io.ReadCloser, *sst.ObjectInfo, error) {
30- var rc io.ReadCloser
31- info := &sst.ObjectInfo{}
32- var err error
33- mimeType := mime.GetMimeType(fpath)
34- if !strings.HasPrefix(mimeType, "image/") || opts == nil || os.Getenv("IMGPROXY_URL") == "" {
35- rc, info, err = s.GetObject(bucket, fpath)
36- if info.Metadata == nil {
37- info.Metadata = map[string][]string{}
38- }
39- // Minio always returns application/octet-stream which needs to be overridden.
40- info.Metadata.Set("content-type", mimeType)
41- } else {
42- filePath := filepath.Join(bucket.Name, fpath)
43- dataURL := fmt.Sprintf("s3://%s", filePath)
44- rc, info, err = HandleProxy(r, s.Logger, dataURL, opts)
45- }
46- if err != nil {
47- return nil, nil, err
48- }
49- return rc, info, err
50-}