How to Fix Nginx 502 Bad Gateway on AWS EC2
The Root Cause
Nginx 502 Bad Gateway on AWS EC2 typically indicates Nginx is unable to communicate with its designated upstream application server (e.g., PHP-FPM, Gunicorn, Node.js process). This often stems from the application process crashing due to resource exhaustion (like out-of-memory errors) specific to the EC2 instance’s size, or the application failing to start or bind to the expected port/socket.
Quick Fix (CLI)
# 1. Identify and check the status of your upstream application service.
# Replace 'your-application-service' with the actual service name (e.g., php-fpm, gunicorn, uwsgi, node-app).
# Example for PHP-FPM (versions vary, e.g., php7.4-fpm):
# sudo systemctl status php-fpm
# Example for a Gunicorn service managed by systemd:
# sudo systemctl status gunicorn
# 2. Review logs for the application service for specific errors (e.g., OOM, unhandled exceptions).
# sudo journalctl -xeu your-application-service -n 50
# 3. Attempt to restart the upstream application service.
# sudo systemctl restart your-application-service
# For PM2-managed Node.js apps: pm2 restart all
# 4. Restart Nginx to ensure it re-establishes connections to the upstream service.
sudo systemctl restart nginx
Configuration Check
Review your Nginx server block configuration, typically found in /etc/nginx/conf.d/*.conf or /etc/nginx/sites-available/*. Focus on the proxy_pass or fastcgi_pass directives within your location blocks to ensure they point to the correct address/port/socket where your application server is listening.
# Example for PHP-FPM (fastcgi_pass):
# Verify this path matches your PHP-FPM pool configuration (e.g., /etc/php/7.4/fpm/pool.d/www.conf 'listen' directive).
location ~ \.php$ {
include fastcgi_params;
fastcgi_pass unix:/run/php/php7.4-fpm.sock; # Ensure this socket path is correct
# OR (if using TCP)
# fastcgi_pass 127.0.0.1:9000; # Ensure this IP and port are correct
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
# Example for general HTTP upstream (proxy_pass, e.g., Gunicorn, Node.js):
# Verify this IP and port match your application's 'bind' address.
location / {
proxy_pass http://127.0.0.1:8000; # Ensure this IP and port are correct
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
Additionally, confirm your upstream application’s configuration (e.g., /etc/php/7.4/fpm/pool.d/www.conf’s listen directive for PHP-FPM, or your Gunicorn/Node.js app’s bind address) matches the Nginx configuration.
Verification
# 1. Test Nginx configuration for syntax errors.
sudo nginx -t
# 2. If the test is successful, reload Nginx to apply any configuration changes.
sudo systemctl reload nginx
# 3. Verify the website is now accessible by making an HTTP request.
curl -I http://localhost
# OR (if testing from outside the EC2 instance, or for a specific domain)
curl -I http://your-ec2-public-ip-or-domain.com