Datadog APM is here
NGINX 502 Bad Gateway: PHP-FPM

NGINX 502 Bad Gateway: PHP-FPM

/ / /
Published: December 8, 2016

This post is part of a series on troubleshooting NGINX 502 Bad Gateway errors. If you’re not using PHP-FPM, check out our other article on troubleshooting NGINX 502s with Gunicorn as a backend.

502 Bad Gateway errors are surprisingly common, and the exact cause of this error code depends on your particular stack.

PHP-FPM health - The dreaded 502 Bad Gateway Error message

Bad gateway errors typically arise due to a breakdown in communication between the frontend webserver and backend application handlers. Most often, the underlying cause can be attributed to excessive latency or exceedingly short timeout windows.

PHP-FPM health - Illustration of a web server handling a CGI request

In other cases, bad gateway errors indicate a misconfigured web application handler—the webserver understood the request and passed it along to the appropriate handler, but something got bungled during the handoff.

Diagnosing the cause of 502 bad gateway errors mostly depends on the application server you’re using, and we’ve laid out solutions for PHP-FPM below.

Common issues

PHP-FastCGI Process Manager (PHP-FPM) is a PHP FastCGI implementation commonly used with NGINX. You may observe 502s when using NGINX and PHP-FPM under the following conditions:

PHP-FPM isn’t running

Issue involves PHP-FPM health

The quickest way to check the status of PHP-FPM is with ps and grep. If your output resembles the text below, you can be sure PHP-FPM is running and jump to the next section section.

root@nginx0:/var/log/nginx# ps aux | grep php
root     29191  0.0  1.7 133628 18108 ?        Ss   20:41   0:00 php-fpm: master process (/etc/php5/fpm/php-fpm.conf)
www-data 29193  0.0  0.5 133628  5956 ?        S    20:41   0:00 php-fpm: pool www
www-data 29194  0.0  0.5 133628  5956 ?        S    20:41   0:00 php-fpm: pool www

If not, try starting PHP-FPM:

init systemcommand
SysVservice php5-fpm start
Systemdsystemctl start php5-fpm.service
init.d/etc/init.d/php5-fpm start
Upstartinitctl start php5-fpm

PHP-FPM won’t start

If PHP-FPM can’t successfully start, make a request for a PHP page on your webserver to cause an error to be logged. Then, tail NGINX’s error log:

www-data@nginx0:/var/log/nginx$ tail /var/log/nginx/error.log
2016/09/19 20:39:30 [crit] 28751#28751: *9 connect() to unix:/var/run/php5-fpm.sock failed (2: No such file or directory) while connecting to upstream, client: 192.0.2.101, server: example.com, request: "GET /test.php HTTP/1.1", upstream: "fastcgi://unix:/var/run/php5-fpm.sock:", host: "192.0.2.255"
2016/09/19 20:39:50 [crit] 28751#28751: *9 connect() to unix:/var/run/php5-fpm.sock failed (2: No such file or directory) while connecting to upstream, client: 192.0.2.101, server: example.com, request: "GET /test.php HTTP/1.1", upstream: "fastcgi://unix:/var/run/php5-fpm.sock:", host: "192.0.2.255"
2016/09/20 16:39:44 [crit] 28751#28751: *33 connect() to unix:/var/run/php5-fpm.sock failed (2: No such file or directory) while connecting to upstream, client: 192.0.2.101, server: example.com, request: "GET /test.php HTTP/1.1", upstream: "fastcgi://unix:/var/run/php5-fpm.sock:", host: "192.0.2.255"

The errors above point to a problem with the request handling socket. NGINX is looking for a UNIX socket located at /var/run/php5-fpm.sock but can’t find it; correlating these errors with errors found in syslog (the default log location for PHP-FPM), it becomes clear that PHP-FPM is failing to start, which is almost certainly a configuration issue.

www-data@nginx0:/var/log/nginx$ tail /var/log/syslog
Sep 20 16:39:10 nginx0 kernel: [77167.468712] init: php5-fpm main process (3551) terminated with status 78
Sep 20 16:39:11 nginx0 kernel: [77167.468727] init: php5-fpm main process ended, respawning

Note the terminated with status 78. To determine what error code 78 represents, we can grep for that error code in /usr/include/sysexits.h:

www-data@nginx0:/var/log/nginx$ cat /usr/include/sysexits.h | grep 78
#define EX_CONFIG       78      /* configuration error */

