Update November 7, 2010
There’s now an updated version of this tutorial which also covers incorporating MySQL.
If you’ve ever needed a very fast, stable, no frills, web server to serve up some pages on a home system, then look no further than nginx. The server is rock solid and gets the job done. And the setup and configuration is unmatched in simplicity for other servers of similar capability.
Nginx is native to the UNIX platform, so you’ll need to get a precompiled version or install Cygwin. I opted for the former because there’s already a package available by Kevin Worthington that works very nicely.
Download the stable package and install it. Because of the Cygwin configuration, it will install to c:\nginx.
Then download the latest PHP Windows binaries (not the installer) and extract all files to c:\nginx\php. We will be using php-cgi.exe because of the nginx fast-cgi capability. Make sure the path is c:\nginx\php\php-cgi.exe during the installation.
Almost there…
Go into c:\nginx\conf and uncomment or modify the following lines in nginx.conf.
location ~ .php$ {
root html;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME c:/nginx/html/$fastcgi_script_name;
include fastcgi_params;
}
Then, in the same folder, edit start-nginx.bat to include the following line :
@ECHO OFF
c:\nginxnginx.exe
c:\nginx\php\php-cgi.exe -b 127.0.0.1:9000 -c c:\nginx\php\php.ini
ping 127.0.0.1 -n 1>NUL
echo Starting nginx
echo .
echo .
echo .
ping 127.0.0.1 >NUL
EXIT
Now edit stop-nginx.bat and add the following lines :
@ECHO OFF
taskkill /f /IM nginx.exe
taskkill /f /IM php-cgi.exe
EXIT
It’s not a perfect solution, but works for non-production applications.
That should be it!
If you need to hide that ugly command prompt during startup, just create two files in conf (alongside start-nginx.bat) and enter the following code :
In launch.js :
var objShell = WScript.CreateObject("WScript.Shell");
var result = objShell.Run("cmd.exe /c start-nginx.bat", 0);
// Give some startup time
WScript.Sleep(3000);
// Navigate to homepage
objShell.Run("http://localhost");
In shutdown.js :
var objShell = WScript.CreateObject("WScript.Shell")
var result = objShell.Run("cmd.exe /c stop-nginx.bat", 0)
Now to startup nginx with fast-cgi PHP, just double-click launch.js. To stop, double-click shutdown.js.
You can make yourself a HTML Application to run these JavaScripts and build a basic control panel at a future date.
Update 12/08
Changed the php.ini file location to an absolute path.
Changed the stop-nginx.bat commands to taskkill instead of multiple process -k lines (you can never tell how many instances there may be of php-cgi.exe, so it’s impractical to do it the old way).
Note: Copying entire blocks is recommended as parts of the code is hidden by my display theme. However all the text is there. Hightlighting the whole thing will ensure that no parts are left behind.
Very nice post. I will be linking to you when people email me to ask how to get PHP running with my Nginx for Windows packages. Thanks!
Thanks!
And thank you for creating that package!
Pingback: nginx + PHP on Windows in 5 minutes | PHP-Blog.com
I’m trying to build a WordPress site, but I can’t get nginx and PHP (FastCGI) to run. I’ve tried following your instructions but the script hangs on the php-cgi.exe command (and won’t go on to start MySQL which is what I want next!).
Can you give me any suggestion or a location for a log file to look at?
Thanks, John
Hi John.
Unfortunately, I never got to get this past the basic PHP+Nginx combo. MySQL was my next step, but work got in the way.
I hope to have a revised set of steps for this soon.
I am not able to find start-nginx.bat file or other bat file also.
i have installed it to C:\nginx\nginx-0.7.61. How to get those bat file? should we create them.?
Hi Dheeraj.
Once installed, the bat file should be located at : conf\start-nginx.bat Inside your installed folder.
Or if you followed the default steps for the installation, C:\nginx\conf\start-nginx.bat. I recommend installing it to default folders since it’s easier to find where the files are.
In fact, in your start menu, you should see the Nginx folder with links to start and stop the server. Right click on the “Start nginx” link and select “properties”. You should see the path to the file.
But in the instructions, I mention that you should download the “stable” branch of Nginx. Which is 0.6.36 as of this post.
I say to use the stable branch since the development branch may have unforseen issues that could cause problems with the PHP installation.
The steps should be the same for both versions.
I’m with Dheeraj above. Grabbing the precompiled binaries from nginx.net, the .bat files are not included. I dug a little deeper and still couldn’t find the .bat’s in the previous stable releases either. :(
Any ideas here?
Maybe this is it.. Sorry for the clutter.. derived from:
http://www.water3d.com/scripts/php
>> nginx\conf\start-nginx.bat
@ECHO OFF
ECHO Starting PHP FastCGI…
RunHiddenConsole.exe “X:\php\php-cgi.exe” -b 127.0.0.1:9000 -c “X:\php\php5.ini”
echo MySQL is starting with mysql\bin\my.cnf
RunHiddenConsole.exe “X:\mysql\bin\mysqld.exe” –defaults-file=”X:\mysql\bin\my.cnf”
start nginx.exe
ping 127.0.0.1 -n 1>NUL
echo Starting nginx
echo .
echo .
echo .
ping 127.0.0.1 >NUL
EXIT
>> nginx\conf\stop-nginx.bat
@ECHO OFF
ECHO Stopping Nginx…
process -k nginx.exe >nul
process -k nginx.exe
process -k nginx.exe
process -k nginx.exe
ECHO Stopping PHP FastCGI…
process.exe -k php-cgi.exe >nul
ECHO Stopping MySQL…
process -k mysqld.exe >nul
EXIT
Great post! I was hoping not to have to resort to VPC on my windows box. Could it be that your paths are missing slashes or that they have been stripped from above?
Hi Bronius
You’re right! WordPress ate my backslashes! :(
I’m not sure why that happened. It could have been some update made by them. I can’t seem to add them back again.
That modified code you posted looks pretty good actually. I think that’s all you need to control nginx and mysql from the commandline.
I’m glad you found it useful.
i try to run nginx-start.bat but wont start php-cgi. i modify a bit and it works in my station.
and thanks. nice post
Hi Barz
Thanks!
And thanks for sharing!
It might be that WordPress is screwing up the formatting on my code. For some reason, they’ve all been modified since they updated.
Excellent work .. best place to learn Nginx installation and fixing issues faced
Thank you!
Hi,
i am trying but i have a problem in error.log and i cant access http://localhost/
4 [win] nginx 4804 sig_send: wait for sig_complete event failed, signal 23, rc 258, Win32 error 0
87160346 [main] nginx 4804 fork: child 4828 – died waiting for dll loading, errno 11
2010/03/05 13:18:42 [alert] 4804#0: fork() failed while spawning “worker process” (11: Resource temporarily unavailable)
2010/03/05 13:21:10 [alert] 4804#0: unknown process 4828 exited on signal 1
can help-me?
thanks
Hi hussan, sorry for the late reply.
I think that may have something to do with the version of Cygwin used to compile the nginx package. Or there may be another instance of nginx already running.
Check your running processes list in Ctrl+Alt+Del and see if there isn’t another instance of nginx already running.
I would recommend using the stable branch of the nginx package as well. This way we can rule out any Cygwin issues.
Whenever a .php file is opened, I get the message (in browser) “no input file specified”
I think the problem is that I forgot to modify this line:
fastcgi_param SCRIPT_FILENAME /nginx/html$fastcgi_script_name;
But I have no idea how to format it. Can you give me an example?
Hi Zemn
Sorry, I just added some more backslashes to this post.
It should be :
fastcgi_param SCRIPT_FILENAME c:/nginx/html/$fastcgi_script_name;
When I first posted this code it was a few versions of WordPress ago. Back then, the content formatter wasn’t cooperating ;)
Pingback: dokuwiki in Portable Nginx « derrick's blog
wanna share, just relesased: new project called NGINXMP for windows. suitable for newbie or development purpose.
link: http://sourceforge.net/projects/nginxmp/
Hi iqbal,
I’ve been looking for an all in one solution for PHP + MySQL and nginx.
I’ll definitely be testing that out.
Thanks for sharing!
Slightly off topic but here goes:
Is there a simple way to add virtualhosts for this? This seems to be the only option:
http://blog.taragana.com/index.php/archive/tips-on-configuring-nginx-for-virtual-hosting/
Hi Aron,
I think you need to take a peek at the virtual hosting setup on the nginx wiki and then look at a more elaborate example for more complex setups.
Great post and really helpful responses!
I was looking for a light server with PHP capabilities in Windows 7, and I’ve found it.
I have to put the bat and js start/stop files in the same directory as nginx.exe, as I had problems with log files:
C:\winapp32\nginx\conf>c:\winapp32\nginx\nginx.exe
[alert]: could not open error log file: CreateFile() “logs/error.log” failed (3: FormatMessage() error:(15100))
2010/06/26 03:05:03 [emerg] 8616#8352: CreateFile() “C:\winapp32\nginx\conf/conf/nginx.conf” failed (3: FormatMessage() error:(15105))
Great post and really helpful responses!
I was looking for a light server with PHP capabilities in Windows 7, and I’ve found it.
In my box, I have to put the bat and js start/stop files in the same directory as nginx.exe, as I had problems with log files:
C:\winapp32\nginx\conf>c:\winapp32\nginx\nginx.exe
[alert]: could not open error log file: CreateFile() “logs/error.log” failed (3: FormatMessage() error:(15100))
2010/06/26 03:05:03 [emerg] 8616#8352: CreateFile() “C:\winapp32\nginx\conf/conf/nginx.conf” failed (3: FormatMessage() error:(15105))
Hi Mcortizo, Thanks!
I think it doesn’t allow nginx to create or open a new log file when it first runs. nginx Needs to open a log file when it first runs or create a new one if it doesn’t exist yet.
Note the last part :
CreateFile() “C:\winapp32\nginx\conf/conf/nginx.conf” failed
The backslashes switch direction.
Try installing nginx to C:\nginx instead and see if this changes. Because nginx was originally designed for Unix-like platforms, that package is fairly limited in where it can be installed.
Pingback: nginx + PHP on Windows in 5 minutes (via This page intentionally left ugly) « JayGreentree
Pingback: nginx + PHP on Windows in 5 minutes - Nginx with PHP
Hey, nice post! I tried to follow your steps but there was no php-cgi.exe file in the PHP installation. Is that something that is deprecated from 5.3.x? I’m going to start digging in deeper to nginx any day. Thanks for the great post!
Hi Anton, Thank you!
I just downloaded the latest stable 5.3.3 Win32 binaries and it seems php-cgi.exe is still there.
I don’t think it’s deprecated, but watch out for the error :
“php-cgi.exe The FastCGI process exited unexpectedly”
I think a few people are coming across this problem in the 5.3.x branch and they all seem to be on Windows (Vista or 7), but it may be solved in the new stable version. It may have something to do with the php.ini settings, but I haven’t tried it out just yet.
try XENSTACK at http://sourceforge.net/projects/xenstack/
just install and run on Mirosoft Windows
Hi Riez, Thanks for the link
I originally posted this a almost two years ago when we didn’t have a native Nginx build for Windows. I’ll have to try out xenstack.
Pingback: Nginx + PHP + MySQL on Windows in 6 minutes « This page intentionally left ugly
hey guys
dont create those JAVA files… they can be edited by any people with acess to the machine, and… they files can be run comands directly to the machine (cmd.exe).
this can compromise the system and your privacy.
Java files? You mean JavaScript? The two are completely different.
Also, if someone can already gain access to your PC to edit the JavaScript files, then your security has already compromised elsewhere. If they can edit these scripts, then they have access to any other file on your system, including the Windows folder.
Running a helper JScript file locally on a Windows machine is no different from running a helper bash script in on a *Nix platform which admins have been doing for a couple of decades.
I found an alternative to using bat files :
http://welpressed.sourceforge.net/
1
Pingback: Install nginx PHP on Windows | Nginx Lighttpd Tutorial
When i try to acess a folder inside the html folder, apears: Acess Denied. How can i solve this ?
Hi Raul,
This is usually caused by the config not allowing indexes and there’s no index.html or index.php file in the folder you’re trying to view. Make sure there’s an index file in the folder you’re trying to access and see if it works.
Also, try browsing the basic configuration options for Nginx and see if you’ve changed something that could cause this.
Thanks, i found the problem.
You need to set “index.php” in the “location” directive. e.g:
location / {
root html;
index index.html index.htm index.php;
}
Hehe
Instead of using JScript to call the batch files, you can simply start/stop nginx and php with the script files itself (I used VBS).
launch.vbs:
Set objShell = WScript.CreateObject(“WScript.Shell”)
Call objShell.Run(“c:\nginx\nginx.exe”, 0)
Call objShell.Run(“c:\nginx\php\php-cgi.exe -b 127.0.0.1:9000 -c c:\nginx\php\php.ini”, 0)
shutdown.vbs:
Set objShell = WScript.CreateObject(“WScript.Shell”)
Call objShell.Run(“taskkill /f /IM nginx.exe”, 0)
Call objShell.Run(“taskkill /f /IM php-cgi.exe”, 0)
Pingback: nginx + PHP on Windows | XFloyd's blog
Pingback: Installing nginx + php in Windows | Another T.Lam's Blog
the PHP FastCGI often stop by itself. can u tell me what’s wrong?
it always happens a few minutes after i tested my site by sending 100 request simultaniously and the test always failed.
Hi Oscar,
It may be a long running script consuming too much memory or maybe there’s a memory leak somewhere. PHP may have a bug as well that’s stopping FastCGI, so try and see if the latest PHP version (5.4.0 as of this post) is what you’re using.
You’re not the only one who’s having this problem.
can you tell me where to download the latest version? the one i downloaded from php.net doesn’t have php.exe
i don’t know how to install it
The windows binaries are located here. Be sure to get the Therad Safe zip. But in my example, we’re not using php.exe, it has to be php-cgi.exe since we’re channeling .php requests to it via FastCGI in nginx.
Mega old but… php-cgi.exe exits after exactly 1000 requests which is default value for env variable PHP_FCGI_MAX_REQUESTS. You can change that value but it will only move the problem in the future. BTW. it’s not recommended to put value of milion there ;-)
We need to create a .cmd file to recycle php-cgi.exe.
Easy solution:
1) Create first file called multi_runcgi.cmd and put it inside:
@ECHO OFF
ECHO Starting PHP FastCGI…
set PATH=C:\PHP;%PATH%
set PHP_FCGI_CHILDREN=0
set PHP_FCGI_MAX_REQUESTS=10000
:loop
c:
cd \php
C:\PHP\php-cgi.exe -b 127.0.0.1:%1
set errorlvl=%errorlevel%
rem do some logging here if required
timeout /T 3
goto loop
2) Create second file called initialize_runcgi.cmd
@ECHO OFF
ECHO Starting PHP FastCGI…
c:
cd \php
start multi_runcgi.cmd 9001
start multi_runcgi.cmd 9002
start multi_runcgi.cmd 9003
start multi_runcgi.cmd 9004
start multi_runcgi.cmd 9005
start multi_runcgi.cmd 9006
start multi_runcgi.cmd 9007
start multi_runcgi.cmd 9008
start multi_runcgi.cmd 9009
start multi_runcgi.cmd 9010
Lastly run the multi_runcgi.cmd file using Task Scheduler with account proper for your PHP scripts – you know, file permissions and etc.
Now you have 10 php-cgi.exe processes with ports 9001-9010 to use by NGINX backend.
If one of the process will exit because out of requests it comes to timeout 3 and start php-cgi.exe again with proper port value.
Second harder approach[which I’m using] is to make a loop where you check if the process exists and eventually recover it.
Create a CMD file with some name and start it through Task Scheduler with proper account.
Only one file is needed to start NGINX and php-cgi.exe. I’m using it to start PHP5 and PHP7 simultaneously.
You can change __PHP_DEBUG to =1 and run it manually with Run As Admin to check for errors.
File:
@ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
REM Respawn php-fcgi by Jacek K e-mail: jack_@wp.pl
REM Copyright (c) 2012
SET __PHP_DEBUG=0
SET __PHP_IP=127.0.0.1
REM PHP5 port settings
SET __PHP5_PORT_START=9000
SET __PHP5_PORT_END=9009
REM PHP7 port settings
SET __PHP7_PORT_START=9050
SET __PHP7_PORT_END=9059
REM Sleep time between checks
SET __PHP_SLEEP=30
REM PHP5 and PHP7 paths
SET __PHP5_PATH=C:\nginx\php_nts\php-cgi.exe
SET __PHP7_PATH=C:\nginx\php7_nts_x64\php-cgi.exe
SET __PHP5_INI_PATH=C:\nginx\php_nts\php.ini
SET __PHP7_INI_PATH=C:\nginx\php7_nts_x64\php.ini
REM Stop all orphan services
taskkill /f /IM nginx.exe
taskkill /f /IM php-cgi.exe
REM Start nginx server
START /B c:\nginx\nginx.exe
REM Let the batch manage respawn of php-cgi.exe [start values]
REM set PHP_FCGI_CHILDREN=0
SET PHP_FCGI_MAX_REQUESTS=1000
:loop
IF %__PHP_DEBUG% EQU 1 ECHO +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
IF %__PHP_DEBUG% EQU 1 ECHO Respawn start: %DATE% – %TIME%
IF %__PHP_DEBUG% EQU 1 ECHO +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
REM PHP5 loop
FOR /L %%A IN (%__PHP5_PORT_START%,1,%__PHP5_PORT_END%) DO (
wmic PROCESS WHERE “Name=’php-cgi.exe’ AND CommandLine LIKE ‘%%%__PHP_IP%:%%A%%'” get Name | find “php” >nul
IF ERRORLEVEL 1 START /B %__PHP5_PATH% -b %__PHP_IP%:%%A -c %__PHP5_INI_PATH%
IF %__PHP_DEBUG% EQU 1 IF ERRORLEVEL 1 ECHO Respawn: PHP5 %__PHP_IP%:%%A
)
REM PHP7 loop
FOR /L %%A IN (%__PHP7_PORT_START%,1,%__PHP7_PORT_END%) DO (
wmic PROCESS WHERE “Name=’php-cgi.exe’ AND CommandLine LIKE ‘%%%__PHP_IP%:%%A%%'” get Name | find “php” >nul
IF ERRORLEVEL 1 START /B %__PHP7_PATH% -b %__PHP_IP%:%%A -c %__PHP7_INI_PATH%
IF %__PHP_DEBUG% EQU 1 IF ERRORLEVEL 1 ECHO Respawn: PHP7 %__PHP_IP%:%%A
)
IF %__PHP_DEBUG% EQU 1 ECHO =========================================================================
TIMEOUT /T %__PHP_SLEEP%
GOTO :loop
Lastly run the multi_runcgi.cmd -> MISTAKE
Lastly run the initialize_runcgi.cmd -> CORRECT
try this
http://www.edisongotan.com/installing-nginx-with-php-on-windows/
how to enable .htaccess in nginx for windows
i installed, nginx and php and mysql for windows
everything running fine
i shift my web from linux hosting company to my window pc ( where these servers running )
my web application have .htaccess file for rewriet mode/rules etc
and its not working due to .htaccess
pls advice where i enable .htaccess for my web application
Unfortunately, you can’t use .htaccess with nginx because it’s a completely different format. .htaccess is for Apache server only. Try browsing the rewrite syntax for nginx.
I have followed your directions and am trying to test the PHP. php-cgi.exe is running and I created an index.php file that has in it, but when I try to view it from a browser all I get is a page that says “No input file specified.”
Admittedly I only marginally understand what I’m doing, but this sounds like a pretty stright-forward problem. What are some things I should check?
Mike…
Hi Michael,
Sorry for the late reply. I’ve been busy with other… er… stuff.
Most of the time, “No input file specified” means there’s an error in the path Nginx has for the fast cgi.
In nginx.conf check for this line:
And see if it’s correct or try and change that to :
This is how the nginx wiki actually has it setup. I’m actually going to rewrite this whole tutorial from scratch (especially since it’s pretty old and there are new versions for all of the software out) so these hiccups should be fewer.
There is also WT-NMP – portable Nginx Mysql Php development stack for Windows:
https://sourceforge.net/projects/wtnmp/
You ought to take part in a contest for one of the highest quality
websites on the net. I am going to highly recommend this blog!
Hi i have problem with rewriting, i have to use not c:/nginx/html/ but “/nginx/html”
because nginx looks : /cygdrive/c/nginx/… and if there is c:/ its error..
hi,
how to harden a windows server using nginx. i have started nginx on the server. help me out on this
Hi,
Php needs some VS dlls that you can download at http://www.microsoft.com/en-us/download/details.aspx?id=30679
Thanks for your article.
Sorry if this is ovious for others, but I can’t figure out whether to get the non-thread safe or thread safe php binaries for use with nginx. As far as I’ve read, FasCGI manages the process it has quite nicely, thus not needing the thread-safe variant, is this correct?
Sorry…as always: Once you start asking, you find the answer immediately.
nginx on FastCGI PHP does not require PHP to have thread-safety for PHP does not integrate within the nginx server directly. (Like it does with Apache through the mod_php module)
Thus by using nginx, especially with FastCGI PHP, a new thread is opened for every request going from nginx to PHP, thus no threads are used, thus PHP can be non-thread-safe, thus the NTS version of the php binaries will do.
Source: http://stackoverflow.com/questions/1623914/what-is-thread-safe-or-non-thread-safe-in-php
I should clarify, at the time of this post, Nginx behavior for FastCGI on Windows had certain issues, which is why I recommend the thread safe version. You have to realize that Nginx was Cygwin compiled; not native binary, since it originally was designed for *nix platforms.
The thread-safe PHP was recommended due to very peculiar behavior on Windows. It has caused unpredictable crashes or file access conflict issues (particularly if you use SQLite or other file based access) due to certain race conditions. SQLite is better at handling these so you’ll have fewer issues if you use it instead of just file based storage.
When using MySQL, using transactions whenever you’re adding/updating rows (even if it’s just one) is highly recommended.