Reverse_proxy to s3 error handling

1. Caddy version (caddy version):

v2.2.1 h1:Q62GWHMtztnvyRU+KPOpw6fNfeCD3SkwH7SfT1Tgt2c=

2. How I run Caddy:

systemd unit

a. System environment:

Ubuntu 20.04.1

b. Command:

systemctl start caddy

c. Service/unit/compose file:


ExecStart=/usr/bin/caddy run --environ --config /etc/caddy/Caddyfile
ExecReload=/usr/bin/caddy reload --config /etc/caddy/Caddyfile


d. My complete Caddyfile or JSON config:


(basics) {
  encode zstd gzip
  rewrite /api /api/

(static) {
  @static {
    path *.ico *.css *.js *.gif *.jpg *.jpeg *.png *.svg *.woff *.woff2 *.json *.webp
  header @static Cache-Control max-age=2678400

(security) {
  header {
    X-Frame-Options SAMEORIGIN
    X-XSS-Protection 1; mode=block
    X-Content-Type-Options nosniff
    Strict-Transport-Security max-age=31536000;
    Referrer-Policy no-referrer-when-downgrade

(ws) {
  @websockets {
    header Connection Upgrade
    header Upgrade websocket

http://wllhvn.wg {
  import basics
  import static

  header {
    X-Frame-Options SAMEORIGIN
    X-XSS-Protection 1; mode=block
    X-Content-Type-Options nosniff

  rewrite / /index.html

  handle {
    rewrite * /wllhvn{path}
    reverse_proxy http://localhost:9000 {
      header_up X-Forwarded-Host {host}
      header_up Host {host}
      header_up Connection ""

      transport http {
        dial_timeout 5m

  handle /api/* {

  handle_errors {
    rewrite * /index.html

http://wllhvn.wg:6566 {
  import ws
  reverse_proxy @websockets {
    header_up Host {host}
    header_up Connection Upgrade
    header_up Upgrade websocket

3. The problem I’m having:

My Caddy is reverse proxy to local S3 serving static files. When I receive 404, S3 returns XML with error and status code 404. So I want to handle these errors and redirect user to index.html

4. Error messages and/or full log output:

No errors

5. What I already tried:

I just have no idea what to do. I googled a lot but found no documentation about reverse proxy to S3 404 handling.

6. Links to relevant resources:

I have a few comments on what I see in your Caddyfile:

You websocket matcher isn’t exactly right, it should be this:

@websockets {
	header Connection *Upgrade*
	header Upgrade    websocket

The * on either side mean “allow any prefix or suffix”. This is important because the Connection header can include other information.

I think every header_up in your config is unnecessary, Caddy v2 forwards headers transparently by default, and even adds a couple that are commonly used for proxies:

Only use header_up lines if you’re actually sure you need them.


Best to make sure you specify a port here. You can either put http://, or :80.

Unfortunately it’s not possible yet to do this from the Caddyfile, but it is possible from JSON config.

There’s a PR here that’s adding support to the Caddyfile, but it’s not complete yet. It’s close though. Might be ready for next release, but maybe not.

Basically, handle_errors is just for errors emitted by Caddy itself, i.e. handlers like file_server, etc. Technically, a 404 from an upstream server is not an error from the perspective of Caddy, it’s a totally valid response. The reverse_proxy handler typically will just write the response directly. The handle_response option of the reverse_proxy is meant to give you an opportunity to do something with the response depending on the status or header (and it totally throws away the response body from the proxy in that case).

1 Like

This topic was automatically closed after 30 days. New replies are no longer allowed.