{"id":217,"date":"2018-02-25T15:23:26","date_gmt":"2018-02-25T07:23:26","guid":{"rendered":"https:\/\/www.techcoil.com\/blog\/?p=217"},"modified":"2018-09-05T11:11:53","modified_gmt":"2018-09-05T03:11:53","slug":"configuring-nginx-for-php-web-applications","status":"publish","type":"post","link":"https:\/\/www.techcoil.com\/blog\/configuring-nginx-for-php-web-applications\/","title":{"rendered":"Configuring Nginx for PHP web applications"},"content":{"rendered":"<p><a href=\"http:\/\/nginx.org\/\" rel=\"noopener\" target=\"_blank\">Nginx<\/a> and <a href=\"http:\/\/php.net\/manual\/en\/book.fpm.php\" rel=\"noopener\" target=\"_blank\">PHP FastCGI Process Manager (FPM)<\/a> 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 <a href=\"https:\/\/www.techcoil.com\/blog\/the-reverse-proxy-server\/\" rel=\"noopener\" target=\"_blank\">reverse proxy server<\/a> for the PHP FastCGI Process Manager. <\/p>\n<p>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. <\/p>\n<p>This post discusses a set of configurations that you can use for configuring Nginx for your PHP web applications.<\/p>\n<h2>Nginx configurations for PHP web applications<\/h2>\n<p>Suppose you have:<\/p>\n<ul>\n<li>the domain names <code>example.com<\/code> and <code>www.example.com<\/code> that are mapped to the IP address of the server where your Nginx installation is running from,<\/li>\n<li>the directory <code>\/var\/www\/example.com<\/code> on your server that contains the PHP scripts and \/ or static files for your application, and<\/li>\n<li>the PHP FastCGI Process Manager running in the same machine as your Nginx installation and listening for requests via the unix socket <code>unix:\/run\/php\/php7.0-fpm.sock<\/code>.<\/li>\n<\/ul>\n<p>You can configure your Nginx web server for your PHP application with the following configurations:<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nserver {\r\n        listen   80;\r\n        server_name example.com www.example.com;\r\n        root \/var\/www\/example.com;\r\n       \r\n        index index.php;\r\n\r\n        location \/ {\r\n                try_files $uri $uri\/ \/index.php?$args;\r\n        }\r\n\r\n        location ~ \\.php$ {\r\n                #NOTE: You should have &quot;cgi.fix_pathinfo = 0;&quot; in php.ini\r\n                include fastcgi.conf;\r\n                fastcgi_pass unix:\/run\/php\/php7.0-fpm.sock;\r\n                fastcgi_buffers 16 16k;\r\n                fastcgi_buffer_size 32k;\r\n        }\r\n}\r\n<\/pre>\n<h3>What does the <code>server_name<\/code> and <code>listen<\/code> directives tell Nginx?<\/h3>\n<p>The <a href=\"http:\/\/nginx.org\/en\/docs\/http\/ngx_http_core_module.html#server_name\" rel=\"noopener\" target=\"_blank\"><code>server_name<\/code><\/a> directive along with the <a href=\"http:\/\/nginx.org\/en\/docs\/http\/ngx_http_core_module.html#listen\" rel=\"noopener\" target=\"_blank\"><code>listen<\/code><\/a> directive instructs Nginx to handle HTTP GET requests directed at either <code>http:\/\/example.com<\/code> or <code>http:\/\/www.example.com<\/code> to take the instructions specified by this <a href=\"http:\/\/nginx.org\/en\/docs\/http\/ngx_http_core_module.html#server\" rel=\"noopener\" target=\"_blank\"><code>server<\/code><\/a> block.<\/p>\n<h3>What does the <code>root<\/code> directive tells Nginx?<\/h3>\n<p>The <a href=\"http:\/\/nginx.org\/en\/docs\/http\/ngx_http_core_module.html#root\" rel=\"noopener\" target=\"_blank\">root<\/a> directive tells Nginx to look for files inside the <code>\/var\/www\/example.com<\/code> directory to serve incoming HTTP GET requests. With this configuration, Nginx will map requests made to:<\/p>\n<ul>\n<li><code>http:\/\/example.com\/images\/logo.png<\/code> into the file path <code>\/var\/www\/example.com\/images\/logo.png<\/code>.<\/li>\n<li><code>http:\/\/example.com\/contact.html<\/code> into the file path <code>\/var\/www\/example.com\/contact.html<\/code><\/li>\n<li><code>http:\/\/example.com\/about\/us.html<\/code> into the file path <code>\/var\/www\/example.com\/about\/us.html<\/code><\/li>\n<\/ul>\n<h3>What does the <code>index<\/code> directive tells Nginx?<\/h3>\n<p>The <a href=\"http:\/\/nginx.org\/en\/docs\/http\/ngx_http_index_module.html#index\" rel=\"noopener\" target=\"_blank\"><code>index<\/code><\/a> directive tells Nginx that whenever a HTTP GET request is made to a directory inside the directory specified by the <code>root<\/code> directive, it should attempt to redirect the request to <code>index.php<\/code> from that directory. For this configuration, Nginx will map requests made to <code>http:\/\/example.com\/<\/code> into <code>http:\/\/example.com\/index.php<\/code>. Since Nginx can only be sure that HTTP requests made to <code>http:\/\/example.com\/<\/code> is hitting the root directory, the <code>index<\/code> directive only takes effect for such HTTP requests.<\/p>\n<p>Nginx uses the configurations inside the <code>\"location \/\"<\/code> block to handle HTTP requests with urls like the following:<\/p>\n<ul>\n<li><code>http:\/\/example.com\/about<\/code><\/li>\n<li><code>http:\/\/example.com\/images<\/code><\/li>\n<li><code>http:\/\/example.com\/start-here<\/code><\/li>\n<li><code>http:\/\/example.com\/tools<\/code><\/li>\n<\/ul>\n<p>This is because these urls could refer to files within the server file system, hence the <code>index<\/code> directive is not applied for such cases.<\/p>\n<h3>What does the <code>\"location \/\"<\/code> block tells Nginx?<\/h3>\n<p>In this set of configurations, any HTTP request that have url that <strong>does not<\/strong> end with <code>.php<\/code> will be handled by Nginx according to the instruction in the <code>\"location \/\"<\/code> block. For example, Nginx will use the configuration in the  <code>\"location \/\"<\/code> block to handle HTTP requests with the following urls:<\/p>\n<ul>\n<li><code>http:\/\/example.com\/images\/logo.png<\/code><\/li>\n<li><code>http:\/\/example.com\/contact.html<\/code><\/li>\n<li><code>http:\/\/example.com\/about\/us.html<\/code><\/li>\n<\/ul>\n<p>Inside the <code>\"location \/\"<\/code> block, the <a href=\"http:\/\/nginx.org\/en\/docs\/ngx_core_module.html#include\"><code>try_files<\/code><\/a> directive tells Nginx to:<\/p>\n<ul>\n<li>Try mapping the incoming HTTP request to a file path on the server file system.<\/li>\n<li>Try mapping the incoming HTTP request to a directory path on the server, <strong>if the file path does not point to any file on the server<\/strong>.<\/li>\n<li>Make an indirect request to the <code>\/index.php<\/code> along any query string variables (captured by the <code>$args<\/code> Nginx variable), <strong>if the directory path does not point to any directory on the server<\/strong>. This will cause Nginx to handle the request with the instructions inside the <code>\"location ~ \\.php$\"<\/code> block.<\/li>\n<\/ul>\n<h3>What does the <code>\"location ~ \\.php$\"<\/code> block tells Nginx?<\/h3>\n<p>The execution of PHP scripts is made possible by the <code>\"location ~ \\.php$\"<\/code> block. The <code>\"location ~ \\.php$\"<\/code> block tells Nginx that whenever a HTTP request with a url ending with a <code>.php<\/code> extension, Nginx should handle the request with directives contained in this block.<\/p>\n<p>Inside the <code>\"location ~ \\.php$\"<\/code> block, the <code>include<\/code> directive tells Nginx to take the configurations defined inside the <a href=\"https:\/\/github.com\/nginx\/nginx\/blob\/master\/conf\/fastcgi.conf\" rel=\"noopener\" target=\"_blank\"><code>fastcgi.conf<\/code><\/a> file located at the Nginx installation root. <\/p>\n<p>The <code>fastcgi.conf<\/code> file describes the incoming HTTP request to the PHP FastCGI Process Manager via several <a href=\"http:\/\/nginx.org\/en\/docs\/http\/ngx_http_fastcgi_module.html#fastcgi_param\" rel=\"noopener\" target=\"_blank\"><code>fastcgi_param<\/code><\/a> directive statements.<\/p>\n<p>The <a href=\"http:\/\/nginx.org\/en\/docs\/http\/ngx_http_fastcgi_module.html#fastcgi_pass\"><code>fastcgi_pass<\/code><\/a> 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 <code>\/run\/php\/php7.0-fpm.sock<\/code> on the same machine. If the PHP FastCGI Process manager resides on another machine, you should replace <code>\/run\/php\/php7.0-fpm.sock<\/code> with an address (for eg. 192.168.1.105) and port number (for eg. 9000):<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nfastcgi_pass 192.168.1.105:9000;\r\n<\/pre>\n<p>Note that if your PHP FastCGI Process Manager is on a separate machine, the directory <code>\/var\/www\/example.com<\/code> <strong>must exist on the file system of machine<\/strong> as well. This is because the value from the <code>root<\/code> directive is passed over to the PHP FastCGI Process Manager via one of the <code>fastcgi_param<\/code> inside the <code>fastcgi.conf<\/code> file.<\/p>\n<p>The <a href=\"http:\/\/nginx.org\/en\/docs\/http\/ngx_http_fastcgi_module.html#fastcgi_buffers\" rel=\"noopener\" target=\"_blank\"><code>fastcgi_buffers<\/code><\/a> and <a href=\"http:\/\/nginx.org\/en\/docs\/http\/ngx_http_fastcgi_module.html#fastcgi_buffer_size\" rel=\"noopener\" target=\"_blank\"><code>fastcgi_buffer_size<\/code><\/a> configure the way responses from the PHP FastCGI Process Manager are buffered.<\/p>\n<h2>Intuitions to developing your PHP application with this set of Nginx configurations<\/h2>\n<p>With this set of Nginx configurations applied, HTTP requests with urls not ending with <code>.php<\/code> will be directed to the <code>\/var\/www\/example.com\/index.php<\/code> file. <\/p>\n<h3>Implementing request dispatcher logic from <code>\/var\/www\/example.com\/index.php<\/code><\/h3>\n<p>The PHP script <code>\/var\/www\/example.com\/index.php<\/code> is the starting point for implementing the request dispatcher based on the front controller pattern.<\/p>\n<h4>Getting the request uri with PHP<\/h4>\n<p>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 <code>\/var\/www\/example.com\/index.php<\/code> or any PHP scripts that are included afterwards, we can get the request uri from the <code>$_SERVER['REQUEST_URI']<\/code> variable.<\/p>\n<p>For example, the <code>$_SERVER['REQUEST_URI']<\/code> returns:<\/p>\n<ul>\n<li><strong>\/about<\/strong> for <code>http:\/\/example.com\/about<\/code><\/li>\n<li><strong>\/about\/me<\/strong> for <code>http:\/\/example.com\/about\/me<\/code><\/li>\n<li><strong>\/search?terms=abc<\/strong> for <code>http:\/\/example.com\/search?terms=abc<\/code><\/li>\n<li><strong>\/start-here<\/strong> for <code>http:\/\/example.com\/start-here<\/code><\/li>\n<\/ul>\n<p>Note that since query strings are included after the request uri, you may want to strip any query strings from <code>$_SERVER['REQUEST_URI']<\/code> before performing uri parsing:<\/p>\n<pre class=\"brush: php; title: ; notranslate\" title=\"\">\r\n$clean_uri = strtok($_SERVER&#x5B;&quot;REQUEST_URI&quot;], '?');\r\n<\/pre>\n<h4>Getting the HTTP method with PHP<\/h4>\n<p>The other variable to inspect for request dispatching is the HTTP method. You can get the HTTP method from <code>$_SERVER['REQUEST_METHOD']<\/code>.<\/p>\n<h4>Using a micro framework<\/h4>\n<p>Alternatively, instead of implementing the request dispatcher logic with <code>$_SERVER['REQUEST_URI']<\/code> and <code>$_SERVER['REQUEST_METHOD']<\/code>, you can use the <a href=\"https:\/\/www.slimframework.com\/\" rel=\"noopener\" target=\"_blank\">Slim micro framework<\/a> within <code>\/var\/www\/example.com\/index.php<\/code> to build up your PHP web application quickly.<\/p>\n<h3>Requesting for PHP scripts directly<\/h3>\n<p>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 <a href=\"https:\/\/wordpress.org\" rel=\"noopener\" target=\"_blank\">WordPress<\/a> is realised mostly by calls made to PHP scripts directly. For example, along with the HTTP GET method, the request uri:<\/p>\n<ul>\n<li><code>\/wp-admin\/edit.php<\/code> will result in WordPress returning the table of posts in your blog.<\/li>\n<li><code>\/wp-admin\/post-new.php<\/code> will result in WordPress presenting a form for you to add a new blog post.<\/li>\n<li><code>\/wp-admin\/upload.php<\/code> will result in WordPress presenting you with the Media Library interface for you to have a glimpse of the image,<br \/>\n audio and video files that you had uploaded to your blog; along with options to upload new ones, edit or delete existing ones.<\/li>\n<\/ul>\n\n      <ul id=\"social-sharing-buttons-list\">\n        <li class=\"facebook\">\n          <a href=\"https:\/\/www.facebook.com\/sharer\/sharer.php?u=https%3A%2F%2Fwp.me%2Fp245TQ-3v\" target=\"_blank\" role=\"button\" rel=\"nofollow\">\n            <img decoding=\"async\" src=\"\/ph\/img\/3rd-party\/social-icons\/Facebook.png\" alt=\"Facebook icon\"> Share\n          <\/a>\n        <\/li>\n        <li class=\"twitter\">\n          <a href=\"https:\/\/twitter.com\/intent\/tweet?text=&url=https%3A%2F%2Fwp.me%2Fp245TQ-3v&via=Techcoil_com\" target=\"_blank\" role=\"button\" rel=\"nofollow\">\n          <img decoding=\"async\" src=\"\/ph\/img\/3rd-party\/social-icons\/Twitter.png\" alt=\"Twitter icon\"> Tweet\n          <\/a>\n        <\/li>\n        <li class=\"linkedin\">\n          <a href=\"https:\/\/www.linkedin.com\/shareArticle?mini=1&title=&url=https%3A%2F%2Fwp.me%2Fp245TQ-3v&source=https:\/\/www.techcoil.com\" target=\"_blank\" role=\"button\" rel=\"nofollow\">\n          <img decoding=\"async\" src=\"\/ph\/img\/3rd-party\/social-icons\/linkedin.png\" alt=\"Linkedin icon\"> Share\n          <\/a>\n        <\/li>\n        <li class=\"pinterest\">\n          <a href=\"https:\/\/pinterest.com\/pin\/create\/button\/?url=https%3A%2F%2Fwww.techcoil.com%2Fblog%2Fwp-json%2Fwp%2Fv2%2Fposts%2F217&description=\" class=\"pin-it-button\" target=\"_blank\" role=\"button\" rel=\"nofollow\" count-layout=\"horizontal\">\n          <img decoding=\"async\" src=\"\/ph\/img\/3rd-party\/social-icons\/Pinterest.png\" alt=\"Pinterest icon\"> Save\n          <\/a>\n        <\/li>\n      <\/ul>\n    ","protected":false},"excerpt":{"rendered":"<p><a href=\"http:\/\/nginx.org\/\" rel=\"noopener\" target=\"_blank\">Nginx<\/a> and <a href=\"http:\/\/php.net\/manual\/en\/book.fpm.php\" rel=\"noopener\" target=\"_blank\">PHP FastCGI Process Manager (FPM)<\/a> 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 <a href=\"https:\/\/www.techcoil.com\/blog\/the-reverse-proxy-server\/\" rel=\"noopener\" target=\"_blank\">reverse proxy server<\/a> for the PHP FastCGI Process Manager. <\/p>\n<p>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. <\/p>\n<p>This post discusses a set of configurations that you can use for configuring Nginx for your PHP web applications.<\/p>\n","protected":false},"author":1,"featured_media":1240,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"advanced_seo_description":"","jetpack_seo_html_title":"","jetpack_seo_noindex":false,"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"footnotes":""},"categories":[4],"tags":[516,515,514,513,23,510,508,511,225,13,243,502,507,509,195,438,512,57],"jetpack_featured_media_url":"https:\/\/www.techcoil.com\/blog\/wp-content\/uploads\/Nginx-Logo.jpg","jetpack_shortlink":"https:\/\/wp.me\/p245TQ-3v","jetpack-related-posts":[],"jetpack_likes_enabled":true,"jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/www.techcoil.com\/blog\/wp-json\/wp\/v2\/posts\/217"}],"collection":[{"href":"https:\/\/www.techcoil.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.techcoil.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.techcoil.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.techcoil.com\/blog\/wp-json\/wp\/v2\/comments?post=217"}],"version-history":[{"count":0,"href":"https:\/\/www.techcoil.com\/blog\/wp-json\/wp\/v2\/posts\/217\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.techcoil.com\/blog\/wp-json\/wp\/v2\/media\/1240"}],"wp:attachment":[{"href":"https:\/\/www.techcoil.com\/blog\/wp-json\/wp\/v2\/media?parent=217"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.techcoil.com\/blog\/wp-json\/wp\/v2\/categories?post=217"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.techcoil.com\/blog\/wp-json\/wp\/v2\/tags?post=217"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}