Error Medic

Resolving "502 Bad Gateway" in Nginx: Comprehensive Troubleshooting Guide

Fix the Nginx 502 Bad Gateway error. Learn to diagnose upstream failures (PHP-FPM, Gunicorn, Node), reverse proxy timeouts, and permission denied issues.

Last updated:
Last verified:
1,892 words
Key Takeaways
  • Check the Nginx error logs (/var/log/nginx/error.log) first to identify the exact failing upstream backend.
  • Verify that the upstream service (PHP-FPM, Gunicorn, Node.js, Tomcat) is actively running and bound to the correct port or Unix socket.
  • Resolve 'failed (13: Permission denied)' errors by fixing SELinux policies, AppArmor profiles, or correcting socket file ownership.
  • Adjust proxy_read_timeout, fastcgi_read_timeout, and buffer sizes for backend applications that generate large headers or process long-running queries.
502 Fix Approaches Compared
MethodWhen to UseTimeRisk
Analyze Nginx Error LogsAlways the required first step for any 502 error5 minsNone
Restart Upstream ServicesBackend process crash (PHP-FPM, Node, Gunicorn, etc.)2 minsLow
Fix Unix Socket PermissionsLog shows '13: Permission denied' for .sock files10 minsMedium
Increase Proxy TimeoutsHeavy requests causing backend to timeout (e.g., Magento 2)5 minsLow
Adjust SELinux BooleanCentOS/RHEL blocking Nginx network connections5 minsHigh

Understanding the 502 Bad Gateway Error in Nginx

When you encounter a 502 Bad Gateway error in Nginx, it fundamentally means that Nginx—acting as a reverse proxy or gateway—received an invalid, incomplete, or entirely absent response from the upstream server it was trying to communicate with. Nginx is designed to sit in front of your core application servers (like PHP-FPM, Gunicorn, uWSGI, Node.js, or Tomcat) to handle HTTP routing, SSL termination, and static file delivery. If that backend server crashes, drops the connection prematurely, or is improperly configured, Nginx will immediately serve a 502 page to the client.

Whether you are running an older stable release like Nginx 1.14.2 on Ubuntu 18.04, an intermediate version like Nginx 1.18.0 on Ubuntu 20.04, or modern releases like Nginx 1.22.0 or 1.23.1 on AWS EC2, the fundamental architecture of a 502 error remains identical. The error is almost never a bug or failure within the Nginx daemon itself. Instead, it is an issue with the backend service or the communication channel linking Nginx and that backend.

Step 1: Diagnose with Nginx Error Logs

The absolute first step in troubleshooting any Nginx 502 error is to check the error logs. Guessing will lead you down the wrong path; the log file will tell you exactly what system component failed.

Open your terminal and run the following command to tail the log:

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

You will typically see one of three highly specific upstream error signatures:

  1. connect() failed (111: Connection refused) while connecting to upstream
  2. connect() to unix:/var/run/php/php8.1-fpm.sock failed (13: Permission denied)
  3. upstream prematurely closed connection while reading response header from upstream

Step 2: Fixing Upstream Service Failures (Connection Refused)

If your error log shows Connection refused, it indicates that Nginx attempted to forward the HTTP request, but nothing was actively listening on the defined port or socket.

For PHP Applications (Laravel, WordPress, Magento 2): Modern PHP applications utilize PHP-FPM (FastCGI Process Manager). If the PHP-FPM daemon crashes due to memory exhaustion, Nginx has no way to serve dynamic .php files.

  • Check the service status: systemctl status php8.1-fpm (adjust the version number to match your environment).
  • Restart the service: sudo systemctl restart php8.1-fpm.
  • If it continues crashing, investigate the PHP-FPM logs located in /var/log/php8.1-fpm.log for fatal errors or child processes hitting memory limits.

For Python Applications (Django, Flask via Gunicorn/uWSGI): When using Python frameworks, Gunicorn or uWSGI must be running and bound to the exact port or socket defined in your Nginx proxy_pass directive. For example, if Nginx expects Gunicorn to be listening on 127.0.0.1:8000 but the Gunicorn service failed to boot due to a syntax error in your Python code, you will receive a 502.

  • Check Gunicorn systemd logs: journalctl -u gunicorn --no-pager | tail -n 50.

For Node.js / React SSR / Angular: If your Node backend (often managed by tools like PM2 or Systemd) crashes due to an unhandled JavaScript exception, Nginx is left stranded.

  • Check PM2 application status: pm2 status and analyze the error output via pm2 logs.

Step 3: Resolving "Permission Denied" Errors

One of the most frequent and heavily searched causes of a 502 is the failed (13: Permission denied) error. This manifests in a few different operational contexts:

1. Unix Socket Permissions: If Nginx communicates with PHP-FPM or Gunicorn via a Unix socket (e.g., /var/run/php/php8.1-fpm.sock), the Nginx worker process (usually running under the user www-data or nginx) must possess explicit read and write permissions to that specific socket file. If the socket file is mistakenly owned by root, Nginx will throw a 502.

  • The Fix: Check your PHP-FPM pool configuration file (e.g., /etc/php/8.1/fpm/pool.d/www.conf) and ensure the ownership directives are correct: listen.owner = www-data listen.group = www-data listen.mode = 0660 After modifying the file, restart PHP-FPM.

