How Nginx passes requests to PHP-FPM
Nginx cannot execute PHP itself — it serves static files and proxies dynamic requests to a separate PHP-FPM (FastCGI Process Manager) process over the FastCGI protocol. This is handled by the fastcgi_pass directive inside a location block that matches files with a .php extension. PHP-FPM runs the script and sends the result back through the same channel.
The link between Nginx and PHP-FPM can be built two ways: through a Unix socket or through a TCP address such as 127.0.0.1:9000. On a single server a socket is usually faster and does not occupy a port, while TCP is convenient when PHP-FPM runs in a separate container or on another machine. On ZevsHost.net shared hosting and VDS with cPanel and ISPmanager 6, a socket is used more often — the panel creates one automatically for every user.
Configuring the location for .php files
The basic block for a PHP site looks like this — a regex match, passing the socket, and a mandatory SCRIPT_FILENAME.
location ~ \.php$ {
include fastcgi_params;
fastcgi_pass unix:/run/php/php8.3-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
Without SCRIPT_FILENAME, PHP-FPM has no idea which file to run and returns a blank page or a "No input file specified" error. The fastcgi_params file usually lives in /etc/nginx/ and is loaded with the include directive — there is no need to rewrite it entirely, just add the missing parameters on top.
Socket or TCP: how to choose without dropping connections
The difference between the two connection methods lies in speed and in limits on the number of simultaneous connections.
| Method | Example address | When to use it |
|---|---|---|
| Unix socket | unix:/run/php/php8.3-fpm.sock | Nginx and PHP-FPM on the same server |
| TCP localhost | 127.0.0.1:9000 | PHP-FPM in a container, needs an explicit port |
| TCP over the network | 10.0.0.5:9000 | PHP-FPM moved to a separate server |
If Nginx logs show the error connect() to unix:/run/php/php8.3-fpm.sock failed (11: Resource temporarily unavailable), the socket queue is full: the PHP-FPM pool cannot process requests fast enough. The fix is to raise listen.backlog in the pool or increase the number of worker processes.
Tuning a PHP-FPM pool for load
A pool is described in a file such as /etc/php/8.3/fpm/pool.d/www.conf. Three parameters control how many requests PHP-FPM handles at once.
pm = dynamic
pm.max_children = 20
pm.start_servers = 4
pm.min_spare_servers = 2
pm.max_spare_servers = 8
pm.max_children is a hard cap on worker processes. It is calculated as: available memory minus memory for the system and Nginx, divided by the average size of one PHP process (usually 40-80 MB for a CMS like WordPress). Set it too high and the server swaps under peak load; set it too low and Nginx starts returning 502 on a traffic spike.
Diagnostics: where to look when the site will not open
The check order for a 502 or 504 error on a PHP-FPM site:
- Service status:
systemctl status php8.3-fpm. - The socket path in the pool config matches the path in
fastcgi_pass. - The PHP-FPM log in
/var/log/php8.3-fpm.logfor "max_children reached". - The Nginx log in
/var/log/nginx/error.logfor "upstream timed out".
A detailed breakdown of specific 502 and 504 error codes with commands for each case is covered in a separate article on 502 and 504 diagnostics. General rules on which location wins for .php files are covered in the article on location priority.
Summary: checklist for the Nginx and PHP-FPM link
- The socket path or TCP address in
fastcgi_passmatcheslistenin the PHP-FPM pool. - The
SCRIPT_FILENAMEparameter is set explicitly, not inherited from an old config template. pm.max_childrenis calculated from the server's RAM, not left at the default.- After editing configs,
nginx -tandsystemctl reload php8.3-fpmwere both run. - The link matches the PHP version actually installed on the server — check with the article on installing Nginx and the output of
php -v.