Nginx + PHP FastCGI on Windows: no php-fpm, no fantasy
Run php-cgi as a FastCGI listener, point Nginx at it, set SCRIPT_FILENAME and fix_pathinfo, and know why IIS FastCGI is often the better Windows choice.
- Build
- 26100.33650
- Edition
- Standard / Datacenter
- Architecture
- x64
- Support
- Documentation (E1)
- Evidence
- E1Official documentation
- Verified
- 2026-10-29
- Page type
- Task
The short answer
Section titled “The short answer”Nginx does not spawn PHP workers. On Windows you start php-cgi.exe as a FastCGI listener and point Nginx at it:
C:\PHP\8.4\php-cgi.exe -b 127.0.0.1:9000 -c C:\PHP\8.4\php.iniThen:
location ~ \.php$ { include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_pass 127.0.0.1:9000;}There is no official Windows php-fpm. If a guide says “install php-fpm on Windows”, it is using a third-party build or confusing FastCGI with FPM.
Full server block
Section titled “Full server block”server { listen 8084; server_name php.local; root C:/sites/php; index index.php index.html;
location / { try_files $uri $uri/ =404; }
location ~ \.php$ { include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param HTTPS $https if_not_empty; fastcgi_pass 127.0.0.1:9000; fastcgi_read_timeout 60s; }}SCRIPT_FILENAME is the one parameter people forget. Without it, PHP-CGI returns “No input file specified” or a blank page.
php.ini for this mode
Section titled “php.ini for this mode”cgi.fix_pathinfo=0fastcgi.impersonate=1date.timezone=UTCexpose_php=Offdisplay_errors=Offlog_errors=Oncgi.fix_pathinfo=0 plus try_files/=404 prevents a nonexistent .php path from being passed to PHP-CGI. It is not a substitute for upload validation.
Process supervision
Section titled “Process supervision”PHP-CGI is a process you must keep alive:
- run it under WinSW/NSSM or a scheduled task with restart;
- set
PHP_FCGI_MAX_REQUESTS(e.g. 500) so workers recycle; - log stderr/stdout somewhere outside the web root;
- monitor the listener (
Test-NetConnection 127.0.0.1 9000); - do not start a second listener on 9000.
For a Windows-only server, IIS FastCGI usually supervises PHP better than a hand-wrapped php-cgi; use Nginx+PHP when you already standardize on Nginx or need its config model.
Verify
Section titled “Verify”& C:\PHP\8.4\php-cgi.exe -vTest-NetConnection 127.0.0.1 -Port 9000Set-Content C:\sites\php\info.php '<?php phpinfo();' -Encoding ASCIIcurl.exe -I -H "Host: php.local" http://127.0.0.1:8084/info.phpRemove info.php after the test.
Lab boundary
Section titled “Lab boundary”E1 for Nginx+PHP. The lab installed PHP 8.4.27 and verified IIS FastCGI, but did not run php-cgi behind Nginx. The Nginx config is the next verification step, not a reproduced claim.