In my last Garage setup
, I used Caddy as my reverse proxy, and it worked just fine.
But Ferron 2
was released recently, so I gave it another shot.
Ferron has a small image size (the Alpine image is just 15MB
).
For a simple reverse proxy with AutoTLS, that is good enough, and Caddy feels a bit overkill for my usage.
Reverse Proxy Configuration
For Ferron, it takes almost nothing to configure the reverse proxy by passing a KDL config to the container.
this.s3.hosting.com {
proxy "http://garage:3902/"
}
Automatic TLS configuration
For Ferron, it takes a little bit more config compared to Caddy. Set it in the same KDL config:
* {
auto_tls
auto_tls_contact "[email protected]"
auto_tls_cache "/var/cache/ferron-acme" // same as the `ferron-acme` mapped volume in docker compose
auto_tls_letsencrypt_production
// Use HTTP-01 challenge instead of TLS-ALPN-01, because the server is behind an HTTPS proxy.
auto_tls_challenge "http-01"
}
Host Header Issue
After setting the config and starting Ferron, it does not work.
At least for virtual-hosted website buckets, because the Host header needs to match the bucket name you are trying to reach.
But Ferron doesn’t seem to handle that by default (Caddy works fine with the default setting).
172.65.32.248 - - [10/Nov/2025:01:51:10 +0000] "garage" "GET / HTTP/1.1" 200 615 "-" "curl/8.7.1" 0.000
By adding proxy_request_header_replace into the config to override the Host Header, the issue is resolved.
this.s3.hosting.com {
proxy "http://garage:3902/"
proxy_request_header_replace "Host" "this.s3.hosting.com"
}
The access log after the changes (I used nginx as the destination for testing purposes):
172.65.32.248 - - [10/Nov/2025:01:52:03 +0000] "this.s3.hosting.com" "GET / HTTP/1.1" 200 615 "-" "curl/8.7.1" 0.000
This also applies to other reverse proxies and tunnels. If you are exposing the bucket and it does not work on the first shot, check the Host header first.