DevOpsil
Nginx
87%
Needs Review

Fix Nginx 502 Bad Gateway Behind a Reverse Proxy

Aareez AsifAareez Asif3 min read

The Error: 502 Bad Gateway

Users see a blank page with:

502 Bad Gateway
nginx/1.24.0

In Nginx's error log (/var/log/nginx/error.log):

2026/03/30 14:22:01 [error] 1234#0: *5678 connect() failed
(111: Connection refused) while connecting to upstream,
client: 203.0.113.50, upstream: "http://127.0.0.1:3000/", request: "GET / HTTP/1.1"

Nginx received the client request but could not get a valid response from the upstream backend.

Root Cause

A 502 means the reverse proxy contacted the upstream server and either:

  1. Upstream is not running — the backend process crashed or was not started
  2. Wrong upstream address/port — Nginx is proxying to the wrong socket
  3. Upstream is too slow — the backend did not respond within the timeout
  4. Socket permission denied — Nginx cannot connect to a Unix socket
  5. SELinux blockinghttpd_can_network_connect is disabled

Step-by-Step Fix

1. Check if the upstream is running

# For a TCP backend (e.g., Node.js on port 3000)
ss -tlnp | grep 3000

# For a Unix socket backend (e.g., Gunicorn)
ls -la /run/gunicorn/gunicorn.sock

# Check process status
systemctl status myapp
pm2 status

If the process is not running, start it. Check its logs for crash reasons.

2. Verify the proxy_pass target matches the backend

# Show the active Nginx config
nginx -T 2>/dev/null | grep proxy_pass

Compare the address and port with what the backend is actually listening on:

# Common mismatch: backend listens on 127.0.0.1:8000 but config says 3000
location / {
    proxy_pass http://127.0.0.1:3000;  # <-- must match the backend
}

3. Test the upstream directly

# Bypass Nginx and hit the backend
curl -v http://127.0.0.1:3000/

# If this also fails, the problem is the backend, not Nginx

4. Increase proxy timeouts

If the backend is slow (large file uploads, long queries):

location / {
    proxy_pass http://127.0.0.1:3000;
    proxy_connect_timeout 60s;
    proxy_send_timeout    60s;
    proxy_read_timeout    60s;
}

Reload Nginx:

sudo nginx -t && sudo systemctl reload nginx

5. Fix Unix socket permissions

If using a socket:

upstream backend {
    server unix:/run/gunicorn/gunicorn.sock;
}

Ensure Nginx's user can access the socket:

# Check socket ownership
ls -la /run/gunicorn/gunicorn.sock
# srw-rw---- 1 www-data www-data ...

# Nginx must run as www-data or be in the www-data group
grep -E '^user' /etc/nginx/nginx.conf

6. Fix SELinux (RHEL/CentOS/AlmaLinux)

# Check if SELinux is blocking
sudo ausearch -m AVC -ts recent | grep nginx

# Allow Nginx to connect to network backends
sudo setsebool -P httpd_can_network_connect 1

# For Unix sockets in non-standard paths
sudo semanage fcontext -a -t httpd_var_run_t "/run/myapp(/.*)?"
sudo restorecon -Rv /run/myapp

7. Check upstream health with multiple backends

upstream app_cluster {
    server 10.0.1.10:3000 max_fails=3 fail_timeout=30s;
    server 10.0.1.11:3000 max_fails=3 fail_timeout=30s;
    server 10.0.1.12:3000 backup;
}

location / {
    proxy_pass http://app_cluster;
    proxy_next_upstream error timeout http_502;
}

proxy_next_upstream tells Nginx to try the next server if one returns a 502.

Prevention Tips

  • Use a process manager (systemd, PM2, supervisord) to auto-restart crashed backends.
  • Add health check endpoints (/healthz) and monitor them separately from the application routes.
  • Set proxy_next_upstream to fail over to healthy backends automatically.
  • Monitor Nginx error logs — alert on 502 spikes using tail -f /var/log/nginx/error.log piped to your alerting stack.
  • Use keepalive connections to reduce socket churn between Nginx and upstreams:
    upstream backend {
        server 127.0.0.1:3000;
        keepalive 32;
    }
    
Share:

Was this article helpful?

Aareez Asif
Aareez Asif

Senior Kubernetes Architect

10+ years orchestrating containers in production. Battle-tested opinions on everything from pod scheduling to service mesh. I've seen clusters burn and helped rebuild them better.

Related Articles

More in Nginx

View all →

Discussion