CRITICAL

How to Fix 502 Bad Gateway in Nginx on Ubuntu 24.04 LTS

Quick Fix Summary

TL;DR

Restart your PHP-FPM or upstream application service and verify the upstream server is reachable from Nginx.

A 502 Bad Gateway indicates Nginx successfully received a request but failed to get a valid response from its upstream server (e.g., PHP-FPM, Gunicorn, another backend). This is a proxy-level error, not a client-side issue.

Diagnosis & Causes

  • Upstream service (PHP-FPM, Gunicorn) is stopped or crashed.
  • Firewall or SELinux blocking Nginx from connecting to upstream.
  • Upstream server timeout due to overload or slow processing.
  • Incorrect socket or port in Nginx's upstream configuration.
  • Resource exhaustion (memory, sockets) on the upstream server.
  • Recovery Steps

    1

    Step 1: Verify Upstream Service Status

    First, confirm if your backend application or process manager is running.

    bash
    sudo systemctl status php8.3-fpm
    sudo systemctl status gunicorn
    sudo ss -tlnp | grep :9000
    2

    Step 2: Restart the Upstream Service

    If the service is down or unstable, restart it and check logs for crash reasons.

    bash
    sudo systemctl restart php8.3-fpm
    sudo journalctl -u php8.3-fpm --since "5 minutes ago" -f
    3

    Step 3: Test Connectivity from Nginx to Upstream

    Simulate Nginx's connection attempt to rule out network or permission issues.

    bash
    # Test TCP connection (for port-based upstream)
    sudo apt-get install -y netcat
    nc -zv 127.0.0.1 9000
    # Test Unix socket permissions
    sudo ls -la /var/run/php/php8.3-fpm.sock
    4

    Step 4: Check Nginx Error Logs for Specific Upstream Errors

    Nginx logs the precise reason for the upstream failure. This is the most diagnostic step.

    bash
    sudo tail -50 /var/log/nginx/error.log
    # Look for lines containing 'connect() failed', 'upstream timed out', or 'Connection refused'
    5

    Step 5: Adjust Nginx Proxy Timeouts

    If logs show timeouts, increase proxy buffers and timeouts to handle slow backends.

    bash
    # Edit your site configuration in /etc/nginx/sites-available/
    sudo nano /etc/nginx/sites-available/your_site
    # Inside the location block for PHP or proxy_pass, add:
    proxy_read_timeout 300s;
    proxy_connect_timeout 75s;
    fastcgi_read_timeout 300s;
    # Test and reload Nginx
    sudo nginx -t && \
      sudo systemctl reload nginx
    6

    Step 6: Inspect Upstream Server Resource Limits

    PHP-FPM may hit `pm.max_children` or memory limits, causing it to reject connections.

    bash
    sudo nano /etc/php/8.3/fpm/pool.d/www.conf
    # Check and adjust: pm.max_children, pm.max_requests, php_admin_value[memory_limit]
    sudo systemctl restart php8.3-fpm

    Architect's Pro Tip

    "For intermittent 502s, monitor `netstat -s | grep 'listen'` for overflowed socket queues and increase the `net.core.somaxconn` kernel parameter."

    Frequently Asked Questions

    I restarted PHP-FPM and the 502 went away, but it came back hours later. What's wrong?

    This points to a resource leak or gradual exhaustion. Your PHP-FPM `pm.max_requests` setting is likely too high or a memory leak in the application is causing workers to die. Lower `pm.max_requests` to recycle workers periodically and monitor PHP-FPM pool status with `sudo systemctl status php8.3-fpm`.

    The Nginx error log says '111: Connection refused'. What does this mean?

    This means Nginx tried to connect to the socket or port defined in `fastcgi_pass` or `proxy_pass` (e.g., 127.0.0.1:9000) and the operating system refused it. The upstream service is not listening on that port. Verify the service is running and the configuration points to the correct address.

    Should I use a Unix socket or TCP port for PHP-FPM with Nginx?

    For single-server setups, a Unix socket (`unix:/var/run/php/php8.3-fpm.sock`) is slightly faster and more secure as it avoids the network stack. For multi-server setups or containerized environments, a TCP port (`127.0.0.1:9000`) is necessary. Ensure socket file permissions allow the `www-data` user (Nginx) to read/write it.

    Related Linux Guides