How to Fix Nginx 502 Bad Gateway: A Complete Troubleshooting Guide
We have all been there. You deploy a shiny new feature, push it to production, grab your coffee, and open your site expecting to see your masterpiece. Instead, you are greeted by a stark, frustrating screen displaying: 502 Bad Gateway.
If you are searching for how to fix nginx 502 bad gateway, take a deep breath. You are in the right place. As a senior developer who has spent countless nights debugging reverse proxy issues, I can tell you that the 502 error is the bane of every DevOps engineer’s existence—but it is also highly fixable once you understand the mechanics behind it.
Welcome back to Sexy Developer. Today, we are rolling up our sleeves, diving into the trenches, and mastering the art of diagnosing and resolving the Nginx 502 Bad Gateway error.
Understanding the 502 Bad Gateway Error
Before we start fixing things, we need to understand what a 502 error actually means.
Nginx is rarely the actual problem. In most modern web architectures, Nginx acts as a reverse proxy. It sits at the front door, takes requests from the internet, and passes them along to an upstream server (like Node.js, Python/Gunicorn, PHP-FPM, or a Go API) sitting safely behind it.
A 502 Bad Gateway error officially means that Nginx successfully received the request from the client, but when it forwarded that request to the upstream server, the response it got back was invalid, incomplete, or entirely non-existent.
Think of Nginx as a highly efficient receptionist. The client asks for a document. The receptionist walks to the back office (the upstream server) to get it. If the back office is empty, on fire, or hands the receptionist gibberish, the receptionist comes back to the client and says, “502 Bad Gateway—I tried, but the back office failed me.”
Step-by-Step Root Cause Analysis
Fixing a 502 error is a process of elimination. Let’s walk through the most common root causes, from the most frequent offenders to the edge cases, and exactly how to solve them.
1. The Upstream Server is Down or Crashed
The absolute most common reason for a 502 error is that the backend application has crashed, hasn’t started yet, or is stuck in an infinite loop. Nginx is trying to connect to port 3000 (or 8080, or a Unix socket), but nothing is picking up the phone.
How to Diagnose
Check the status of your backend application. If you are running it via systemd, use systemctl:
sudo systemctl status your-backend-service
If you are running a Node.js app using a process manager like PM2:
pm2 list
pm2 logs
If you are running containers via Docker or Docker Compose:
docker ps -a
docker-compose ps
docker logs <container_name>
How to Fix
If the service is inactive or exited, restart it and look for application-level errors.
# Restarting a systemd service
sudo systemctl restart your-backend-service
# Restarting a PM2 application
pm2 restart app-name
# Restarting a Docker container
docker restart <container_name>
Pro Tip: Don’t just restart and walk away. Look at the logs. Did it run out of memory (OOM Killed)? Did a syntax error crash the runtime? If you don’t fix the underlying application error, the 502 will return tomorrow.
2. Port and Socket Mismatches
Sometimes the backend is running perfectly fine, but Nginx is knocking on the wrong door. This happens frequently during deployments when environment variables or configuration files are out of sync.
How to Diagnose
First, find out exactly what Nginx is trying to connect to. Check your Nginx configuration (usually found in /etc/nginx/sites-available/ or /etc/nginx/conf.d/):
location / {
proxy_pass http://127.0.0.1:8080;
}
Now, go to your server’s terminal and check if anything is actually listening on port 8080:
sudo netstat -tulpn | grep 8080
# OR
sudo ss -tulpn | grep 8080
How to Fix
If the netstat or ss output shows your app listening on 3000 instead of 8080, you have a mismatch. You need to update either your application’s start script or your Nginx configuration so they match perfectly.
If using a Unix socket (common with PHP-FPM), verify the socket file actually exists:
ls -l /run/php/php8.2-fpm.sock
If it doesn’t exist, PHP-FPM isn’t running, or its configuration is pointing to a different socket path.
3. Analyzing Nginx Error Logs for Clues
When dealing with how to fix nginx 502 bad gateway, the Nginx error log is your best friend. It will tell you exactly why Nginx gave up.
How to Diagnose
Open a terminal and tail the Nginx error log in real-time while you refresh your website:
sudo tail -f /var/log/nginx/error.log
Look for specific error strings:
* Connection refused: Nginx reached the server, but nothing is listening on that port. (Refer back to Step 2).
* No such file or directory: Nginx is configured to use a Unix socket, but the socket file doesn’t exist.
* Connection timed out: The upstream server is too busy to respond. (This technically throws a 504 Gateway Timeout, but can sometimes manifest as a 502 depending on Nginx configuration).
4. Permission and Ownership Issues
Linux security is strict. If Nginx does not have the proper permissions to read files or communicate via a socket, it will fail. This is especially common when setting up PHP applications or using Unix sockets for Node/Python apps.
How to Diagnose
Check the permissions of your application’s socket file or web root directory:
ls -la /var/run/my_app.sock
If the file is owned by root or a specific user, and Nginx is running as www-data (on Ubuntu/Debian) or nginx (on CentOS/RHEL), it might not have read/write access to the socket.
How to Fix
Ensure the Nginx user has access to the upstream socket or files. You can add the Nginx user to the application’s user group, or modify the socket permissions in your backend’s configuration.
For example, if your Node app creates a socket, ensure it grants read/write permissions to others:
// Node.js http server example
server.listen('/tmp/my_app.sock', () => {
// Grant read/write permissions to Nginx
require('fs').chmodSync('/tmp/my_app.sock', 0o666);
console.log('Server listening on socket');
});
For web root file permissions, standard practice is:
sudo chown -R www-data:www-data /var/www/html
sudo find /var/www/html -type d -exec chmod 755 {} \;
sudo find /var/www/html -type f -exec chmod 644 {} \;
5. Upstream Sent Too Big Header (Buffer Issues)
This is a tricky edge case that catches many developers off guard. Your backend is working, it processes the request, and it sends back a response. But the HTTP headers are too large for Nginx’s default buffer size. This often happens if your application sets massive cookies, or if you are passing large authentication tokens (like heavy JWTs).
Nginx will drop the connection and throw a 502 error, and in the error log, you will see: upstream sent too big header while reading response header from upstream.
How to Fix
You need to increase the fastcgi or proxy buffer sizes in your Nginx configuration.
Open your Nginx server block configuration and add the following directives inside the location block:
# If using PHP-FPM (FastCGI)
location ~ \.php$ {
fastcgi_pass unix:/run/php/php8.2-fpm.sock;
fastcgi_buffer_size 128k;
fastcgi_buffers 4 256k;
fastcgi_busy_buffers_size 256k;
# ... other fastcgi params
}
# If using Proxy Pass (Node.js, Python, Go, etc.)
location / {
proxy_pass http://127.0.0.1:3000;
proxy_buffer_size 128k;
proxy_buffers 4 256k;
proxy_busy_buffers_size 256k;
}
Test your configuration and reload Nginx:
sudo nginx -t
sudo systemctl reload nginx
6. DNS Resolution Failures within Nginx
If your Nginx configuration proxies requests to an external hostname rather than a local IP (e.g., proxy_pass http://api.internal-network.local;), Nginx has to resolve that domain name. By default, Nginx resolves domain names only at startup. If the IP address of that upstream changes later, Nginx will keep trying to use the old, stale IP address, resulting in a 502.
How to Fix
To resolve this, you must use a resolver directive. This forces Nginx to dynamically resolve the domain name based on a reliable DNS server (like Google’s 8.8.8.8 or AWS’s internal DNS).
resolver 8.8.8.8 valid=30s;
location /api {
# Using a variable forces Nginx to use the resolver
set $upstream_endpoint http://api.internal-network.local;
proxy_pass $upstream_endpoint;
}
By putting the URL into a variable (like $upstream_endpoint), Nginx is forced to re-evaluate and re-resolve it on demand, ensuring it always knows the correct IP address of your upstream service.
Advanced Edge Cases
If you have gone through the steps above and are still wondering how to fix nginx 502 bad gateway, you might be dealing with an infrastructure-level edge case.
Keepalive Connections Dropping
Sometimes Nginx maintains a keepalive connection to the upstream server. The upstream server closes the connection after a timeout, but Nginx tries to use it again, resulting in a reset connection and a 502 error.
You can mitigate this by matching the keepalive_timeout in your upstream server to Nginx, or by explicitly configuring Nginx’s upstream keepalive settings:
upstream backend {
server 127.0.0.1:8080;
keepalive 32;
}
server {
location / {
proxy_pass http://backend;
proxy_http_version 1.1;
proxy_set_header Connection "";
}
}
*Telling Nginx to use HTTP/1