I love Nginx as a webserver, it’s quick and easy to configure (if you know what you are doing). As a web developer (or should I say programmer), I like to make things as easy as possible in my development environment. As  my projects have increased over time I have noticed my Nginx config growing to accommodate each project.

My project directory looks something like:

  • root
    • project-1
      • public
        • index.php
    • project-2
      • public_html
        • index.php
    • project-3
      • public
        • index.php

And this goes on for a lots more projects using the same directory structure.

Now my Nginx conf file for this looks like , as all my projects use MVC all requests are routed through ‘index.php’

As you can see each site under root gets its own location block as if I didn’t do this this then then a url like ‘http://localhost/site-1/public/blog/list’ would result in a rude default Nginx 404 ‘file not found’ page instead of my sites blog list! You can see problems with this approach

  1. Each new site I have to add a new location block and restart the server
  2. Each time I delete a project I have to delete the location block and restart the server

Well I didn’t want to keep adding/deleting sites from the config file. So what could I do? Looking over the location blocks and directory structure I saw a pattern and wondered if I could abstract all sites into one location block. This is what I came up with using regex for the location parameter.

First I put my php-fpm config in an include file in /etc/nginx

Then I rewrote my site config file in ‘/etc/nginx/sites-enabled/projects.conf’

Restart the server and now all my projects work that use this directory structure. Breaking down the new location block at lines 16-25

line 16 is the regex pattern ~ /(.*)/(public_html|public)  This pattern has two groups, the first group matches any character after ‘/’ which will match ‘/site-1′, /’site-2/sub-site’ etc. The next group matches the directory ‘public’ or ‘public_html’ after the next ‘/’ so will match ‘/site-1/public’, ‘/site-2/public_html’ etc.

line 18 is the try_file directive which will check if the file or directory exists id so will server them if none of these is found it will server the ‘index.php’ defined by the regex groups as an example: ‘/<first group>/<second group>/index.php’.

I can now add and delete project site without touching the nginx config or restarting the server! 🙂

Multiple PHP Config

Wait on a minute, after this I started wondering if I could run different PHP versions just by altering the URL to a prefix like ‘/php/7.0′, /php/7/1’ or ‘/php/7.2’. So with my new found knowledge of regex I set too.

Now my PHP versions are in separate directories:


Yet another pattern we can use with regex so I come up with additional location block look like

Here I am using a new pattern to check if the URI starts with ‘/php/’ then check the first group ‘(7.0|7.1|7.2)’ this group matches which version I want then second and third group is the same as above but is optional and in the try_files directive I alter the directory structure to the matched pattern.

In the sub location block I again use regex to capture the PHP version number I want to run and use the matched pattern to the fastcgi_pass directive.

I restarted the server and tested my new block and YES! it worked now when I use the PHP prefixes in my URI I run that PHP version as you can see from the screen capture blow

So Now my Nginx confix file looks like

A lot shorter and zero maintenance plus the ability to see all my sites in different PHP versions all at once just by changing the URL 🙂 Super!

Hope this helps and I would love to hear your comments on this and any improvements or different applications of this I would love to hear too.

See ya soon and happy coding!