LocalHost using Nginx PHP MySQL

GeekThis remains completely ad-free with zero trackers for your convenience and privacy. If you would like to support the site, please consider giving a small contribution at Buy Me a Coffee.

Building websites that are dynamic require tools and software including but not limited to a Web Server, PHP, MySQL, and all other libraries and tools you may require.

You can of course set this all up using a program such as XAMPP inside of Windows, but doing it manually gives you more control of the settings and lets you move to production easier.

To setup a “localhost” server you need to download the following software.

Nginx Web Server

This is the server software that handles web requests. At the time of this tutorial I downloaded the 1.3.12 Development Build for Windows (zip file) from http://nginx.org


PHP is a “compiler” of sorts. It processes PHP files so you can have a dynamic website built using PHP. If you are not going to use PHP, this tutorial won’t benefit you that much. At the time of this tutorial I downloaded PHP Version 5.4.11 VC9 x86 Thread Safe ZIP file from http://php.net


MySQL is a database that works well with PHP. It allows you to store information for users and other content for the site. At the time of this tutorial I downloaded MySQL 5.6.10 64bit ZIP File from http://www.mysql.com

Once you have all of the files downloaded, you need to extract the files into a folder. I have all my websites and projects on a separate drive Z: and I put them in Z:\Zerver.

A sample of what the directory looks like is below.


Now there are a few settings we need to modify to get PHP working with Nginx, and to also get Nginx pointing to the correct locations.

Open up the Nginx Root (in this case nginx-1.3.12) and navigate into the folder “conf” and open the file nginx.conf

In this file, you can setup all your sites, locations, settings, etc. Below is my nginx.conf file.

DO NOT COPY AND PASTE - For Development Servers Only

Look through my setting of nginx.conf, and set your settings to fit your site.

worker_processes  1;
error_log  logs/error.log;
events {
	worker_connections	1024;

http {
	include	mime.types;
	default_type	application/octet-stream;
	access_log	logs/access.log;
	sendfile	on;
	keepalive_timeout	65;
	server {
		listen	80;
		server_name	localhost;
		root	z:/;
		location / {
			index index.php index.html index.htm;
			autoindex on;
		location ~ \.php$ {
			fastcgi_index index.php;
			fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
			include fastcgi_params;
			try_files $uri =404;


Logs all HTTP errors, such as HTTP Status Codes (403, 404, 500, 501, 503, etc). Also logs if nginx runs into an issue opening a file due to permissions or other issues.

http { }

The http block is the main block to hold all your settings for sites. If a setting is in a http block, it will apply to all websites hosted. This is good for setting up timeouts and other settings if they are the same for all sites. Settings can be overwritten in other blocks though.

Server { }

The server block is used for individual servers or sites. You can have multiple server blocks for subdomains, main domains, and more. Each will be allowed different settings to fit that site’s needs.


Listen is the port the server will listen on. Most websites have this set to 80 (default port), but if you are using a server block for a program to access, you can change the port as long as your program has that port set. Also listen may also be 443 for SSL or HTTPS.


Server_name is used to set the name of the server. This allows you to have multiple server blocks listening on the same port, but directing to different folders and websites. In this case “localhost” is used so I can navigate to “localhost” to view my website.


Root is the document root for that server block. I set it to the Z: drive because all my sites and projects are located there, so I can access all my projects for a web browser to test them.

Location { }

Location blocks sets special requirements and rules for specific files. The location block for “/” is for the root of the server {} root, in this case “Z:/"”, and it will follow to all sub directories also.


Sets the index files, so they will be opened by default. If the index file doesn’t exist, either a 403 will be issued, or you will see an “autoindex” tree.


Autoindex allows for all files to be seen. This is great for development purposes because you can easily navigate around files without having to remember all the paths. For production servers it is recommended you keep this off.


Fast CGI Pass sends PHP requests (or other files if configured incorrectly) to the PHP “server” you have running. By default the port is 9000. If required you can have multiple PHP “servers” running so each site has a different configuration for PHP.


Fastcgi_index is similar to the normal “index” parameter. It shows which file should be processed as the index of the website or directory.


This setting sets different parameters for your site to be used by fastcgi. In the above configuration I used it to modify the SCRIPT_FILE to allow PHP to get the correct full directory.


This setting is very important for PHP to hide passwords and other important information. If the file doesn’t exist (illustrated by the $uri variable) it will then return a 404 page. You can also have it redirect to a different page, but the last option should always be a HTTP status code just in case the previous files don’t exist.

Now that we have Nginx setup, you may want to change PHP settings. By default the settings are usually fine for a development server. If you would like to change the settings you will have to navigate to the PHP root, and create or open the php.ini file. PHP should come with various configuration files that you can pick from and modify.

One thing that we do have to change to get MySQL running is to enable the MySQL Extension.

Find the extension_dir setting, and set it to point to your extensions folder. In my case I set it to “ext” inside of php.ini.

extension_dir = "ext"

Next you need to uncomment or add the extension.


I also suggest enabling PDO MySQL for extra security if you plan on using PDO.


You can also enable various other extensions but at this time I do not require any of them. Some suggestions of ones that some CMS’s use are “php_curl.dll”, “php_fileinfo.dll”, “php_bz2.dll” and “php_gd2.dll”.

The last part of this tutorial is to get MySQL running, and this is by far the easiest. You have to run the exe and that’s all. MySQL comes setup with default settings that work right away with the PHP library we enabled.

MySQL Information

Username: root
Password: [empty / blank / none]
Port: 3306
Host: localhost or

To get your server running now since everything is configured, you have to start all the services. To make it easy I created a batch file that you can save as “start.bat” in your folder that you placed your PHP, Nginx and MySQL folders.

You can also start the services by running them manually through CMD. Nginx is odd about running from a different root directory, so when starting nginx from CMD, make sure your current working directory is that of nginx.

When running PHP, make sure you run the php-cgi.exe to work with the nginx settings. The other PHP executable files are for apache and IIS which we are not running.

Below is a batch script that should start up all your services.

   REM --- Start Loading Nginx
   CD "nginx-1.3.12"
   START "NGINX" /B "nginx.exe"
   REM -- Start Loading MYSQL
   CD "../mysql-5.6.10-winx64/bin"
   START "MYSQL" /B "mysqld.exe" --explicit_defaults_for_timestamp
   REM -- Start Loading PHP
   CD "../../php-5.4.11-Win32-VC9-x86"
   START "PHP" /B "php-cgi.exe" -b
   REM -- Kill All
   CD "../"
   echo Press Enter to Kill Server
   PAUSE > nul
   echo Killing Server
    REM -- Kill Nginx
   CD "nginx-1.3.12"
   nginx.exe -s quit
   REM -- Kill MySQL
   cd "../mysql-5.6.10-winx64/bin"
   mysqladmin.exe -u root shutdown
   REM -- Kill PHP

Related Posts

Automatically Start Docker Container

Automatically start Docker containers when your server or computer boots using restart policies and avoiding systemd service files.

How to Train SpamAssassin

Learn about the different methods used to train SpamAssassin, along with initial spam data sources to use with SpamAssassin. Update your bayes database easily with existing data.

SpamAssassin SA-Update Tool

Learn what SpamAssassin's sa-update tool does, how it works, and if you should keep it running and modifying the configuration files on your server.

Incremental MySQL Backup with Binary Log

Learn how to properly perform an incremental MySQL backup using binary logs without having a gap between backups and overall improve the speed of database backups.