How to have a reverse_proxy fallback

1. Caddy version (caddy version):

v2.4.3 h1:Y1FaV2N4WO3rBqxSYA8UZsZTQdN+PwcoOcAiZTM8C0I=

2. How I run Caddy:

caddy run

a. System environment:

MacOS 11.5.2

b. Command:

caddy run

d. My complete Caddyfile or JSON config:

:2016

@matcher_front {
    header_regexp host Host ^front
}
reverse_proxy @matcher_front 127.0.0.1:3000 127.0.0.1:8080 {
    lb_policy first
    @error status 500 502 503
    handle_response @error {
		reverse_proxy * 127.0.0.1:8080
	}
}

3. The problem I’m having:

What I’m trying to achieve, is having a fallback URL for one of my proxy servers. I have a route that matches correctly to my local :3000 port. However if that service is not up, I’d like the request to be forward to a different service at port :8080 which will run some logic and then will start-up the service at :3000.

4. Error messages and/or full log output:

This is what gets logged when I make a request with my service on 3000 down:

2021/08/24 02:53:41.822	ERROR	http.log.error	dial tcp 127.0.0.1:3000: connect: connection refused	{"request": {"remote_addr": "127.0.0.1:52749", "proto": "HTTP/1.1", "method": "GET", "host": "front:2016", "uri": "/", "headers": {"Upgrade-Insecure-Requests": ["1"], "Accept": ["text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9"], "Accept-Encoding": ["gzip, deflate"], "Connection": ["keep-alive"], "Pragma": ["no-cache"], "Cache-Control": ["no-cache"], "User-Agent": ["Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36"], "Accept-Language": ["en-US,en;q=0.9"]}}, "duration": 0.000322875, "status": 502, "err_id": "08gevucx1", "err_trace": "reverseproxy.statusError (reverseproxy.go:857)"}

5. What I already tried:

I tried adding the :8080 as another upstream to my reverse_proxy list, with first as the strategy, hoping if the first one is down it’ll just hit the 8080 instead, but that didn’t work.

I also tried using the handle_response, to route there, but that also doesn’t get called (I assume because there’s no status code)

I’m very new to caddy, and just going off the docs. Can this be done?

For Caddy to try to select the next backend when using lb_policy first, the first backend must be marked as unhealthy.

You can do this in one of three ways:

  • Use lb_try_duration to configure Caddy to continue trying to choose a upstream for this amount of time, if an error occurred when trying to connect (and make sure to configure dial_timeout for transport http to a value smaller than the try duration, so that Caddy will give up trying to connect before the try duration expires). Note that this method doesn’t mark the upstream as unhealthy.

  • Enable passive health checks. At minimum fail_duration must be configured for this. This is essentially reading the result of the proxy attempt, and if it failed according to the rules configured, then it will be marked unhealthy for fail_duration amount of time.

  • Enable active health checks. Caddy will run an worker outside of the request-response flow which will make requests to your upstreams to see if they’re still alive. This will mark the upstream as unhealthy if the health rules are not met.

Yeah – handle_response will only trigger if a successful roundtrip happened from the backend. In this case, an error happened in Caddy, so the way to handle these would be the handle_errors routes.

2 Likes

Thank you!

Adding lb_try_duration and fail_duration solved my problem!

1 Like

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