Linux VPS

Nginx and PHP-FPM over FastCGI: fastcgi_pass, params and buffers explained

How Nginx talks to PHP-FPM using FastCGI: what fastcgi_pass, SCRIPT_FILENAME and fastcgi_split_path_info do, Unix socket vs TCP, buffers and timeouts, and the security rule that stops PHP running uploads.

AdvancedLinux VPS3 min read

Nginx cannot run PHP itself. It forwards PHP requests to PHP-FPM using the FastCGI protocol and relays the answer. Most PHP-on-Nginx problems, from "File not found" to 502 errors and security holes, come from a few lines in that handover. This guide explains each line of a typical PHP location so you can write it correctly.

Before you start

A complete PHP location

location ~ \.php$ {
    try_files $uri =404;
    fastcgi_split_path_info ^(.+\.php)(/.+)$;
    include fastcgi_params;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    fastcgi_param PATH_INFO $fastcgi_path_info;
    fastcgi_index index.php;
    fastcgi_pass unix:/run/php/php8.3-fpm.sock;
    fastcgi_read_timeout 60s;
    fastcgi_buffers 16 16k;
    fastcgi_buffer_size 32k;
}

Line by line

try_files $uri =404

Only pass the request to PHP if the .php file really exists. Without it, a request such as /uploads/avatar.jpg/x.php could make older or misconfigured PHP setups execute an uploaded image as PHP. Debian's snippets/fastcgi-php.conf includes an equivalent check. Also keep security.limit_extensions = .php in the pool (the default).

fastcgi_split_path_info

Splits URLs like /index.php/products/42 into the script (/index.php) and PATH_INFO (/products/42). Needed by some frameworks; harmless otherwise. Note: with try_files $uri =404 such URLs 404, so apps using PATH_INFO need a location matching \.php(/|$) and a try_files $fastcgi_script_name =404 instead.

include fastcgi_params

Loads the standard variables PHP expects: REQUEST_METHOD, QUERY_STRING, CONTENT_TYPE, REMOTE_ADDR, SERVER_NAME, HTTPS and others. Debian also ships fastcgi.conf, identical except that it already sets SCRIPT_FILENAME.

SCRIPT_FILENAME

The most important parameter: the full path of the file PHP-FPM should run. $document_root$fastcgi_script_name becomes e.g. /var/www/example.com/public/index.php. If it is missing or wrong, PHP-FPM answers "Primary script unknown" and the browser shows File not found.

fastcgi_pass

Where PHP-FPM listens:

OptionExampleWhen to use
Unix socketunix:/run/php/php8.3-fpm.sockSame server; slightly faster, protected by file permissions
TCP127.0.0.1:9000PHP-FPM in another container or server; bind to localhost or a private IP only

Never expose a FastCGI port to the internet: anyone reaching it can make PHP-FPM run arbitrary files.

fastcgi_read_timeout

How long Nginx waits for PHP to reply. Too short gives 504s on slow pages; align it with PHP's limits as described in keep-alive and timeouts.

fastcgi_buffers and fastcgi_buffer_size

Nginx buffers PHP's response in memory so PHP-FPM is freed quickly, even for slow clients. fastcgi_buffer_size holds the response headers; large cookies or many headers overflow it and cause 502 "upstream sent too big header". 32k fixes most cases. Responses larger than the buffers spill to a temp file, which is fine.

Passing extra values to PHP

fastcgi_param APP_ENV production;
fastcgi_param PHP_VALUE "upload_max_filesize=64M \n post_max_size=64M";

PHP_VALUE changes php.ini settings per site. Prefer setting them in the pool with php_admin_value, which the app cannot override.

Telling PHP about HTTPS behind a proxy

If TLS ends at a load balancer, PHP sees plain HTTP. Map the forwarded header to the HTTPS param:

map $http_x_forwarded_proto $fastcgi_https { default ""; https on; }
fastcgi_param HTTPS $fastcgi_https if_not_empty;

Troubleshooting

  • "File not found." / "Primary script unknown": wrong SCRIPT_FILENAME or root, or PHP-FPM can't read the file (permissions, open_basedir, chroot).
  • 502 Bad Gateway: socket path wrong, PHP-FPM down, or socket permissions deny Nginx. See fix 502 with PHP-FPM.
  • PHP file downloads instead of running: the request never matched the PHP location (check location order).
  • "upstream sent too big header": raise fastcgi_buffer_size.

FAQ: Nginx and PHP-FPM over FastCGI

Socket or TCP: which is faster?

Sockets are marginally faster on the same machine. The difference rarely matters; choose by architecture.

Can one Nginx serve several PHP versions?

Yes. Point each site's fastcgi_pass at the matching version's socket.

What is FastCGI caching?

Nginx can store PHP output and reuse it: see Nginx FastCGI cache.

Next steps

Was this guide helpful?

Still stuck?

Ask MdmHost AI for a quick answer, or open a ticket and our team will take a look. We are here 24/7.