How to Fix Nginx '502 Bad Gateway' Error with PHP-FPM
Problem Explanation
The Nginx '502 Bad Gateway' error indicates that Nginx, acting as a reverse proxy, received an invalid response from an upstream server. In the context of PHP applications, this upstream server is almost always PHP-FPM (FastCGI Process Manager). When a user requests a PHP page, Nginx forwards the request to PHP-FPM, waits for PHP-FPM to process the script and return the output, and then serves that output to the user. A 502 error means this handshake failed: PHP-FPM either didn't respond, responded too slowly, or sent an uninterpretable response.
Users encountering this problem will see a "502 Bad Gateway" message displayed in their web browser, often accompanied by an Nginx default error page or a customized error page if configured. The immediate impact is that the PHP application is inaccessible, leading to service disruption. Identifying the root cause requires methodical investigation of both Nginx and PHP-FPM configurations and logs.
Why It Happens
The '502 Bad Gateway' error between Nginx and PHP-FPM typically arises from a breakdown in communication or an inability of PHP-FPM to process requests. Common root causes include:
- PHP-FPM Not Running or Unresponsive: The PHP-FPM service might be stopped, crashed, or completely overwhelmed by too many requests, making it unable to accept new connections from Nginx.
- Incorrect Configuration: Mismatches between Nginx's
fastcgi_passdirective and PHP-FPM'slistendirective (e.g., Nginx expecting a TCP port while PHP-FPM listens on a Unix socket, or vice-versa, or incorrect paths/ports). - Resource Exhaustion: PHP-FPM child processes might be hitting PHP limits (like
memory_limit,max_execution_time) or server resource limits (CPU, RAM), causing them to crash or hang before returning a response. This leads Nginx to time out waiting. - Permission Issues: Nginx might lack the necessary read/write permissions for the PHP-FPM Unix socket file, preventing it from establishing a connection.
- Network Problems/Firewall: While less common in a typical Nginx-PHP-FPM setup on a single server, network issues or firewall rules could block communication if PHP-FPM is running on a different host or listening on a non-standard port.
Step-by-Step Solution
## Step 1: Check PHP-FPM Service Status
The first step is to confirm that the PHP-FPM service is running and healthy.
-
Check Service Status:
sudo systemctl status php*-fpm(Replace
php*-fpmwith your specific PHP version, e.g.,php7.4-fpmorphp8.1-fpm. On RHEL/CentOS, it might just bephp-fpm.)Look for "Active: active (running)". If it's not running, or shows errors:
sudo systemctl start php*-fpm sudo systemctl enable php*-fpm # To ensure it starts on bootIf it's running but appears problematic, try restarting it:
sudo systemctl restart php*-fpm -
Inspect PHP-FPM Logs: If the service is failing to start or restarting frequently, check its specific logs:
sudo journalctl -u php*-fpm --since "5 minutes ago"Or, check pool-specific error logs, often found at
/var/log/php-fpm/www-error.logor similar locations. This can reveal underlying PHP configuration issues or script errors causing crashes.
## Step 2: Verify Nginx Configuration for PHP-FPM
Nginx must be correctly configured to pass requests to PHP-FPM.
- Locate Nginx Server Block: Find your website's Nginx configuration file, typically in
/etc/nginx/sites-available/your_site.confor directly in/etc/nginx/nginx.conf. - Check
fastcgi_passDirective: Inside thelocation ~ \.php$block, locate thefastcgi_passdirective. It should point to your PHP-FPM socket or TCP address.- Unix Socket Example:
fastcgi_pass unix:/var/run/php/php8.1-fpm.sock; - TCP Port Example:
fastcgi_pass 127.0.0.1:9000;
- Unix Socket Example:
- Match with PHP-FPM
listenDirective: Ensure this value exactly matches thelistendirective in your PHP-FPM pool configuration file (e.g.,/etc/php/*/fpm/pool.d/www.conf).; In /etc/php/*/fpm/pool.d/www.conf listen = /var/run/php/php8.1-fpm.sock ; Must match Nginx's fastcgi_pass ; OR listen = 127.0.0.1:9000 ; Must match Nginx's fastcgi_pass - Test and Reload Nginx:
If the syntax is okay, reload Nginx for changes to take effect:sudo nginx -tsudo systemctl reload nginx
## Step 3: Inspect PHP-FPM Pool and PHP Settings
PHP-FPM's resource management and general PHP settings can cause 502s.
- Review PHP-FPM Pool Configuration (
www.conf):pm(Process Manager):ondemandsaves memory but can introduce latency;dynamicis a good balance;staticis fixed. Ifpmisondemandordynamicandpm.max_childrenis too low, PHP-FPM might become unresponsive under load. Increasepm.max_childrenif necessary, but monitor server RAM.request_terminate_timeout: If set too low, long-running PHP scripts will be killed, causing Nginx to receive no response. Set to0for unlimited (not recommended for production) or a reasonable value (e.g.,300s).listen.owner,listen.group,listen.mode: If using a Unix socket, these directives define permissions. Nginx's user (typicallywww-dataon Debian/Ubuntu,nginxon RHEL/CentOS) must have read/write access to the socket. Ensurelisten.owner = www-dataandlisten.group = www-data(or corresponding Nginx user/group).
- Examine
php.iniSettings:memory_limit: If a script exceeds this, it will terminate, leading to a 502. Increase (e.g.,256Mor512M) if your application requires more memory.max_execution_time: Similar torequest_terminate_timeout, if a script runs longer than this, it will be terminated. Increase if legitimate long-running scripts are causing issues.upload_max_filesize/post_max_size: Large file uploads can hit these limits, potentially causing issues.- Error Logging: Ensure
log_errors = Onanderror_logpoints to a writable file for detailed PHP errors.
After changes, restart PHP-FPM:sudo nano /etc/php/*/fpm/php.ini # Or similar path for php.ini sudo nano /etc/php/*/fpm/pool.d/www.conf # Or similar path for www.confsudo systemctl restart php*-fpm.
## Step 4: Examine Nginx Error Logs for Specific Clues
Nginx's error logs often provide precise details about why it couldn't connect to or get a response from PHP-FPM.
- Check Nginx Error Log:
Look for entries related tosudo tail -f /var/log/nginx/error.logfastcgi_passor the 502 error. Common messages include:connect() failed (13: Permission denied) while connecting to upstream: Indicates Nginx cannot access the PHP-FPM socket due to incorrect permissions.connect() failed (111: Connection refused) while connecting to upstream: PHP-FPM is not listening on the specified socket/port, or is completely down.upstream timed out (110: Connection timed out) while reading response header from upstream: PHP-FPM accepted the connection but didn't send a response within Nginx's configured timeout. This often points to a hanging PHP script or an overwhelmed PHP-FPM.No such file or directory: The specified Unix socket path forfastcgi_passdoes not exist.
## Step 5: Increase Nginx and PHP-FPM Timeouts
If "upstream timed out" is the issue, or if your application involves long-running processes, you may need to increase timeout values.
-
Nginx Timeouts (in your Nginx server block):
location ~ \.php$ { # ... other fastcgi parameters ... fastcgi_read_timeout 300s; # Default is 60s fastcgi_send_timeout 300s; # Default is 60s fastcgi_connect_timeout 300s; # Default is 60s # ... }Set these to a value higher than your longest expected PHP script execution. Reload Nginx after changes:
sudo systemctl reload nginx. -
PHP-FPM Request Terminate Timeout (in
www.conf): Ensurerequest_terminate_timeoutin your PHP-FPM pool configuration is either0(unlimited, use with caution) or higher than Nginx'sfastcgi_read_timeout.request_terminate_timeout = 300sRestart PHP-FPM after changes:
sudo systemctl restart php*-fpm.
## Step 6: Check File and Directory Permissions
Incorrect permissions are a frequent cause of Permission denied errors in Nginx logs.
-
PHP-FPM Socket Permissions: If using a Unix socket (e.g.,
/var/run/php/php8.1-fpm.sock), check its permissions:ls -l /var/run/php/php*-fpm.sockThe owner and group should typically be
rootandwww-data(or the Nginx user's group), with permissions likesrw-rw----(socket, read/write for owner and group). If yourwww.conffile specifieslisten.ownerandlisten.group, ensure these match the Nginx user and group. If not, PHP-FPM won't create the socket with the correct permissions. -
Web Root Directory Permissions: While less directly related to the 502, incorrect permissions on your web root directory (where PHP files reside) can prevent PHP-FPM from reading scripts, potentially leading to errors or timeouts. Ensure your Nginx user (e.g.,
www-data) and PHP-FPM user have read and execute permissions for directories and read permissions for files.sudo chown -R www-data:www-data /var/www/your_site sudo find /var/www/your_site -type d -exec chmod 755 {} \; sudo find /var/www/your_site -type f -exec chmod 644 {} \;
## Step 7: Debugging a Hanging PHP Script or Application
If PHP-FPM is running and configured correctly, but the 502 occurs only for specific requests, a problematic PHP script is likely the culprit.
- Identify Problematic Scripts: Check your application's internal logs, Nginx access logs (for slow requests), or use browser developer tools to pinpoint which URLs cause the 502.
- Enable Detailed PHP Error Reporting (Temporarily): In
php.ini, set:
Remember to turn this off in production environments. Restart PHP-FPM. This might display more specific PHP errors instead of a generic 502.display_errors = On display_startup_errors = On error_reporting = E_ALL - Trace Execution: For complex issues, tools like Xdebug can help step through PHP code execution. Command-line tools like
stracecan trace system calls made by PHP-FPM processes (sudo strace -p <php-fpm-pid>) to identify where it's getting stuck. - Database/External Service Issues: Check if the PHP script relies on a database or external API that might be slow or unresponsive.
Common Mistakes
- Not Restarting/Reloading Services: Configuration changes to Nginx or PHP-FPM require a service reload (
nginx -s reloadorsystemctl reload nginx) or restart (systemctl restart php*-fpm) to take effect. Forgetting this is a common oversight. - Mismatch in
fastcgi_passandlisten: Using a Unix socket path in Nginx while PHP-FPM is listening on a TCP port, or vice-versa, or simply an incorrect path/port. - Ignoring Logs: Troubleshooting without consulting Nginx's
error.logand PHP-FPM's error logs is like trying to fix a car with a blindfold. These logs are your primary diagnostic tools. - Insufficient Resource Allocation: Underestimating the memory (
memory_limit) or execution time (max_execution_time,request_terminate_timeout) required by complex PHP applications, or not allocating enough PHP-FPM child processes (pm.max_children). - Incorrect Socket Permissions: Forgetting to set
listen.ownerandlisten.groupinwww.confto match the Nginx user/group, or not ensuring the socket file itself has the correct permissions for Nginx to access it.
Prevention Tips
- Monitor System Resources: Implement monitoring for CPU, RAM, and PHP-FPM process count. Tools like
htop,Netdata, or a full-fledged monitoring stack (e.g., Prometheus with Grafana) can alert you to resource exhaustion before it causes 502 errors. - Regular Log Review and Alerting: Regularly check Nginx and PHP-FPM error logs. Configure log aggregation and alerting (e.g., ELK stack, Splunk, or simpler
grepscripts) to notify you immediately of critical errors. - Tune PHP-FPM Process Manager: Configure PHP-FPM's process manager (
pm) settings (pm.max_children,pm.start_servers,pm.min_spare_servers,pm.max_spare_servers) based on your server's available RAM and expected traffic.dynamicorstaticmodes are generally preferred for production overondemandfor performance, provided you have sufficient memory. - Optimize PHP Application Code: Ensure your PHP application is efficient, especially concerning database queries and external API calls. Long-running, memory-intensive, or I/O-bound operations are prime candidates for causing timeouts and 502s. Implement caching where appropriate.
- Set Realistic Timeouts: While increasing timeouts can prevent immediate 502s, excessively high timeouts can mask underlying performance issues. Set timeouts (Nginx
fastcgi_read_timeout, PHP-FPMrequest_terminate_timeout) to reasonable values that accommodate legitimate long processes but still catch runaway scripts. - Maintain Consistent Configuration: Use configuration management tools (Ansible, Puppet, Chef) or version control for Nginx and PHP-FPM configuration files to ensure consistency and easier rollback if changes introduce new issues.
- Keep Software Updated: Regularly update Nginx, PHP, and PHP-FPM to benefit from performance improvements, bug fixes, and security patches.