Customize second reverse_proxy upstream configuration

I am trying to customize the reverse_proxy directive so I can modify the options for the second upstream.
I want to use the second upstream as a maintenance page that gives a 503 error.

The problem I have is that Caddy in front of traefik, I’m using traefik for ingress but traefik will just give a 404 if the host is down due. Doing an @error handle_response would not be appropriate as every 404 request would suddenly be presented with this maintenance screen.

Adding a second host under reverse_proxy for loadbalancing is almost perfect, however, it presents an HTTP 200 Status, which is not what I need. I need the second upstream to give a 503 status, however, I can’t seem to figure out how to modify the reverse proxy only for the second upstream.

I also can’t just reverse_proxy the maintenance page to a local address then pass that as the second upstream, because the header_up {upstream_hostport} is set so that it can work with traefik to begin with. Same deal if I hosted the maintenance page through caddy directly, it would be a local address and I can’t combine that with the required headers for speed.local.network

Current setup:


(headers) {
        header_up Host {upstream_hostport}
        header_up X-Real-IP {remote_host}
        transport http {
                tls_insecure_skip_verify
        }
}

(healthcheck) {
        health_uri /
        health_interval 5s
        health_timeout 5s
        health_status 2xx
}

speed.example.com {
        reverse_proxy https://librespeed.local.network https://maintenance.local.network {
                import headers
                import healthcheck
        }
}

You probably want lb_policy first, otherwise a random upstream will be chosen.

Can’t you change that upstream app itself to serve that status code?

Why do you have traefik at all? If you’re using it for a Docker stack, Caddy can do the same with GitHub - lucaslorentz/caddy-docker-proxy: Caddy as a reverse proxy for Docker

1 Like

Thanks for the suggestion, I figured out how to enable a custom HTTP status code. However its a “Maintenance mode” option that will serve that code for the whole webserver.

Only problem, caddy now won’t load balance to the maintenance page because the healthcheck requires a 2xx code, and the maintenance site (on purpose) is now serving a 503.
I haven’t figured out a way to allow 2 different types of HTTP codes. If I could have it allow 2xx and just 503 that would work.

I will look into caddy for docker but most of my stuff is on Kubernetes because I’m using helm charts on TrueNAS scale, which only lets me use traefik for ingress, but using caddy for my gateway on a VM

You can probably do this:

(headers) {
	header_up Host {upstream_hostport}
	header_up X-Real-IP {remote_host}
	transport http {
		tls_insecure_skip_verify
	}
}

(healthcheck) {
	health_uri /
	health_interval 5s
	health_timeout 5s
	health_status 2xx
}

speed.example.com {
	reverse_proxy https://librespeed.local.network {
		import headers
		import healthcheck
	}

	handle_errors {
		reverse_proxy https://maintenance.local.network {
			import headers
		}
	}
}

When your primary is unhealthy, Caddy will trigger an error which you can handle with handle_errors, by making another request to your maintenance upstream.

1 Like

Wow, didn’t realize I could use handle_errors to handle errors only when the healthcheck fails.

Absolutely amazing, just what I needed.

You sir, seriously rock!

1 Like

handle_errors is for handling errors emitted by other handlers, not for handling 5xx status responses from an upstream; 5xx responses don’t count as errors, they’re just a response.

"no upstreams available" is the error reverse_proxy will emit when all upstreams are unhealthy, which can be rehandled with handle_errors.

1 Like

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