Nginx & php-fpm

Here’s a down and dirty setup for those running WordPress/Drupal and want to leverage Nginx and php-fpm, php’s built in process manager. Note we can finally get away from that annoying htaccess file (I personally hate ’em, of course others love ’em with the granularity it offers for serving many vhosts/customers, etc).

1) Let’s start with our default server block and our catch all location for root, /:

  server {
     listen       80 default_server;
     server_name _;
     autoindex off;
     access_log  logs/access.80.log  main;

     location / {
            root   html;
            index index.php;
    	    try_files $uri $uri/ /index.php?$args;
     }
  }

Notice we’re using the try_files config which will use the first resource feasible. In the majority of cases, this should default to the last arg, /index.php?$args. For WordPress/Drupal setups, Nginx will attempt to load the index.php while passing all associated arguments a client requested behind the scene – this isn’t a redirect back to the client!

**HINT** – For those looking to simply serve php files without routing all requests through an index.php, simply remove the last /index.php?$args from the try_files line.

2) Now, lets configure a location block to handle proper *.php processing. This is where php-fpm comes into play:

 location ~ \.php$ {
      try_files $uri =404;  # if the intended php script isn't available, a 404 will be returned.
      fastcgi_split_path_info ^(.+\.php)(/.+)$;  
      include fastcgi_params;  ## will pass each param below to each request
      fastcgi_index index.php;  ## needed for proper wordpress / drupal routing
      fastcgi_param SCRIPT_FILENAME $document_root/$fastcgi_script_name;  # note we're using document_root here, only use for default vhost
      fastcgi_pass 127.0.0.1:9000;  # listening destination of php-fpm
 }

I’ve added comments for a bit of clarity. Note, there are plenty of additional configurations you can pass back to php-fpm, this is just the bare minimum to get up and running. Special note, if you run numerous vhosts within your nginx setup, make sure you pass replace $document_root within the fastcgi_param SCRIPT_FILENAME setting based on your specific vhost. If you don’t, php-fpm will leverage the default root.

3) Here’s the full example:

    server {
        listen       80 default_server;
	server_name _;
	autoindex off;
        access_log  logs/access.80.log  main;
        location / {
            root   html;
            index index.php;
    	    try_files $uri $uri/ /index.php?$args;
        }

	location ~ \.php$ {
                try_files $uri =404;
                fastcgi_split_path_info ^(.+\.php)(/.+)$;
                include fastcgi_params;
                fastcgi_index index.php;
                fastcgi_param SCRIPT_FILENAME $document_root/$fastcgi_script_name;
                fastcgi_pass 127.0.0.1:9000;
        }
    }

4) Here’s a vhost example, showing the document_root replaced on subsequent vhosts:

    server {
        listen       80 default_server;
	server_name _;
	autoindex off;
        access_log  logs/access.80.log  main;
        location / {
            root   html;
            index index.php;
    	    try_files $uri $uri/ /index.php?$args;
    	    #content_by_lua_file conf/cache.lua ;
        }

	location ~ \.php$ {
                try_files $uri =404;
                fastcgi_split_path_info ^(.+\.php)(/.+)$;
                include fastcgi_params;
                fastcgi_index index.php;
                fastcgi_param SCRIPT_FILENAME $document_root/$fastcgi_script_name;
                fastcgi_pass 127.0.0.1:9000;
        }

        error_page   400 401 402 403 404 500 502 503 504  /index.html;
        location = /50x.html {
            root   html;
        }

        location ~* \.(?:ico|css|js|gif|jpe?g|png)$ {
                expires max;
                add_header Pragma public;
                add_header Cache-Control "public";
        }
    }
#
# site vhost2
#
server {
        listen 80;
        server_name vhost2.example.com;
        autoindex off;
        access_log logs/access.vhost2.log main;

        error_page 400 401 402 403 404 500 501 502 503 /index.html;

	location / {
            root   vhost2;
            try_files $uri $uri/ /index.php?$args;
        }

        location ~ \.php$ {
                try_files $uri =404;
                fastcgi_split_path_info ^(.+\.php)(/.+)$;
                include fastcgi_params;
                fastcgi_index index.php;
                fastcgi_param SCRIPT_FILENAME /usr/local/nginx/vhost2/$fastcgi_script_name;  ## notice the prefixed doc_root is that of vhost2!!!
                fastcgi_pass 127.0.0.1:9000;
        }

        error_page   400 401 402 403 404 500 502 503 504  /index.html;
        location = /50x.html {
            root   vhost2;
        }

        location ~* \.(?:ico|css|js|gif|jpe?g|png)$ {
		root vhost2;
                expires 1d;
                add_header Pragma public;
                add_header Cache-Control "public";
        }
    }