Nginx with PHP and MySQL on Windows 7

3:57 am Windows Development

In the past, whenever I needed a web server on Windows, I would install the XAMPP distribution (comes with Apache, PHP, and MySQL) and call it a day. This time, I wanted to use Nginx instead of Apache as the web server. Below are the steps I took to install Nginx, PHP and MySQL separately on Windows 7.

Install Nginx

Nginx is pretty easy to install on Windows. Just do the following:

  1. Download the latest Nginx for windows version. (Currently, only 32-bit versions are available.)
  2. Unzip to a directory like “c:\nginx”.
  3. Create two subdirectories which “nginx.exe” expects to exist:
    mkdir c:\nginx\logs
    mkdir c:\nginx\temp
  4. If you want to change the document root from the default “c:\nginx\html” and/or enable directory listing, edit the “c:\nginx\conf\nginx.conf” file and adjust the global “location /” declaration like so:
            location / {
                #root   html; # comment out default root at "nginx_install_dir\html"
                root   /www;  # use new root "c:\www" (assuming nginx is install on c: drive)
                index  index.html index.htm;
                autoindex on; # Add this to enable directory listing
            }
  5. To run the Nginx web server, launch the “Command Prompt” and issue these commands:
    # Go to Nginx installation directory
    c:
    cd \nginx

    # Start Nginx
    start nginx.exe

    Notes:

    • Running “c:\nginx\nginx.exe” without changing to the “c:\nginx” directory will fail because Nginx will look for the log and temp subdirectories, which won’t exist under another directory.
    • The “start” command will launch Nginx in a separate window; otherwise, Nginx would take control of the current “Command Prompt” window. That separate window will appear and quickly disappear.
    • It is not necessary to run the “Command Prompt” as an administrator.
  6. Browse to http://localhost/ . You should see a “Welcome to nginx!” page.
  7. To quit Nginx, in the “Command Prompt” window, do the following:
    # Go to Nginx installation directory
    c:
    cd \nginx

    # Quit Nginx
    nginx.exe -s quit

    If you have started Nginx more than once, the quit command above will only kill the last Nginx process started. To kill all Nginx processes, run the following:

    taskkill /F /IM nginx.exe

To avoid launching multiple instances of Nginx, I created the following “intelligent” Nginx start and stop batch script files.

Create a file named “start_nginx.bat” with the content below:

@ECHO OFF

REM Start Nginx
tasklist /FI "IMAGENAME eq nginx.exe" 2>NUL | find /I /N "nginx.exe">NUL
IF NOT "%ERRORLEVEL%"=="0" (
   REM Nginx is NOT running, so start it
   c:
   cd \nginx
   start nginx.exe
   ECHO Nginx started.
) else (
   ECHO Nginx is already running.
)

And create a file named “stop_nginx.bat” with this content:

@ECHO OFF

REM Stop Nginx
tasklist /FI "IMAGENAME eq nginx.exe" 2>NUL | find /I /N "nginx.exe">NUL
IF "%ERRORLEVEL%"=="0" (
   REM Nginx is currently running, so quit it
   c:
   cd \nginx
   nginx.exe -s quit
   ECHO Nginx quit issued.
) else (
   ECHO Nginx is not currently running.
)

Install and Configure PHP

To install PHP on Windows:

  1. Browse to php.net, click on the “Windows downloads” link, and download the latest thread safe version. Either 32-bit or 64-bit versions will work.
  2. Unzip to a directory, like “c:\nginx\php”.
  3. Select a PHP configuration (I recommend the development version):
    copy c:\nginx\php\php.ini-development c:\nginx\php\php.ini

