When setting up a fresh LEMP stack, the 502 Bad Gateway error is practically a rite of passage. Let's break down what's happening with your specific configuration and how to fix it systematically.
# Verify both services are running
ps aux | grep -E 'nginx|php-fpm'
systemctl status nginx php-fpm
Your nginx configuration shows you're trying to pass PHP requests to 127.0.0.1:9000
, but let's confirm PHP-FPM is actually listening there:
# Check PHP-FPM listening socket
ss -tulnp | grep 9000
# Alternative:
netstat -tulnp | grep 9000
- Socket vs TCP mismatch (you're using TCP port 9000)
- Permission issues between nginx and PHP-FPM processes
- Incorrect fastcgi_params
- PHP-FPM pool configuration errors
First, check PHP-FPM's pool configuration (typically in /etc/php5/fpm/pool.d/www.conf
):
[www]
listen = 127.0.0.1:9000
listen.allowed_clients = 127.0.0.1
user = www-data
group = www-data
pm = dynamic
pm.max_children = 5
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3
Then verify nginx and PHP-FPM are using the same user:
# In nginx.conf (usually www-data or nginx)
user www-data;
# Should match PHP-FPM pool user
Many modern setups use Unix sockets instead of TCP for better performance:
# In PHP-FPM pool config:
listen = /run/php/php7.4-fpm.sock
# Corresponding nginx config:
fastcgi_pass unix:/run/php/php7.4-fpm.sock;
If using TCP sockets, ensure proper SELinux contexts:
# For RHEL/CentOS:
setsebool -P httpd_can_network_connect 1
# For Ubuntu/Debian with AppArmor:
aa-status | grep nginx
# Check for denials in /var/log/syslog
Create a test script to bypass nginx:
# test.php
<?php phpinfo(); ?>
# Then call via:
SCRIPT_FILENAME=/path/to/test.php REQUEST_METHOD=GET cgi-fcgi -bind -connect 127.0.0.1:9000
Always check these critical logs:
# Nginx error log
tail -f /var/log/nginx/error.log
# PHP-FPM error log (location defined in php-fpm.conf)
tail -f /var/log/php5-fpm.log
Here's a verified working minimal setup:
server {
listen 80;
server_name localhost;
root /srv/www;
index index.php;
location / {
try_files $uri $uri/ =404;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
The key differences from your original config are the simplified PHP handler location and using Unix sockets.
When you've configured Nginx with PHP-FPM exactly as shown in countless tutorials:
apt-get install php5 nginx php-fpm
/etc/init.d/nginx start
/etc/init.d/php5-fpm start
But still encounter the dreaded 502 error, there are several layers we need to examine. Let's break down the troubleshooting process systematically.
Before diving deep, perform these quick checks:
# Check if services are running
ps aux | grep nginx
ps aux | grep php-fpm
# Verify listening ports
netstat -tulnp | grep ':9000'
Most 502 errors stem from communication issues between Nginx and PHP-FPM. Modern PHP-FPM installations typically use Unix sockets instead of TCP ports. Here's how to check your current configuration:
# Check PHP-FPM pool configuration
cat /etc/php5/fpm/pool.d/www.conf | grep 'listen ='
# Sample output showing socket configuration
;listen = 127.0.0.1:9000
listen = /var/run/php5-fpm.sock
If you find socket configuration, your Nginx config should mirror this:
location ~ \.php$ {
try_files $uri =404;
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
Socket communication requires proper permissions. Check these critical elements:
# Verify socket file exists and permissions
ls -la /var/run/php5-fpm.sock
# Check Nginx and PHP-FPM user/group
cat /etc/nginx/nginx.conf | grep 'user'
cat /etc/php5/fpm/pool.d/www.conf | grep -E 'user|group'
Example fix for permission problems:
chown www-data:www-data /var/run/php5-fpm.sock
chmod 766 /var/run/php5-fpm.sock
When basic fixes don't work, enable detailed logging:
# Nginx error logging
error_log /var/log/nginx/error.log debug;
# PHP-FPM logging
catch_workers_output = yes
php_admin_flag[log_errors] = on
Sample log entries to look for:
connect() to unix:/var/run/php5-fpm.sock failed (13: Permission denied)
upstream prematurely closed connection while reading response header from upstream
Here's a battle-tested Nginx server block that resolves most 502 issues:
server {
listen 80;
server_name yourdomain.com;
root /srv/www;
index index.php;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}