Load balancing between reverse_proxy

1. The problem I’m having:

Hello,

Context :
I’m trying to configure a host to serve a nextjs app. In order to avoid any downtime when publishing, I have setup a “blue-green” deployment following this post

Ofc, I don’t use nginx but Caddy so I’m trying to make the configuration for Caddy.

TL;DR, I have two nextjs running through pm2, one on port 3000 and the other one on port 3001.
Only one is running at a time.

The result is a 502 error.

The configuration works if I only have the running nextjs as the reverse_proxy

2. Error messages and/or full log output:

{"level":"error","ts":1732899944.9000401,"logger":"http.log.error.log0","msg":"dial tcp 127.0.0.1:3001: connect: connection refused","request":{"remote_ip":"80.201.38.152","remote_port":"60471","client_ip":"80.201.38.152","proto":"HTTP/1.1","method":"GET","host":"myhub.inowai.com","uri":"/","headers":{"User-Agent":["curl/8.9.1"],"Accept":["*/*"]},"tls":{"resumed":false,"version":771,"cipher_suite":49195,"proto":"http/1.1","server_name":"myhub.inowai.com"}},"duration":0.006365153,"status":502,"err_id":"8cqe2r7z9","err_trace":"reverseproxy.statusError (reverseproxy.go:1269)"}

3. Caddy version:

v2.8.4

4. How I installed and ran Caddy:

Using the stable release doc on Install — Caddy Documentation

a. System environment:

Ubuntu 22.04.4

b. Command:

sudo systemctl (re)start|stop caddy

c. Service/unit/compose file:

PASTE OVER THIS, BETWEEN THE ``` LINES.
Please use the preview pane to ensure it looks nice.

d. My complete Caddy config:

(common) {
        # security stuff
        header /* {
                -Server
                X-Content-Type-Options nosniff
                X-Frame-Options DENY
                Strict-Transport-Security max-age=31536000;
        }
}

myhub.inowai.com {
        import common
        encode gzip zstd

        # Storage path for files
        root * /mnt/aiweb
        @exists file
        handle @exists {
                file_server
        }

        reverse_proxy localhost:3000  localhost:3001 

        file_server

        log {
                output file /var/log/caddy/inowai.log {
                        roll_keep 8
                        roll_keep_for 72h
                }
                format json
        }

        tls backend@opp.mx
}

5. Links to relevant resources:

The 502 error occurs because Caddy is trying to reverse proxy to both Next.js instances (on ports 3000 and 3001) at once, but only one is active.

To fix this:

  1. Ensure Only One Instance Is Running: Make sure only one Next.js app is active via pm2. Use pm2 list to check and stop the inactive instance.
  2. Update Caddy Configuration: Modify your Caddy config to proxy only to the active port (e.g., localhost:3000). Example:
    reverse_proxy localhost:3000
    
  3. Automate the Process: Use a script to detect which Next.js app is running and update Caddy’s config automatically.

This should resolve the 502 error by ensuring Caddy proxies to the correct instance.

None of this is correct. Please don’t post AI slob.

Your configuration is close. You’re missing configuring the load balancing policy (directive: lb_policy). Caddy defaults to random, which is why your config might work sometimes. You likely need first, whose documentation says:

first chooses the first available upstream, from the order they are defined in the config, allowing for primary/secondary failover; remember to enable health checks along with this, otherwise failover will not occur.

I think your reverse_proxy part should look like this. The docs recommend having health check so the load balancer knows which upstream is healthy, so consider adding an endpoint that returns 200 when the app is up.


	reverse_proxy localhost:3000 localhost:3001 {
		lb_policy first
		health_uri /health # configure such endpoint in your app
	}

2 Likes

Thank you so much Mohammed, this was the missing pieces !