How to set NGINX with PHP on Windows
To have a local server that uses PHP on Windows, there are many options. Nginx is one of them, but we need to have some ideas on how to configure Nginx to use PHP.
Recently, I formatted my PC and in order to avoid installing XAMPP again, I decided to install NGINX and follow the configuration recommended by others, although it didn’t work too well for me, so let’s see how I did my installation and configuration.
[Info] The installation that we will see in this post will be for doing projects in the local environment, for production you should take a different approach[/info]
Nginx Installation
To install Nginx on Windows, we don’t need much. We simply need to go to http://nginx.org/en/download.html and download the latest stable version.
Once the file has been downloaded, we can unzip it and copy the folder inside to wherever we want, for example to C:\Nginx and change its name to Nginx. We can also place it in our user’s folder, in my case C:\Users\luisg\Nginx.
PHP installation
To install PHP in this case, I used Chocolatey with its GUI (graphic user interface). You can see how to install Chocolatey in https://blastcoding.com/en/chocolatey-a-package-manage-for-windows/
Just select what you want to install and that’s it. As you can see, I also installed Composer. These days, having PHP without Composer is like competing with a cart against a car.
Config of Nginx to use PHP
Nginx comes with a default configuration for PHP, but it will not work in all cases, since it is designed for use on Linux. Let’s see this configuration:
NGINX – nginx.conf#user nobody; worker_processes 1; #error_log logs/error.log; #error_log logs/error.log notice; #error_log logs/error.log info; #pid logs/nginx.pid; events { worker_connections 1024; } http { include mime.types; default_type application/octet-stream; #log_format main '$remote_addr - $remote_user [$time_local] "$request" ' # '$status $body_bytes_sent "$http_referer" ' # '"$http_user_agent" "$http_x_forwarded_for"'; #access_log logs/access.log main; sendfile on; #tcp_nopush on; #keepalive_timeout 0; keepalive_timeout 65; #gzip on; server { listen 80; server_name localhost; #charset koi8-r; #access_log logs/host.access.log main; location / { root html; index index.html index.htm; } #error_page 404 /404.html; # redirect server error pages to the static page /50x.html # error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } # proxy the PHP scripts to Apache listening on 127.0.0.1:80 # #location ~ \.php$ { # proxy_pass http://127.0.0.1; #} # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000 # #location ~ \.php$ { # root html; # fastcgi_pass 127.0.0.1:9000; # fastcgi_index index.php; # fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name; # include fastcgi_params; #} # deny access to .htaccess files, if Apache's document root # concurs with nginx's one # #location ~ /\.ht { # deny all; #} } # another virtual host using mix of IP-, name-, and port-based configuration # #server { # listen 8000; # listen somename:8080; # server_name somename alias another.alias; # location / { # root html; # index index.html index.htm; # } #} # HTTPS server # #server { # listen 443 ssl; # server_name localhost; # ssl_certificate cert.pem; # ssl_certificate_key cert.key; # ssl_session_cache shared:SSL:1m; # ssl_session_timeout 5m; # ssl_ciphers HIGH:!aNULL:!MD5; # ssl_prefer_server_ciphers on; # location / { # root html; # index index.html index.htm; # } #} }
From this file, we are interested in the part that matters most to us, which is the location ~ \.php$
part, which we must uncomment, leaving it as follows.
location ~ \.php$ { root html; fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name; include fastcgi_params; }
In this code snippet from our nginx.conf file, we can see that it has: root
, fastcgi_pass
, fastcgi_index
y fastcgi_param
root
– This is where our server will look. In my case, I left it in html folder but with its full path throughout the file.
For example, if I want to have multiple sites that will be folders placed in the html folder, therefore, when I upload the server if I search localhost/automotora it will be the page hosted in C:/Users/luisg/Nginx/html/automotora
fastcgi_pass
– In this configuration we see that we pass it a socket 127.0.0.1:9000 which is constituted by the ip and port where php-cgi will listen. We will not touch this configuration unless necessary
fastcgi_index
– we will not touch it clearly, we want our index to be index.php although we could also set it to be home.php
fastcgi_param
– with this configuration we will define parameters that we will pass to fastcgi, in this case SCRIPT_FILENAME
is enough, in this case it is telling you that the PHP files are in the scripts folder we will change this to $document_root$fastcgi_script_name
in this way we will tell you that we will check from root.
#user nobody; worker_processes 1; #error_log logs/error.log; #error_log logs/error.log notice; #error_log logs/error.log info; #pid logs/nginx.pid; events { worker_connections 1024; } http { include mime.types; default_type application/octet-stream; #log_format main '$remote_addr - $remote_user [$time_local] "$request" ' # '$status $body_bytes_sent "$http_referer" ' # '"$http_user_agent" "$http_x_forwarded_for"'; #access_log logs/access.log main; sendfile on; #tcp_nopush on; #keepalive_timeout 0; keepalive_timeout 65; #gzip on; server { listen 80; server_name localhost; #charset koi8-r; #access_log logs/host.access.log main; location / { root C:/Users/luisg/Nginx/html; index index.html index.htm index.php; } #error_page 404 /404.html; # redirect server error pages to the static page /50x.html # error_page 500 502 503 504 /50x.html; location = /50x.html { root C:/Users/luisg/Nginx/html; } # proxy the PHP scripts to Apache listening on 127.0.0.1:80 # #location ~ \.php$ { # proxy_pass http://127.0.0.1; #} # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000 # location ~ \.php$ { root C:/Users/luisg/Nginx/html; fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; #fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name; include fastcgi_params; } # deny access to .htaccess files, if Apache's document root # concurs with nginx's one # #location ~ /\.ht { # deny all; #} } # another virtual host using mix of IP-, name-, and port-based configuration # #server { # listen 8000; # listen somename:8080; # server_name somename alias another.alias; # location / { # root html; # index index.html index.htm; # } #} # HTTPS server # #server { # listen 443 ssl; # server_name localhost; # ssl_certificate cert.pem; # ssl_certificate_key cert.key; # ssl_session_cache shared:SSL:1m; # ssl_session_timeout 5m; # ssl_ciphers HIGH:!aNULL:!MD5; # ssl_prefer_server_ciphers on; # location / { # root html; # index index.html index.htm; # } #} }
Creating a BATCH file to start PHPCGI and NGINX
To start PHP-CGI with this command in the console, it would be enough to execute C:\tools\phpX\php-cgi.exe -b 127.0.0.1:9000
, where X in this example would represent the version.
But keep in mind that we should also run Nginx and terminate the processes when indicated. For this, we could use taskkill /f /im nginx.exe
to terminate Nginx and taskkill /f /im php-cgi.exe
to terminate PHP CGI.
The following batch script was made with the help of ChatGPT, and I made some corrections to make it work.
I don’t know as much about batch scripting as one might think upon seeing this file, but it’s still understandable enough. We have 2 labels: :terminate_services
and :main
. All the “REM” lines are comments, “start” is used to initiate a command, etc.
Using “goto” will move to the designated label, although it may seem like a good idea, avoid doing this in programming languages, or you’ll end up with spaghetti code.
archivo.bat@echo off :main REM Start Nginx start "Nginx" nginx.exe REM Start PHP-CGI start "PHP-CGI" "C:\tools\php83\php-cgi.exe" -b 127.0.0.1:9000 REM Wait for user input to stop services set /p input=Enter 'exit' to stop services: if /I "%input%"=="exit" goto :terminate_services goto :main :terminate_services REM Kill PHP-CGI task taskkill /f /im php-cgi.exe echo PHP-CGI has been stopped. REM Kill Nginx task taskkill /f /im nginx.exe echo Nginx has been stopped. exit /b
html
or/html
.