Setting a custom maintenance page on nginx

February 11, 2016

I know we are living in the era of zero-downtime deploy but given my website user base and the fact that it’s really simple and small, I thought an old school “maintenance page” would be enough for me at the moment.

My deployment process is executed by a single command, so it’s quite stable and fast.

For the sake of completeness, I would talk a bit about my deployment process.

I use Fabric, so I have a few micro tasks in a Python script. Tasks like config_nginxconfig_monit etc.

I also have other bigger tasks that call those micro tasks in sequence, my two main tasks are config and deploy. I almost never use the config task, let’s talk about what the deploy task do:

It’s really straight forward and simple to implement.

The maintenance mode

The following is a simplified version of my nginx configuration file:

server {
    listen 80;
    root /var/www/maintenance; [1]

    location / {
        if (-f $document_root/index.html) { [2]
            return 503;
        }
        # the rest of you configuration goes here
    }

    error_page 503 @maintenance; [3]
    location @maintenance { [4]
        rewrite ^(.*)$ /index.html break; [5]
    }
}

Let’s go to a basic definition of each point:

  1. Sets the root path for requests. I don’t use the root for any request, so I set it to a specific directory used for the maintenance mode;
  2. Check if there’s an index.html file in root directory. If the file exists I return the 503 Service Unavailable code;
  3. The error_page directive is used to specify the @maintenance location to be used to process the request;
  4. The @ prefix means this location is a named location, as such it’s not accessible by the client, being used only by other directives as error_page;
  5. Finally we simply serve the index.html document.

After altering the nginx configuration file for the website I created two other micro tasks in my Fabric script.

The first task simple copy the HTML document with an informative text about the maintenance process. This micro task is executed before every other task within the deploy task.

The other task is used to remove the index.html document, setting back the website to it’s normal state. This task is executed as the last process within that major deploy task.

Now everytime I execute my deploy task the website is put into a maintenance mode and automatically pulled out from it.

I’ve also added the Google Analytics tracking code in this maintenance page. This way if the number of requests during the maintenance process consistently grow, I’ll start to focus on a zero-downtime deployment process.

I hope this could help you!