How to Fix '502 Bad Gateway' in Nginx Caused by PHP-FPM Configuration Mismatch
Problem Explanation
Encountering a "502 Bad Gateway" error is a common frustration for anyone running PHP applications behind an Nginx web server. This specific guide focuses on instances where the 502 error stems from a misconfiguration in how Nginx attempts to communicate with the PHP-FPM (FastCGI Process Manager) service. When this problem occurs, users typically see a generic "502 Bad Gateway" message displayed directly in their web browser, often accompanied by the Nginx logo, indicating that Nginx itself received an invalid response from an upstream server—in this case, PHP-FPM.
The core issue manifests when Nginx, acting as a reverse proxy, tries to pass a PHP request to PHP-FPM, but PHP-FPM either isn't listening at the expected address, or it's listening in a way that Nginx cannot properly connect to. This can result in Nginx waiting indefinitely for a response or getting an immediate refusal, leading it to serve the 502 error page to the client. The consequence is a website that is completely inaccessible, rendering PHP applications like WordPress, Laravel, or custom-built scripts unresponsive.
Why It Happens
The 502 Bad Gateway error in this context primarily occurs due to a breakdown in communication between Nginx and PHP-FPM. Nginx is a high-performance web server that excels at serving static content and acting as a reverse proxy. For dynamic content generated by PHP, Nginx doesn't process the PHP code itself; instead, it hands off .php requests to a specialized process manager, PHP-FPM. PHP-FPM executes the PHP script and returns the output to Nginx, which then delivers it to the client's browser.
The "configuration mismatch" arises when the communication parameters configured in Nginx's site configuration file do not align with PHP-FPM's listening configuration. Common scenarios include:
- Incorrect Socket Path: Nginx might be configured to connect to a specific Unix domain socket (e.g.,
/var/run/php/php7.4-fpm.sock), but PHP-FPM is listening on a different path (e.g.,/run/php/php8.1-fpm.sock) or is configured to listen on a TCP port instead. - Incorrect TCP Port/Address: If PHP-FPM is configured to listen on a TCP address and port (e.g.,
127.0.0.1:9000), Nginx must be configured to connect to that exact IP and port. Any discrepancy in the IP address or port number will lead to a connection failure. - PHP-FPM Service Not Running: The PHP-FPM service might have crashed, failed to start, or simply isn't running, meaning there's no process listening at the configured socket or port for Nginx to connect to.
- Permissions Issues: If using a Unix domain socket, Nginx's worker process user (typically
www-dataornginx) might not have the necessary read/write permissions to access the socket file created by PHP-FPM. - Firewall Restrictions: In cases where PHP-FPM listens on a TCP port, an active firewall might be blocking Nginx from connecting to that port, even if both services are on the same server (though this is less common for loopback connections).
These mismatches prevent Nginx from successfully forwarding PHP requests, resulting in the "502 Bad Gateway" error being displayed to the user.
Step-by-Step Solution
To effectively troubleshoot and fix the "502 Bad Gateway" error caused by PHP-FPM configuration mismatch, follow these steps systematically.
## Step 1: Verify PHP-FPM Service Status
The first crucial step is to ensure that the PHP-FPM service is actually running. If it's not active, Nginx will have nothing to connect to, leading directly to a 502 error.
Open your terminal and run the following command, replacing X.Y with your specific PHP version (e.g., 7.4, 8.1):
sudo systemctl status phpX.Y-fpm
Example Output (Running):
● php7.4-fpm.service - The PHP 7.4 FastCGI Process Manager
Loaded: loaded (/lib/systemd/system/php7.4-fpm.service; enabled; vendor preset: enabled)
Active: active (running) since Mon 2023-10-23 10:00:00 UTC; 1 day ago
Docs: man:php-fpm7.4(8)
Process: 1234 ExecStartPost=/usr/lib/php/php-fpm-socket-helper install /run/php/php-fpm.sock /etc/php/7.4/fpm/pool.d/www.conf 7.4 (code=exited, status=0/SUCCESS)
Main PID: 1236 (php-fpm7.4)
Status: "Processes active: 0, idle: 5, Requests: 0, slow: 0, Traffic: 0req/sec"
Tasks: 6 (limit: 1109)
Memory: 25.0M
CGroup: /system.slice/php7.4-fpm.service
├─1236 php-fpm: master process (/etc/php/7.4/fpm/php-fpm.conf)
├─1237 php-fpm: pool www
├─1238 php-fpm: pool www
└─1239 php-fpm: pool www
If the status shows Active: inactive (dead), failed, or anything other than active (running), you need to start it:
sudo systemctl start phpX.Y-fpm
sudo systemctl enable phpX.Y-fpm # To ensure it starts on boot
Then re-check the status. If it fails to start, investigate PHP-FPM's own logs (usually /var/log/phpX.Y-fpm.log or journalctl -u phpX.Y-fpm) for more specific errors.
## Step 2: Check Nginx Error Logs
Nginx logs are your best friend for diagnosing upstream issues. They will often pinpoint exactly what Nginx failed to connect to.
Check the main Nginx error log file, typically located at /var/log/nginx/error.log:
sudo tail -f /var/log/nginx/error.log
Look for messages similar to these:
connect() failed (111: Connection refused) while connecting to upstreamconnect() failed (13: Permission denied) while connecting to upstreamupstream timed out (110: Connection timed out) while connecting to upstreamno live upstreams while connecting to upstream
These messages will usually include the exact socket path or IP address and port that Nginx attempted to connect to (e.g., unix:/var/run/php/php7.4-fpm.sock or 127.0.0.1:9000). Make a note of this address, as it's what Nginx expects.
## Step 3: Identify PHP-FPM Listening Configuration
Now that you know what Nginx wants to connect to, you need to find out what PHP-FPM is actually listening on. PHP-FPM's listening configuration is typically defined in its pool configuration file. For the default www pool, this is usually:
/etc/php/X.Y/fpm/pool.d/www.conf
Again, replace X.Y with your PHP version. Open this file with a text editor:
sudo nano /etc/php/X.Y/fpm/pool.d/www.conf
Look for the listen directive. It will be configured in one of two ways:
-
Unix Domain Socket:
listen = /run/php/phpX.Y-fpm.sock listen.owner = www-data listen.group = www-data listen.mode = 0660Note the full socket path. Ensure
listen.ownerandlisten.groupare set to the Nginx user and group (commonlywww-data). -
TCP Address and Port:
listen = 127.0.0.1:9000Note the IP address and port.
Compare this listen value with the address Nginx reported trying to connect to in Step 2. They must match exactly.
## Step 4: Align Nginx PHP-FPM Configuration
Now you need to configure Nginx to connect to the exact address PHP-FPM is listening on.
Locate your Nginx site configuration file. This is typically found in /etc/nginx/sites-available/ and symlinked to /etc/nginx/sites-enabled/. For example, your_domain.conf or default.
sudo nano /etc/nginx/sites-available/your_domain.conf
Inside this file, find the location ~ \.php$ block. This block is responsible for forwarding PHP requests. Look for the fastcgi_pass directive.
You need to adjust fastcgi_pass to match the listen directive you found in Step 3:
-
If PHP-FPM listens on a Unix socket:
location ~ \.php$ { include snippets/fastcgi-php.conf; # Or include fastcgi_params; fastcgi_pass unix:/run/php/phpX.Y-fpm.sock; # MAKE THIS MATCH PHP-FPM's listen }Ensure the path
/run/php/phpX.Y-fpm.sockmatches thelistendirective fromwww.conf. -
If PHP-FPM listens on a TCP address/port:
location ~ \.php$ { include snippets/fastcgi-php.conf; # Or include fastcgi_params; fastcgi_pass 127.0.0.1:9000; # MAKE THIS MATCH PHP-FPM's listen }Ensure the IP address and port
127.0.0.1:9000matches thelistendirective fromwww.conf.
Also, double-check that include snippets/fastcgi-php.conf; or include fastcgi_params; is present to provide the necessary FastCGI parameters.
## Step 5: Check Socket Permissions (for Unix sockets)
If you are using a Unix domain socket, Nginx needs appropriate permissions to read and write to it. While listen.owner, listen.group, and listen.mode in www.conf usually handle this, it's worth verifying.
The www-data user (or whichever user Nginx runs as) must be able to access the socket file. If listen.owner and listen.group are set correctly to www-data, and Nginx runs as www-data, permissions are usually fine. However, if Nginx runs as nginx user, you might need to add nginx to the www-data group:
sudo usermod -aG www-data nginx
Then check the socket's permissions (after PHP-FPM is running and created it):
ls -l /run/php/phpX.Y-fpm.sock
It should look something like: -rw-rw---- 1 www-data www-data 0 Oct 23 10:00 /run/php/php7.4-fpm.sock. If the Nginx user isn't www-data and isn't in the www-data group, you might face permission issues. Adjust listen.owner and listen.group in www.conf to match the Nginx user/group, or add the Nginx user to the group that owns the socket.
## Step 6: Test Nginx Configuration and Restart Services
After making changes to Nginx and PHP-FPM configuration files, you must test and restart the services.
First, test your Nginx configuration syntax:
sudo nginx -t
If it reports syntax is ok and test is successful, proceed. If there are errors, fix them before proceeding.
Now, restart or reload Nginx and PHP-FPM:
sudo systemctl reload nginx # Or restart if reload doesn't work for your change
sudo systemctl restart phpX.Y-fpm # Restart PHP-FPM to apply changes in www.conf
After both services have been restarted, clear your browser cache and try accessing your website again.
## Step 7: Check Firewall Configuration (for TCP connections)
If PHP-FPM is configured to listen on a TCP port (e.g., 127.0.0.1:9000) and your server has a firewall enabled, ensure that connections to this port are not blocked. For local connections (Nginx and PHP-FPM on the same server), loopback traffic (127.0.0.1) is rarely blocked. However, if Nginx and PHP-FPM are on separate servers, or if your firewall rules are unusually strict, this could be an issue.
To check the firewall status (e.g., with UFW):
sudo ufw status
If the port is explicitly blocked or if the default policy prevents it, you might need to allow it:
sudo ufw allow 9000/tcp # Replace 9000 with your actual PHP-FPM port
sudo ufw reload
This step is generally less common for local 502 issues but is critical for multi-server setups or unusual firewall configurations.
Common Mistakes
When troubleshooting "502 Bad Gateway" errors, users frequently make a few common mistakes that prolong the diagnostic process:
- Restarting Only Nginx: A common oversight is restarting Nginx after making changes to its configuration but forgetting to restart PHP-FPM (if its configuration was also modified). Changes to PHP-FPM's
listendirective or other settings only take effect after the PHP-FPM service is restarted. Both services need to be aligned and refreshed. - Incorrectly Identifying PHP-FPM Version: Servers can sometimes have multiple PHP versions installed (e.g., PHP 7.4, 8.1, 8.2). If Nginx is configured to talk to
php8.1-fpm.sock, butphp7.4-fpmis the one actually running or configured for the site, a mismatch will occur. Always ensure you are checking and modifying the configuration for the correct PHP-FPM version. - Typos in Socket Paths or Ports: Even a single character error in the
fastcgi_passdirective in Nginx or thelistendirective in PHP-FPM can prevent communication. Double-check all paths and port numbers for exact matches. - Editing the Wrong Configuration File: Nginx configurations can be complex, with
default.conf, site-specific files, and included snippets. Ensure you are editing the active configuration file for the website experiencing the issue, not a generic or inactive one. Similarly, ensure you're modifying the correct PHP-FPM pool configuration file. - Ignoring Log File Details: The Nginx error logs provide specific clues, such as "Connection refused to
unix:/path/to/socket" or "Connection refused to127.0.0.1:9000". Ignoring these precise details and guessing at solutions can lead to wasted time. Always refer to the logs for the exact address Nginx is attempting to connect to.
Prevention Tips
Preventing future "502 Bad Gateway" errors due to PHP-FPM configuration mismatches involves implementing best practices for server configuration and maintenance:
- Standardize Configuration: Establish a consistent naming convention and location for PHP-FPM sockets or TCP ports across your servers and applications. This reduces the chance of misconfiguration when deploying new sites or updating PHP versions. For example, always use
/run/php/phpX.Y-fpm.sockfor Unix sockets or127.0.0.1:9000for TCP, consistently across all projects. - Use Configuration Management Tools: For larger deployments or multiple servers, tools like Ansible, Puppet, or Chef can automate configuration, ensuring consistency and reducing human error. These tools enforce desired states, making mismatches less likely.
- Always Test Nginx Configuration: Before reloading or restarting Nginx, always run
sudo nginx -tto check for syntax errors. This simple command can catch many common configuration issues before they cause downtime. - Monitor PHP-FPM Status: Implement monitoring for your PHP-FPM service (e.g., using
systemctl status, Nagios, Prometheus). If PHP-FPM crashes or stops listening, you'll be alerted proactively, allowing you to intervene before users encounter a 502 error. - Version Control Configuration Files: Store your Nginx and PHP-FPM configuration files in a version control system (like Git). This allows you to track changes, revert to previous working versions if a problem arises, and provides a clear history of modifications.
- Regularly Review Logs: Periodically review Nginx error logs (
/var/log/nginx/error.log) and PHP-FPM logs (e.g.,journalctl -u phpX.Y-fpm) even when things are working. This can help identify minor issues or warnings that might escalate into a 502 error in the future. - Understand PHP-FPM Pool Management: If you manage multiple PHP applications or distinct PHP versions, understand how to create and manage separate PHP-FPM pools. Each pool can listen on a different socket or port, allowing you to isolate applications and prevent global configuration changes from affecting all sites simultaneously.