Our suspicions are confirmed; the error is in fact due to a misconfiguration of PHP-FPM.

Resolving PHP-FPM config issues

Configuration issues could be a result of fat fingers, or a genuine configuration conflict.

To resolve an error caused by misconfiguration, first make sure the socket directory is writeable by the user running php-fpm. Next, verify that the socket is being created with the appropriate user permissions.

In particular, check your worker pool configurations (in /etc/php5/fpm/pool.d/*.conf) and verify:

  • socket path
  • process owner/group
  • listen.owner/listen.group
user = www-data
group = www-dat

listen = /var/run/php5-fpm.sock

listen.owner = www-data
listen.group = www-data

Notice the typo in the configuration file above: group = www-dat should read group = www-data. Fixing this typo and restarting the PHP-FPM daemon resolves the issue.

NGINX can’t communicate with PHP-FPM

PHP-FPM health - Issue lies in NGINX

If both PHP-FPM and your application are working properly, the issue may reside in NGINX’s configuration. In your sites-enabled directory, open the configuration for the site causing issues (/etc/nginx/sites-enabled/default, by default) and verify that the fastcgi_pass directive matches the socket (listen) in your PHP-FPM worker pool configuration.

[...]
        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_nam$
                include fastcgi_params;

        }

If you’ve made any changes, make sure you restart NGINX.

NGINX is timing out

If the backend application server is up and running, the cause of the issue likely lies in the application being served. Specifically, applications which do not respond to NGINX in a timely manner will cause a 502 because NGINX couldn’t wait any longer for a response.

Depending on what the application is supposed to do, a long execution time ( > 30 seconds) may be expected. In that case, increasing both the maximum execution time and NGINX’s timeout window as outlined below would be the best solution.

However, if long execution periods are abnormal in the context of your application and the data set it is processing, you may benefit from profiling and optimizing the application in question.

This fix requires two changes: first, open PHP-FPM’s configuration file (/etc/php5/fpm/php.ini), and find the following line:
max_execution_time = 30

Increase max_execution_time to your expected application execution time (in seconds). It may be prudent to add a buffer of extra time, just in case.

Next, in your NGINX config (/etc/nginx/nginx.conf), add the following within the http block to increase timeout windows, buffers, and buffer sizes:

http { 
...

fastcgi_buffers 8 16k;
fastcgi_buffer_size 32k;
fastcgi_connect_timeout 300;
fastcgi_send_timeout 300;
fastcgi_read_timeout 300;
}

Finally, once changes are made and saved, reload NGINX and PHP-FPM:

PHP-FPM:

init systemcommand
SysVservice php5-fpm reload
Systemdsystemctl reload php5-fpm.service
init.d/etc/init.d/php5-fpm reload
Upstartinitctl reload php5-fpm

NGINX:

init systemcommand
SysVservice nginx reload
Systemdsystemctl reload nginx.service
init.d/etc/init.d/nginx reload
Upstartinitctl reload nginx

PHP-FPM is timing out

In some cases, increasing the timeout window for PHP-FPM may only provide a temporary solution to a deeper underlying issue. Depending on the nature of your application, you may be able to profile and optimize it to reduce its execution time, side-stepping the timeout issue entirely. For example, your application may be spending an inordinate time blocking on a database query which, depending on your platform, may count against the maximum allotted execution time. From the PHP documentation: “Any time spent on activity that happens outside the execution of the script such as system calls using system(), stream operations, database queries, etc. is not included when determining the maximum time that the script has been running. This is not true on Windows where the measured time is real.”

If your NGINX timeout is sufficiently high, you could temporarily extend PHP’s execution time limit by invoking the set_time_limit() function from within your application, but if you are continuously bumping into the execution ceiling, a long-term solution like profiling or increasing PHP-FPM’s timeout may be more appropriate.

200 OK

Whether the problem was in your application, PHP-FPM, or NGINX doesn’t matter to your end-users. So while you’ve solved the immediate issue, monitoring the performance and health of your infrastructure and applications is an ongoing concern.

With Datadog, you can collect, visualize, alert, and act on performance and health metrics from across your entire infrastructure. And with 15 months of retention at full granularity, you can compare past performance with recent trends, forecast traffic and load, and fire alerts when things deviate from expectations.

If you’re already a Datadog customer, you can start monitoring NGINX, PHP-FPM, and the rest of your stack today. If you don’t yet have a Datadog account, sign up for a free and get started in minutes.


Want to write articles like this one? Our team is hiring!