Self-contained maintenance page

Sometimes we need to take our web apps offline temporarily. It could be to do a major upgrade or in an emergency situation. Anyways, you should at least set a static page to notify regular users that the site is currently unavailable. And it’s even better if you can maintain access for you and your fellow developers in the meantime.

Create a maintenance page

First step is to create a good maintenance page. Good means clean, simple, visually attractive and the most important thing: “self-contained” ! So any required resource should be embedded inside a “simple” HTML file.

How to do that ?

For CSS use the tag style to integrate the content into the HTML like this:

<style media="screen" type="text/css">
 ... Add CSS data here ...
</style>

For images encode them in base64 using the base64 command and add the resulting string into the HTML like this:

<img src="data:image/gif;base64,BASE64STRING" alt="my_image" />

You have a good maintenance page ? Perfect, now let talk how to serve it.

Serve the maintenance page

The first component that receive the users requests should be serving the page. Depending your stack that means either the:

  • HTTP server should serve the page
  • HTTP reverse-proxy cache (aka. Varnish) should serve the page

In the first case i highly suggest you to make a dedicated maintenance VirtualHost on a separate port.

In the second case you must modify your vcl_error section with something like this:

if (obj.status == 703) {
    set obj.status = 503;
    set obj.http.Content-Type = "text/html; charset=utf-8";
    synthetic {"
           ... Add HTML content here ...
    "};
    return(deliver);
}

Note the fake HTTP code 703. We will use it later 😉

Maintain access for you, display maintenance page for others

If your maintenance page is served by Varnish use an acl for IP filtering like this:

acl me_and_dev {
"1.2.3.4"/32;
}

sub vcl_recv {
    if (!client.ip ~ me_and_dev) {
            error 703 "Service unavailable";
    }
}

If your maintenance page is served by Apache use an iptable rule to redirect traffic to the maintenance VirtualHost‘s port except for your IP :

iptables -t NAT -A PREROUTING -i eth0 -p tcp --dport 80 \! -s '1.2.3.4' --to-ports 81

Note that if you can’t use IP filtering, other solution are possible like using a special maintenance cookie set after requesting a “secret url”.