Managing site maintenance with Varnish 3.x

Recently I had to push out a few updates to a site that required a few big interface changes that I didn't want the public to see while I was making them. The application is running under Apache and we're using Varnish 3.x as a reverse proxy.

I wanted to be able to have a white list of IPs that can access the site and be able to display a custom error page to the user letting them know that the site is undergoing maintenance. If I were only running Apache I could do it easily in the vhost for the site, but we're using Varnish so we need to stop the request once it hits the server. I could do it with iptables and block traffic to port 80 and 443, but I wanted to display a message to the end user letting them know that the site is under maintenance.

Varnish makes this really easy, all you have to do is define access control lists and populate it with the IP address of machines you want varnish to whitelist.

acl admins {
    '123.123.123.123'; # The IP address of my machine
    '127.0.0.1';
}

And inside of your sub vcl_recv function you would put a check in to make sure that the client.ip is not included in the admins acl.

if (!(client.ip ~ admins)) {
    error 503 'Service Unavailable';
}

Finally, we need to display a custom error message to the end user. Because we're using the 503 error code we can use the sub vcl_error directive to generate a page to return to the user.

sub vcl_error {
    if (obj.status == 503) {
        set obj.http.Content-Type = "text/html; charset=utf-8";
        synthetic {"
            <!DOCTYPE html>
            <html>
                <head>
                    <title>Site Maintenance</title>
                </head>
                <body>
                    <h1>We're doing some maintenance!</h1>
                    <p>This site will be back shortly, we're doing a bit of maintenance.</h1>
                </body>
            </html>
        "};
    }
    return (deliver);
}

So, there we go, we have our acl defined with our IPs that varnish will talk to, we have our check to make sure the client.ip is able to talk to varnish, and finally we have our error message. You can put anything in there and even load it from a file if needed.

Add new comment

Plain text

  • No HTML tags allowed.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.