We will run the “c:\nginx\php\php-cgi.exe” server to allow Nginx to execute PHP scripts using the FastCGI protocol.

  1. Edit “c:\nginx\conf\nginx.conf” to uncomment the FastCGI section and update the fastcgi_param entries like so:
            # 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;
                fastcgi_param  REQUEST_METHOD $request_method;
                fastcgi_param  SCRIPT_FILENAME $document_root$fastcgi_script_name;
                include        fastcgi_params;
            }

    Notes:

    • Don’t forget to update the “root” location value if you are not using the default “c:\nginx\html” directory.
    • The fastcgi_param values are recommended extra parameters passed to PHP scripts for their optional use.
  2. Add the following to the bottom of the “start_nginx.bat” file:
    REM Start php-cgi
    tasklist /FI "IMAGENAME eq php-cgi.exe" 2>NUL | find /I /N "php-cgi.exe">NUL
    IF NOT "%ERRORLEVEL%"=="0" (
       REM php-cgi is NOT running, so start it
       start /min c:\nginx\php\php-cgi.exe -b localhost:9000 -c c:\nginx\php\php.ini
       ECHO php-cgi started.
    ) else (
       ECHO php-cgi is already running.
    )

    Notes:

    • Use localhost instead of 127.0.0.1 to support both IPv4 and IPv6 addressing (if it is enabled). 127.0.0.1 was not resolvable on my IPv6-enabled Windows installation. (Strangely, using 127.0.0.1 in the nginx.conf’s FastCGI section above is okay though.)
    • Unfortunately, “start php-cgi.exe” will show a separate “Command Prompt” window which will remain visible; the “/min” parameter flag is used to minimize that window. If you really want to prevent that window from appearing, you’ll need to use a VBScript to execute the batch file.
    • The order in which Nginx and php-cgi are launched does not matter.
    • The PHP distribution has a “php-win.exe” file which supposedly is the same as “php-cgi.exe” but without throwing up a “Command Prompt” window; however, I could not get “php-win.exe” to run as a server.
  3. Add the following to the bottom of the “stop_nginx.bat” file:
    REM Stop php-cgi
    tasklist /FI "IMAGENAME eq php-cgi.exe" 2>NUL | find /I /N "php-cgi.exe">NUL
    IF "%ERRORLEVEL%"=="0" (
       REM php-cgi is currently running, so quit it
       taskkill /f /IM php-cgi.exe
       ECHO php-cgi killed.
    ) else (
       ECHO php-cgi is not currently running.
    )
  4. Create a PHP test script at “c:\nginx\html\info.php”with the following content:
    <?php
    phpinfo();
    ?>
  5. Run “start_nginx.bat” to launch Nginx and php-cgi. Browse to http://localhost/info.php and you should see information about the PHP installation.

Install MySQL

Let’s get MySQL up and running:

  1. Download the latest MySQL Community Server. I suggest the “ZIP Archive” distributions, either the 32-bit or 64-bit version. Click the Download button. You don’t need to log in to download, just click the “No thanks, just start my download” link at the bottom of the page.
  2. Unzip to a directory like “c:\nginx\mysql”.
  3. Select the default MySQL configuration:
    copy c:\nginx\mysql\my-default.ini c:\nginx\mysql\my.ini
  4. Initialize MySQL by running the “Command Prompt” as an administrator (so Windows registry keys and service can be created) and these commands:
    # Current directory must be the MySQL installation directory
    cd c:\nginx\mysql

    # Initialize database with root user and blank password
    bin\mysqld --initialize-insecure

    # Install MySQL as a Windows service
    bin\mysqld --install-manual

    # Start MySQL Server service
    net start mysql
  5. Test by running these commands (administrator privileges not required):
    # Run MySQL client, skipping password input since blank
    c:\nginx\mysql\bin\mysql.exe -u root --skip-password

    # Run some commands and a query
    mysql> SHOW databases;
    mysql> USE mysql;
    mysql> SHOW tables;
    mysql> DESC user;
    mysql> SELECT * FROM user;

    # Assign new root password
    mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY 'new_password';

    # Quit MySQL client
    mysql> quit;

    # Run MySQL client with password prompt
    c:\nginx\mysql\bin\mysql.exe -u root -p
    # Input the new_password
  6. Enable PHP mysqli extension by uncommenting the line below in “c:\nginx\php\php.ini”:
    extension=php_mysqli.dll
  7. Create a test script named mysql.php with the following content:
    <?php
    // HTML response header
    header('Content-type: text/plain');

    // Database connection parameters
    $DB_HOST = 'localhost';
    $DB_PORT = 3306; // 3306 is default MySQL port
    $DB_USER = 'root';
    $DB_PASS = ''; // blank or new_password
    $DB_NAME = 'mysql'; // database instance name

    // Open connection (all args can be optional or NULL!)
    $mysqli = new mysqli($DB_HOST, $DB_USER, $DB_PASS, $DB_NAME, $DB_PORT);
    if ($mysqli->connect_error) {
      echo 'Connect Error (' . $mysqli->connect_errno . ') ' . $mysqli->connect_error . PHP_EOL;
    } else {
      // Query users
      if ($result = $mysqli->query('SELECT User FROM user')) {
        echo 'Database users are:' . PHP_EOL;
        for ($i = 0; $i < $result->num_rows; $i++) {
          $result->data_seek($i);
          $row = $result->fetch_assoc();
          echo $row['User'] . PHP_EOL;
        }
        $result->close();
      } else {
        echo 'Query failed' . PHP_EOL;
      }
    }

    // Close connection
    $mysqli->close();
    ?>
  8. Run “stop_nginx.bat” followed by “start_nginx.bat” to restart Nginx and php-cgi processes. Browse to http://localhost/mysql.php and you should see a listing of the MySQL database users.
  9. You can stop and/or uninstall the MySQL Server service by running “Command Prompt” as an administrator and issuing these commands:
    # Stop MySQL Server service
    net stop mysql

    # Uninstall MySQL Server service
    sc delete mysql

You don’t have to run MySQL Server as a Windows service. Instead, you can run MySQL Server from the “Command Prompt” (administrator privileges not required) like so:

# Start MySQL Server
c:\nginx\mysql\bin\mysqld.exe

# Stop MySQL Server
c:\nginx\mysql\bin\mysqladmin.exe -u root shutdown

