Switch between branches using Nginx

For some of my projects, most of the time I use two branches: master and dev and I work mostly in dev. If I need to send the url to some clients with some dev/beta features I should create another (sub)domain like dev.myproject.com and sometimes, if I forget to change some configurations about the domain name (specially with some “very intelligent” CMSes that keeps the configuration in the database) I will get an email back saying “the new feature is not working” 🙂

In the end, I wanted to have an easy solution to switch between branches, keeping the same domain and to not confuse the clients or the QA with my beta/dev/test/acceptance subdomains. Everything should be on: http://myproject.com.

So, how I did it?
My project has the root folder in /var/www/project_dev/web for the dev branch and /var/www/project_master/web for the master branch.

In this case, I have the following nginx config file (/etc/nginx/sites-enabled/project)

upstream finalbranch {
map  $cookie_branch     $branch {
        default         finalbranch;
map $cookie_branch      $everything {
        dev   ;
server {
        index index.php; 
        location = / {
                proxy_pass              http://$branch;
        location / {
                proxy_pass              http://$everything;


In this config file I specify, if I have a cookie called “branch” to read it’s value. If the value is “dev” it will send the request further to the nginx running on port 8080, called dev. If the cookie doesn’t exists or it is “master” it will send the request to the nginx running on port 8888.

And I have also another two nginx config files: /etc/nginx/sites-enabled/dev and /etc/nginx/sites-enabled/master

In dev file I have:

server {
	# we want to listen on port 80 on all IPs on our system - both IPv4 and IPv6
	listen 8080;
        set $branch dev; 
	# where are our site files stored?
        root /var/www/project_${branch}/web;
        index index.php;
	access_log /var/log/nginx/project_${branch}_access.log;
	error_log /var/log/nginx/project_${branch}_error.log;
        # Deny all . files
        location ~ /\. {
                deny all;
        location / {
          try_files $uri =404;
          fastcgi_split_path_info ^(.+\.php)(/.+)$;
          # NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini
          # With php5-cgi alone:
          # With php5-fpm:
          #fastcgi_pass unix:/var/run/php5-fpm.sock;
          fastcgi_index index.php;
          include fastcgi_params;

And in master file I just changed:

set $branch dev;


set $branch master;

After I setup this nginx configuration, in my project I created a file, set.php through which I create the specific cookie. The PHP code is very simple. I just read the GET branch parameter and I setup a cookie.

The file set.php should be in /var/www/project_dev/web as well in /var/www/project_master/web.

$branch = 'master';
if (isset($_GET['branch']))
  $branch = $_GET['branch'];
echo $branch;
# you have 1 hour to check
setcookie("branch", $branch, time() + 3600);
header('Location: index.php');


Now, I can just do: http://myproject.com/set.php?branch=dev and I will see the dev branch and if I want to switch back on master, I just have to go to http://myproject.com/set.php?branch=master

In the future I hope to write another blog post in which to present a more elegant solution, without 3 nginx config files and a PHP script to set up cookies.

All the code can be found on Github.

If you found useful this blog post, please click some of the share buttons below. Thanks! 🙂

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.