2. Process Execution Permissions (nginx.pid failed 13 permission denied): If you see emerg open() /var/run/nginx.pid failed (13: Permission denied) or bind to 0.0.0.0:80 failed (13: Permission denied), this is not a reverse proxy issue. This indicates you are attempting to start the Nginx master process as a standard non-privileged user. Operating systems require root (administrator) privileges to bind network interfaces to well-known ports under 1024 (like port 80 for HTTP and 443 for HTTPS).

  • The Fix: Always manage the Nginx daemon via systemd using sudo: sudo systemctl start nginx.

3. SELinux Restrictions on CentOS/RHEL/AlmaLinux: If you are operating on a Red Hat-based distribution, Security-Enhanced Linux (SELinux) is often configured strictly by default. It actively blocks the Nginx process from initiating outbound network connections to upstream application servers, resulting in a 502 Bad Gateway.

  • The Fix: You must explicitly allow HTTP network connections by modifying the SELinux boolean. Run: sudo setsebool -P httpd_can_network_connect 1.

Step 4: Timeouts and Proxy Buffer Limitations

Sometimes, a 502 Bad Gateway is fundamentally a timeout in disguise, or an internal buffer overflow caused by an exceptionally large HTTP response header generated by the upstream server.

Handling Long-Running Processes: If your e-commerce platform (like Magento 2) or a complex Laravel background job takes too long to execute a heavy database query, Nginx may assume the backend has died and drop the connection prematurely. You need to instruct Nginx to wait longer. Add these directives to your relevant location block in nginx.conf:

location / {
    proxy_pass http://127.0.0.1:8080;
    proxy_read_timeout 300s;
    proxy_connect_timeout 75s;
    proxy_send_timeout 300s;
    
    # If using PHP-FPM instead of proxy_pass, use:
    fastcgi_read_timeout 300s;
}

Fixing Header Buffer Overflows: Applications like Keycloak, Home Assistant, or heavy Magento installations often return massive authentication cookies or headers. Nginx has strictly defined default buffer sizes. If the backend response header exceeds this buffer, Nginx throws a 502.

  • The Fix: Increase the buffer sizes in your nginx.conf:
proxy_buffer_size 128k;
proxy_buffers 4 256k;
proxy_busy_buffers_size 256k;
fastcgi_buffer_size 128k;
fastcgi_buffers 4 256k;

Step 5: Environment-Specific Nuances

Docker / Nginx Proxy Manager / Unraid: If you are running Nginx Proxy Manager within a Docker container to expose services like Home Assistant, a 502 usually means the proxy container cannot successfully route network traffic to the destination IP address. Ensure you are utilizing the Docker bridge network IP or the host machine's static IP. Do not use localhost or 127.0.0.1 in the Nginx Proxy Manager UI, as that will point to the interior of the isolated proxy container itself, not your host machine.

Cloud Environments (AWS EC2, Elastic Beanstalk): On AWS architectures, a transient 502 Bad Gateway frequently occurs during application deployment phases when the old application container or process is spun down slightly before the new one is fully initialized and ready to accept traffic. To mitigate this, implement zero-downtime rolling deployments utilizing Elastic Load Balancer (ELB) health checks. This ensures the router will prevent sending live user traffic to an unready backend instance.

Control Panels (Plesk, cPanel): In managed environments like Plesk or cPanel, Nginx is often utilized strictly as an aggressive caching frontend reverse proxy to Apache. If you receive a 502 here, it generally means the backend Apache service has failed. You should immediately investigate the Apache error logs (/var/log/apache2/error.log or /usr/local/apache/logs/error_log) and utilize the control panel's service manager to restart the httpd daemon.

Conclusion

Resolving a 502 Bad Gateway in Nginx necessitates a calm, systematic diagnostic approach. The Nginx error log is your definitive roadmap. Once you identify the specific failure signature—whether that is a dead upstream service, an aggressive SELinux permission restriction, or a simple timeout on a heavy database query—applying the correct infrastructure fix becomes a straightforward task. Always ensure you syntactically validate your configuration (sudo nginx -t) and reload the daemon (sudo nginx -s reload) after implementing any modifications.

Frequently Asked Questions

bash
# 1. Test Nginx configuration for syntax errors
sudo nginx -t

# 2. View the last 50 lines of the error log to find the root cause
sudo tail -n 50 /var/log/nginx/error.log

# 3. Check status of common upstream services
sudo systemctl status php8.1-fpm
sudo systemctl status gunicorn
sudo systemctl status docker

# 4. Fix socket permissions (if using PHP-FPM unix sockets)
# Edit /etc/php/8.1/fpm/pool.d/www.conf and ensure:
# listen.owner = www-data
# listen.group = www-data

# 5. Reload Nginx to apply changes
sudo systemctl reload nginx
E

Error Medic Editorial

The Error Medic Editorial team consists of senior SREs, systems administrators, and DevOps engineers dedicated to demystifying complex web server architecture, resolving downtime, and sharing production-ready infrastructure solutions.

Sources

Related Articles in Nginx

Explore More Linux Sysadmin Guides