Unfortunately, the “mysqld.exe” will take control of the “Command Prompt” window and the “start” command does not work in this case, so you will need to open a second “Command Prompt” window in order to issue the shutdown command.

Some info taken from:

12 Responses
  1. Galih Pribadi :

    Date: June 16, 2016 @ 7:37 am

    Thanks very much for your article.
    It’s work for me ^_^

  2. Sorcerer :

    Date: September 26, 2016 @ 11:57 am

    My OS is Win8.1 64bit. Followed your instructions, when I typed localhost in Chrome, the page returned “This site can’t be reached. localhost refused to connect”. I use AVG antivirus. I turn off AVG and tried to access localhost again. Same error message.

    Also, when I looked at the taskmanager, there were 2 nginx.exe (32 bit) windows processes when I issued “start nginx” command in the nginx folder. I deleted one of them and tried to access localhost page. Same error message.

    What should be done to correct this error and get localhost to display the “Welcome to nginx!” page?

    Thanks in advance.

  3. Chanh :

    Date: September 30, 2016 @ 1:13 am

    Hi,

    Sorry for the delayed reply. It looks like you are at step 6 “Browse to http://localhost/“. I just tried the latest nginx-1.11.4 build on my Windows 10 64-bit system and it worked as expected.

    I can think of three issues that could be causing the problem you are seeing. Could you try the following?

    1. Quit (or kill) all the nginx.exe processes and then run nginx.exe. Because you had two nginx processes, one of them got port 80 and the other failed to get port 80 (because it was already taken). Unfortunately, we don’t know which nginx process got port 80 successfully so to make sure, we have to quit all nginx processes to free up the port 80. The new nginx process should then successfully bind to port 80.
    2. Browse to “http://127.0.0.1/”. This is very unlikely but there might be an issue with resolving localhost to 127.0.0.1 on your system.
    3. Change from port 80 to port 8080. Quit all nginx.exe processes, edit “c:\nginx\config\nginx.conf”, replace the “listen 80” with “listen 8080”, save, and start nginx.exe. Browse to “http://localhost:8080/”. This issue could occur if another program has already taken possession of port 80, or your firewall is blocking access to the first 1024 ports.

    You can also check the log file at “c:\nginx\logs\error.log” to see if there are error messages that might indicate what the problem is.

    Hope that helps.
    Chanh

  4. Glenn :

    Date: December 20, 2016 @ 4:29 pm

    Chanh, followed your instructions; worked first time “out of the gate” (on Windows 10 x64.) Thank you!

  5. Jim :

    Date: December 25, 2016 @ 6:33 pm

    Thanks very much. Your explanation was concise and very useful. I just started using ngnix and this saved me a lot of time.

  6. Konstantinos :

    Date: December 28, 2016 @ 5:05 pm

    It cannot load any extension (module) because the path is incorrect. I had to edit php.ini and change to:

    extension_dir = "C:\nginx\php\ext"

    The tutorial was very helpful, thank you!

  7. Madhurjya Roy :

    Date: May 26, 2017 @ 11:23 pm

    Thank you. I wanted to use my existing MariaDB installation and all I had to do is skip parts of the “Install MySQL” section of your post.

    I was wondering if there would be any problems with using the installed version (and not the zip version), but everything worked like a charm. 🙂

  8. Jeff D. :

    Date: September 6, 2017 @ 9:17 pm

    Great tutorial, helped me a lot, thanks!

  9. Spa Motrew :

    Date: November 21, 2017 @ 5:36 pm

    Why work this hard when you can install a php development stack based on nginx?

    https://sourceforge.net/projects/wtnmp/

    WinNMP – Windows Nginx MySql Php stack

    A lightweight, fast and stable server stack for developing php mysql applications on windows, based on the excellent webserver Nginx. A lighter alternative to XAMPP and WAMP, with Composer, Adminer, LetsEncrypt certificates, WinSCP, multiple PHP versions, projects and virtual servers.

  10. Chanh :

    Date: December 4, 2017 @ 11:32 am

    Thanks for letting us know about WinNMP, Spa. It does look more lightweight than XAMPP/WAMP, though it includes MariaDB (a fork of MySQL, instead of MySQL) and numerous other utilities (Redis, WinSCP, etc.) which some may not need or want.

  11. Wolfgang B. :

    Date: December 4, 2017 @ 10:37 am

    Thank you very much for your helpful tutorial! It worked great for me with two minor changes:
    – I had to uncomment the line ‘extension_dir = “ext”‘ in php.ini
    – The test script mysql.php doesn’t work for the user ‘root’. I had to create a new user

  12. Chanh :

    Date: December 4, 2017 @ 11:26 am

    Thanks, Wolfgang, for letting us know. Looks like Konstantinos earlier had a related issue with the ‘extension_dir’ directive also.

Leave a Comment

Your comment

You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

Please note: Comment moderation is enabled and may delay your comment. There is no need to resubmit your comment.