keepcalculator

06 Numbers and Powers

Fix 502 Bad Gateway: Nginx & Gunicorn Guide

Card No. 06·34777 · Updated · Standard formula, shown below

This guide walks you through diagnosing and fixing a 502 Bad Gateway error when using Nginx as a reverse proxy in front of Gunicorn. The error means Nginx couldn’t get a valid response from Gunicorn, so you’ll check Gunicorn’s status, socket configuration, and Nginx’s proxy settings, then restart both services.

What You’ll Need

  • SSH access to your server (or a terminal if running locally)
  • sudo privileges
  • Your project’s directory path (where your WSGI app lives)
  • Basic familiarity with the command line

Step-by-Step

  1. Check if Gunicorn is running. Run ps aux | grep gunicorn. If you see no gunicorn processes, it’s not running. If it’s running, note the PID and the bind address (e.g., 127.0.0.1:8000 or a socket file).
  2. If Gunicorn isn’t running, start it manually. Navigate to your project directory and run: gunicorn --workers 3 --bind 127.0.0.1:8000 myapp:app (replace myapp:app with your WSGI entry point). If it starts without errors, the problem was simply that Gunicorn was down. If it fails, read the error output—it usually points to a missing module, a syntax error, or a permission issue.
  3. If Gunicorn is running, test it directly. From your server, run curl http://127.0.0.1:8000 (or the address you configured). If you get HTML or a JSON response, Gunicorn is working. If you get a connection refused, it’s not listening on the expected address/port.
  4. Check the Nginx error log. Run sudo tail -f /var/log/nginx/error.log and then try to access your site. The log will show the exact upstream error, like connect() failed (111: Connection refused) while connecting to upstream or upstream prematurely closed connection while reading response header from upstream.
  5. Verify the Nginx configuration. Open your Nginx site config (usually in /etc/nginx/sites-available/ or /etc/nginx/conf.d/) and check the proxy_pass directive. It must match exactly where Gunicorn is listening. If Gunicorn is on 127.0.0.1:8000, then proxy_pass http://127.0.0.1:8000; is correct. If you’re using a Unix socket, it should be proxy_pass http://unix:/path/to/gunicorn.sock;.
  6. Check file permissions for socket files. If you use a Unix socket, ensure the directory containing the socket is writable by the user that runs Gunicorn (often www-data or ubuntu). Run sudo chown www-data:www-data /path/to/socketfile.sock if needed.
  7. Restart both services. After any config change, run sudo systemctl restart gunicorn and sudo systemctl reload nginx. Then test your site again.
  8. If using a systemd service for Gunicorn, check its status. Run sudo systemctl status gunicorn. Look for lines like Active: failed or Active: inactive (dead). If it failed, journalctl -u gunicorn will show the full error log.

Common Mistakes

  • Mismatched bind addresses. Gunicorn listening on 127.0.0.1:8000 but Nginx proxying to localhost:8000 can cause issues if IPv6 is involved—use 127.0.0.1 explicitly.
  • Forgetting to restart Gunicorn after code changes. If your app crashes on startup, Gunicorn may stop. Always restart after deploying new code.
  • Socket file paths with typos. A single character difference in the socket path will cause a 502. Copy-paste the path from one config to the other.
  • Firewall blocking the port. If Gunicorn is on a non-standard port, ensure your firewall allows local connections (usually not an issue for localhost, but if Gunicorn is on a different interface, it matters).

Tips

  • Use a systemd service for Gunicorn. It auto-starts on boot and restarts after crashes. Example unit file: [Service] ExecStart=/usr/bin/gunicorn --workers 3 --bind 127.0.0.1:8000 myapp:app.
  • Increase Gunicorn timeout for slow endpoints. If your app takes more than 30 seconds to respond, add --timeout 60 to the Gunicorn command. Nginx also has a proxy_read_timeout (default 60s) that you might need to increase.
  • Set the number of workers to 2 * CPU cores + 1. This is a common rule of thumb for CPU-bound apps.
  • Test Nginx config before reloading. Run sudo nginx -t to catch syntax errors before applying.

Troubleshooting

If the 502 persists, work through these in order:

  1. Check if Gunicorn is actually running. ps aux | grep gunicorn again. Sometimes it dies silently after starting.
  2. Look at Gunicorn’s stdout/stderr. If you started it manually, the terminal shows the error. If it’s a service, use journalctl -u gunicorn.
  3. Try a simple test app. Create a file test.py with def app(environ, start_response): ... and run Gunicorn on it. If that works, the issue is in your app’s code.
  4. Check SELinux or AppArmor. On some systems, these can block Nginx from connecting to the socket. Temporarily set them to permissive mode to test (but re-enable after).
  5. Verify Nginx is running. sudo systemctl status nginx. If it’s not running, start it.
  6. Check for multiple Nginx configs. If you have both sites-enabled and conf.d entries for the same domain, they can conflict. Disable one.

Frequently Asked Questions

Why does my 502 happen only on some requests?

That usually means Gunicorn is crashing or timing out on specific requests—often due to a memory leak or a very slow endpoint. Check Gunicorn’s logs for tracebacks, and consider increasing the timeout or the number of workers.

Should I use a TCP port or a Unix socket?

Unix sockets are slightly faster because they avoid TCP overhead, but they require proper file permissions. TCP ports are easier to debug and work across containers. If you’re just starting, use a TCP port like 127.0.0.1:8000.

What does ‘upstream prematurely closed connection’ mean?

This means Gunicorn accepted the connection but closed it before sending a full response. Common causes: the worker crashed (check Gunicorn logs), the request took too long and the worker was killed, or the app raised an unhandled exception that closed the socket.

Can a 502 be caused by Nginx itself?

Yes, but less often. A misconfigured proxy_pass (wrong URL, missing trailing slash) or a syntax error in the Nginx config can cause it. Always run sudo nginx -t after editing.

How do I fix a 502 after a server reboot?

If Gunicorn isn’t configured to start on boot, it won’t be running after a reboot. Create a systemd service and enable it with sudo systemctl enable gunicorn. Also ensure Nginx starts on boot with sudo systemctl enable nginx.

My Gunicorn log shows ‘Address already in use’. What now?

Another process (maybe a previous Gunicorn instance) is using the port. Find it with sudo lsof -i :8000 and kill it with sudo kill -9 PID, then start Gunicorn again.

Related

Method: the standard formula for this calculation, rounded as each result states. See how the calculators work or report an error.

More cards in this drawer

The whole Numbers and Powers drawer →