Configuring Nginx for PHP web applications
Nginx and PHP FastCGI Process Manager (FPM) are often used side by side for PHP applications. In such a setting, Nginx will be the first point of contact for incoming HTTP requests, acting as a reverse proxy server for the PHP FastCGI Process Manager.
The PHP FastCGI Process Manager then interprets the HTTP requests that it receives from Nginx and runs the PHP scripts for generating the corresponding HTTP responses for Nginx to return back to the HTTP client.
This post discusses a set of configurations that you can use for configuring Nginx for your PHP web applications.
Nginx configurations for PHP web applications
Suppose you have:
- the domain names
example.com
andwww.example.com
that are mapped to the IP address of the server where your Nginx installation is running from, - the directory
/var/www/example.com
on your server that contains the PHP scripts and / or static files for your application, and - the PHP FastCGI Process Manager running in the same machine as your Nginx installation and listening for requests via the unix socket
unix:/run/php/php7.0-fpm.sock
.
You can configure your Nginx web server for your PHP application with the following configurations:
server { listen 80; server_name example.com www.example.com; root /var/www/example.com; index index.php; location / { try_files $uri $uri/ /index.php?$args; } location ~ \.php$ { #NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini include fastcgi.conf; fastcgi_pass unix:/run/php/php7.0-fpm.sock; fastcgi_buffers 16 16k; fastcgi_buffer_size 32k; } }
What does the server_name
and listen
directives tell Nginx?
The server_name
directive along with the listen
directive instructs Nginx to handle HTTP GET requests directed at either http://example.com
or http://www.example.com
to take the instructions specified by this server
block.
What does the root
directive tells Nginx?
The root directive tells Nginx to look for files inside the /var/www/example.com
directory to serve incoming HTTP GET requests. With this configuration, Nginx will map requests made to:
http://example.com/images/logo.png
into the file path/var/www/example.com/images/logo.png
.http://example.com/contact.html
into the file path/var/www/example.com/contact.html
http://example.com/about/us.html
into the file path/var/www/example.com/about/us.html
What does the index
directive tells Nginx?
The index
directive tells Nginx that whenever a HTTP GET request is made to a directory inside the directory specified by the root
directive, it should attempt to redirect the request to index.php
from that directory. For this configuration, Nginx will map requests made to http://example.com/
into http://example.com/index.php
. Since Nginx can only be sure that HTTP requests made to http://example.com/
is hitting the root directory, the index
directive only takes effect for such HTTP requests.
Nginx uses the configurations inside the "location /"
block to handle HTTP requests with urls like the following:
http://example.com/about
http://example.com/images
http://example.com/start-here
http://example.com/tools
This is because these urls could refer to files within the server file system, hence the index
directive is not applied for such cases.
What does the "location /"
block tells Nginx?
In this set of configurations, any HTTP request that have url that does not end with .php
will be handled by Nginx according to the instruction in the "location /"
block. For example, Nginx will use the configuration in the "location /"
block to handle HTTP requests with the following urls:
http://example.com/images/logo.png
http://example.com/contact.html
http://example.com/about/us.html
Inside the "location /"
block, the try_files
directive tells Nginx to:
- Try mapping the incoming HTTP request to a file path on the server file system.
- Try mapping the incoming HTTP request to a directory path on the server, if the file path does not point to any file on the server.
- Make an indirect request to the
/index.php
along any query string variables (captured by the$args
Nginx variable), if the directory path does not point to any directory on the server. This will cause Nginx to handle the request with the instructions inside the"location ~ \.php$"
block.
What does the "location ~ \.php$"
block tells Nginx?
The execution of PHP scripts is made possible by the "location ~ \.php$"
block. The "location ~ \.php$"
block tells Nginx that whenever a HTTP request with a url ending with a .php
extension, Nginx should handle the request with directives contained in this block.
Inside the "location ~ \.php$"
block, the include
directive tells Nginx to take the configurations defined inside the fastcgi.conf
file located at the Nginx installation root.
The fastcgi.conf
file describes the incoming HTTP request to the PHP FastCGI Process Manager via several fastcgi_param
directive statements.
The fastcgi_pass
directive shows Nginx the channel to communicate with the PHP FastCGI Process Manager. In this case, Nginx will communicate with PHP FastCGI Process Manager via the unix socket located at /run/php/php7.0-fpm.sock
on the same machine. If the PHP FastCGI Process manager resides on another machine, you should replace /run/php/php7.0-fpm.sock
with an address (for eg. 192.168.1.105) and port number (for eg. 9000):
fastcgi_pass 192.168.1.105:9000;
Note that if your PHP FastCGI Process Manager is on a separate machine, the directory /var/www/example.com
must exist on the file system of machine as well. This is because the value from the root
directive is passed over to the PHP FastCGI Process Manager via one of the fastcgi_param
inside the fastcgi.conf
file.
The fastcgi_buffers
and fastcgi_buffer_size
configure the way responses from the PHP FastCGI Process Manager are buffered.
Intuitions to developing your PHP application with this set of Nginx configurations
With this set of Nginx configurations applied, HTTP requests with urls not ending with .php
will be directed to the /var/www/example.com/index.php
file.
Implementing request dispatcher logic from /var/www/example.com/index.php
The PHP script /var/www/example.com/index.php
is the starting point for implementing the request dispatcher based on the front controller pattern.
Getting the request uri with PHP
Since the HTTP request uri is passed over to PHP FastCGI Process Manager, we can use the request uri as one of the decision points in the generation of HTTP responses. Inside /var/www/example.com/index.php
or any PHP scripts that are included afterwards, we can get the request uri from the $_SERVER['REQUEST_URI']
variable.
For example, the $_SERVER['REQUEST_URI']
returns:
- /about for
http://example.com/about
- /about/me for
http://example.com/about/me
- /search?terms=abc for
http://example.com/search?terms=abc
- /start-here for
http://example.com/start-here
Note that since query strings are included after the request uri, you may want to strip any query strings from $_SERVER['REQUEST_URI']
before performing uri parsing:
$clean_uri = strtok($_SERVER["REQUEST_URI"], '?');
Getting the HTTP method with PHP
The other variable to inspect for request dispatching is the HTTP method. You can get the HTTP method from $_SERVER['REQUEST_METHOD']
.
Using a micro framework
Alternatively, instead of implementing the request dispatcher logic with $_SERVER['REQUEST_URI']
and $_SERVER['REQUEST_METHOD']
, you can use the Slim micro framework within /var/www/example.com/index.php
to build up your PHP web application quickly.
Requesting for PHP scripts directly
Another way of creating your PHP application is to craft the HTTP request to run PHP scripts directly. This way of development is usually used for building the admin portal of your web application. For example, the Dashboard in WordPress is realised mostly by calls made to PHP scripts directly. For example, along with the HTTP GET method, the request uri:
/wp-admin/edit.php
will result in WordPress returning the table of posts in your blog./wp-admin/post-new.php
will result in WordPress presenting a form for you to add a new blog post./wp-admin/upload.php
will result in WordPress presenting you with the Media Library interface for you to have a glimpse of the image,
audio and video files that you had uploaded to your blog; along with options to upload new ones, edit or delete existing ones.