VMHeaven

Troubleshooting

nginx 502 Bad Gateway — it is your upstream, not nginx

A 502 means nginx could not reach your app. Read the error log, then fix the four causes: upstream down, wrong socket, timeout, or socket permissions.

Updated 08 Aug 2026~6 min read

A 502 Bad Gateway from nginx means nginx is working fine — it is your upstream that failed. nginx tried to hand the request to your application (PHP-FPM, a Node process, gunicorn, another server) and got nothing usable back. So you debug the thing behind nginx, not nginx itself.

Always start with the error log

The log names the exact reason. Read it before touching config:

tail the error log
sudo tail -n 50 /var/log/nginx/error.log

The message points straight at the cause:

  • connect() failed (111: Connection refused) — the upstream is not running.
  • no live upstreams — every backend nginx knows about is down.
  • upstream timed out — the backend is alive but too slow.
  • connect() to unix:/…​.sock failed — wrong socket path or permissions.

Cause 1: the upstream is not running

check + restart the backend
# pick the one you use
sudo systemctl status php8.3-fpm
sudo systemctl status your-node-app
sudo systemctl restart php8.3-fpm

Confirm it is actually listening where nginx expects. If nginx proxies to 127.0.0.1:3000, that port must show up here:

is the backend listening?
sudo ss -tlnp | grep -E ':3000|php|fpm'

Cause 2: wrong socket or port in the config

The fastcgi_pass or proxy_pass target must match what the backend binds. A PHP upgrade that changes the socket path (php8.2-fpm.sock php8.3-fpm.sock) is a classic trigger:

check the mismatch
grep -R "fastcgi_pass\|proxy_pass" /etc/nginx/
ls /run/php/    # what socket actually exists?

Cause 3: the backend is too slow

If the log says timed out, the app works but exceeds nginx’s patience. Raise the timeout as a stopgap, but fix the slow code or add resources for a real cure:

raise proxy timeout
# in the location or server block
proxy_read_timeout 120s;
# then
sudo nginx -t && sudo systemctl reload nginx

Cause 4: socket permissions

When nginx and the backend run as different users, nginx may not be allowed to open the socket. Align the FPM pool’s listen.owner/listen.group with the nginx user (often www-data), then restart both.

Persistent 502s under traffic often mean the server is simply undersized. A Hi-CPU KVM plan gives PHP-FPM and Node the headroom to keep responses inside nginx’s timeout window.

Frequently asked

Is a 502 nginx's fault?

No. nginx is working — it tried to pass the request to your backend (PHP-FPM, Node, etc.) and got nothing usable. Debug the upstream, not nginx.

Where do I find the actual cause?

In /var/log/nginx/error.log. The message names it: 'connection refused' (upstream down), 'upstream timed out' (too slow), or a socket-path error.

502s appear only under load — why?

Usually PHP-FPM running out of workers or the server running out of RAM. Check 'free -m' and the FPM pm.max_children setting before raising the timeout.

More in Troubleshooting

See all