PHP-FastCGI on Windows¶
NGINX can interface with PHP on Windows via a FastCGI daemon, which ships with PHP: php-cgi.exe. You need to run php-cgi.exe -b 127.0.0.1: and use fastcgi_pass 127.0.0.1:; in the NGINX configuration file. After being launched, php-cgi.exe will keep listening for connections in a command prompt window. To hide that window, use the tiny utility RunHiddenConsole
Steps¶
- Install NGINX for Win32.
- Install the Windows binaries of PHP, making sure that php-cgi.exe is installed in the same directory as php.exe .
- Create somewhere (e.g. in c:\nginx\ ) a batch file start-php-fcgi.bat similar to this one:
@ECHO OFF ECHO Starting PHP FastCGI. set PATH=C:\PHP;%PATH% c:\bin\RunHiddenConsole.exe C:\PHP\php-cgi.exe -b 127.0.0.1:9123
root c:/www; location ~ \.php$ fastcgi_pass 127.0.0.1:9123; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; >
Autostarting PHP and NGINX¶
- Schedule a basic (on Windows Vista) task to run the batch file above at system start up under the SYSTEM account.
- If using Windows NGINX from https://kevinworthington.com/nginx-for-windows/, schedule a basic (on Windows Vista) task to run C:\nginx\conf\start-nginx.bat file at system start up under the SYSTEM account in starting directory C:\nginx .
- A home made Cygwin build of NGINX can be scheduled using a batch file similar to this:
cd /d C:\cygwin\bin && bash -c /usr/local/nginx/sbin/nginx
Nginx fastcgi php example
- The basics of TOGAF certification and some ways to prepare TOGAF offers architects a chance to learn the principles behind implementing an enterprise-grade software architecture, including.
- Haskell vs. PureScript: The difference is complexity Haskell and PureScript each provide their own unique development advantages, so how should developers choose between these two .
- A quick intro to the MACH architecture strategy While not particularly prescriptive, alignment with a MACH architecture strategy can help software teams ensure application .
- Postman API platform will use Akita to tame rogue endpoints Akita’s discovery and observability will feed undocumented APIs into Postman’s design and testing framework to bring them into .
- How to make use of specification-based test techniques Specification-based techniques can play a role in efficient test coverage. Choosing the right techniques can ensure thorough .
- GitHub Copilot Chat aims to replace Googling for devs GitHub’s public beta of Copilot Chat rolls out GPT-4 integration that embeds a chat assistant into Visual Studio, but concerns .
- Explore the key features of Microsoft Defender for Cloud Apps Monitoring and visibility are crucial when it comes to cloud security. Explore Microsoft Defender for Cloud Apps, and see how .
- 4 popular machine learning certificates to get in 2023 AWS, Google, IBM and Microsoft offer machine learning certifications that can further your career. Learn what to expect from each.
- Rein in services to avoid wasted cloud spend Organizations often make the easy mistake of duplicate purchases, which lead to wasted cloud spend. Learn strategies to avoid .
- Security hygiene and posture management: A work in progress Security hygiene and posture management may be the bedrock of cybersecurity, but new research shows it is still decentralized and.
- How to avoid LinkedIn phishing attacks in the enterprise Organizations and users need to be vigilant about spotting LinkedIn phishing attacks by bad actors on the large business social .
- Thoma Bravo sells Imperva to Thales Group for $3.6B With the acquisition, Thales looks to expand its Digital Security and Identity business with an increased focus on protecting web.
- AWS Control Tower aims to simplify multi-account management Many organizations struggle to manage their vast collection of AWS accounts, but Control Tower can help. The service automates .
- Break down the Amazon EKS pricing model There are several important variables within the Amazon EKS pricing model. Dig into the numbers to ensure you deploy the service .
- Compare EKS vs. self-managed Kubernetes on AWS AWS users face a choice when deploying Kubernetes: run it themselves on EC2 or let Amazon do the heavy lifting with EKS. See .
FastCGI Example¶
First thing, I recommend keeping all your typical FCGI settings in a single file and importing them.
For example you might have an /etc/nginx/fastcgi.conf (or /etc/nginx/fastcgi_params that’s installed by default on debian) file that looks like this:
#fastcgi.conf fastcgi_param GATEWAY_INTERFACE CGI/1.1; fastcgi_param SERVER_SOFTWARE nginx; fastcgi_param QUERY_STRING $query_string; fastcgi_param REQUEST_METHOD $request_method; fastcgi_param CONTENT_TYPE $content_type; fastcgi_param CONTENT_LENGTH $content_length; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param SCRIPT_NAME $fastcgi_script_name; fastcgi_param REQUEST_URI $request_uri; fastcgi_param DOCUMENT_URI $document_uri; fastcgi_param DOCUMENT_ROOT $document_root; fastcgi_param SERVER_PROTOCOL $server_protocol; fastcgi_param REMOTE_ADDR $remote_addr; fastcgi_param REMOTE_PORT $remote_port; fastcgi_param SERVER_ADDR $server_addr; fastcgi_param SERVER_PORT $server_port; fastcgi_param SERVER_NAME $server_name;
This allows you to keep your individual FCGI configurations as simple as possible. You may also want to replace $document_root in SCRIPT_FILENAME and DOCUMENT_ROOT with an actual path, the $document_root variable is hardcoded and may not reflect your install (will cause variations on ‘script not found’ errors, usually). To use NGINX + Virtual Host + PHP you should ommit the SCRIPT_NAME variable in order for PHP to choose the correct DOCUMENT_ROOT .
Spawning a FastCGI Process¶
Unlike Apache or Lighttpd, NGINX does not automatically spawn FCGI processes. You must start them separately. In fact, FCGI is a lot like proxying. There’s a few ways to start FCGI programs, but luckily PHP5 will auto-spawn as many as you set in the PHP_FCGI_CHILDREN environment variable. So we simply run php -b 127.0.0.1:9000 manually, or create an init script like so:
#!/bin/bash BIND=127.0.0.1:9000 USER=www-data PHP_FCGI_CHILDREN=15 PHP_FCGI_MAX_REQUESTS=1000 PHP_CGI=/usr/bin/php-cgi PHP_CGI_NAME=`basename $PHP_CGI` PHP_CGI_ARGS="- USER=$USER PATH=/usr/bin PHP_FCGI_CHILDREN=$PHP_FCGI_CHILDREN PHP_FCGI_MAX_REQUESTS=$PHP_FCGI_MAX_REQUESTS $PHP_CGI -b $BIND" RETVAL=0 start() echo -n "Starting PHP FastCGI: " start-stop-daemon --quiet --start --background --chuid "$USER" --exec /usr/bin/env -- $PHP_CGI_ARGS RETVAL=$? echo "$PHP_CGI_NAME." > stop() echo -n "Stopping PHP FastCGI: " killall -q -w -u $USER $PHP_CGI RETVAL=$? echo "$PHP_CGI_NAME." > case "$1" in start) start ;; stop) stop ;; restart) stop start ;; *) echo "Usage: php-fastcgi" exit 1 ;; esac exit $RETVAL
Save this to /etc/init.d/ (or wherever your init scripts are) as php-fcgi Install the usual way (for this debian init script, it’s update-rc.d php-fcgi defaults) and start it.
Connecting NGINX to the running FastCGI Process¶
Now that the FCGI process is running, we must tell NGINX to proxy requests to it via the FCGI protocol:
location ~ \.php$ include /etc/nginx/fcgi_params; #or whatever you named it fastcgi_pass 127.0.0.1:9000; >
Secure your upload directory!!¶
Too many example configs fail to secure the “uploads” directory of the application. Remember that if someone can upload a file named xyz.php and the uploads dir is publically accessible then you have given the attacker an easy way to insert PHP onto your site…
So if your app has an upload dir «/images/» then insert if ($uri !~ «^/images/») before fastcgi_pass , as so:
location ~ \.php$ include /etc/nginx/fastcgi_params; if ($uri !~ "^/images/") fastcgi_pass 127.0.0.1:9000; > >
PHP FastCGI Example¶
This example is for newer PHP (>= 5.3.3) using the included PHP FPM (FastCGI Process Manager).
This guide assume PHP FPM already installed and configured either using tcp port ( 127.0.0.1:9000 ) or unix socket ( /var/run/php-fpm.sock ).
There are many guide about configuring NGINX with PHP FPM, but many of them are incomplete (don’t handle PATH_INFO correctly) or contain security issues (don’t check whether the script is indeed php file).
FastCGI Params¶
First thing, I recommend keeping all your typical FCGI settings in a single file and importing them.
For example on debian and ubuntu by default there is /etc/nginx/fastcgi_params file that should look like this:
fastcgi_param QUERY_STRING $query_string; fastcgi_param REQUEST_METHOD $request_method; fastcgi_param CONTENT_TYPE $content_type; fastcgi_param CONTENT_LENGTH $content_length; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param SCRIPT_NAME $fastcgi_script_name; fastcgi_param PATH_INFO $fastcgi_path_info; fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info; fastcgi_param REQUEST_URI $request_uri; fastcgi_param DOCUMENT_URI $document_uri; fastcgi_param DOCUMENT_ROOT $document_root; fastcgi_param SERVER_PROTOCOL $server_protocol; fastcgi_param GATEWAY_INTERFACE CGI/1.1; fastcgi_param SERVER_SOFTWARE nginx/$nginx_version; fastcgi_param REMOTE_ADDR $remote_addr; fastcgi_param REMOTE_PORT $remote_port; fastcgi_param SERVER_ADDR $server_addr; fastcgi_param SERVER_PORT $server_port; fastcgi_param SERVER_NAME $server_name; fastcgi_param HTTPS $https; # PHP only, required if PHP was built with --enable-force-cgi-redirect fastcgi_param REDIRECT_STATUS 200;
Please note if you’re using Ubuntu Precise (12.04), I change SCRIPT_FILENAME and add PATH_INFO params.
Connecting NGINX to PHP FPM¶
Now we must tell NGINX to proxy requests to PHP FPM via the FCGI protocol:
location ~ [^/]\.php(/|$) fastcgi_split_path_info ^(.+?\.php)(/.*)$; if (!-f $document_root$fastcgi_script_name) return 404; > # Mitigate https://httpoxy.org/ vulnerabilities fastcgi_param HTTP_PROXY ""; fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; # include the fastcgi_param setting include fastcgi_params; # SCRIPT_FILENAME parameter is used for PHP FPM determining # the script name. If it is not set in fastcgi_params file, # i.e. /etc/nginx/fastcgi_params or in the parent contexts, # please comment off following line: # fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; >
If you’re using unix socket change fastcgi_pass to:
fastcgi_pass unix:/var/run/php-fpm.sock;