repos / pico

pico services mono repo
git clone https://github.com/picosh/pico.git

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
14 files changed,  +5, -495
M dev.md
M go.mod
M go.sum
D caddy/Caddyfile.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 
M docker-compose.override.yml
+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
M docker-compose.prod.yml
+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
M docker-compose.yml
+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=
M pkg/pobj/reader.go
+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 
M pkg/pobj/storage/fs.go
+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 }
D pkg/pobj/storage/minio.go
+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-}
M pkg/pobj/util.go
+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"
M pkg/send/protocols/sftp/handler.go
+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)
M pkg/shared/storage/base.go
+1, -7
 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)
D pkg/shared/storage/minio.go
+0, -49
 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-}