0

During website maintenance, it is sometimes necessary to shutdown our website.

Our current method is to touch a file which will trigger the web server (nginx) to redirect traffic to a maintenance page hosted in Amazon S3. It is important to host the maintenance page on a external server because during maintenance there can be no guarantee about the availability of any local files.

This is the nginx config that we use for "Maintenance Mode":

server {
    ...

    # Redirect processing of 503 error pages into a named location:
    error_page 503 @maintenance;

    # "Maintenance Mode" is off by default - Use a nginx variable to track state.
    set $maintenance off;

    # Swith on "Maintenace Mode" if a certain file exists.
    if (-f /var/www/mysite/shared/maintenanceON) {
        set $maintenance on;
    }
    # Don't use "Maintenance Mode" for our own offices.
    if ($remote_addr ~ (69.69.96.69|69.69.69.79)) {
        set $maintenance off;
    }
    # Don't use "Maintenance Mode" for certain urls, e.g. the load-balancer ping page.
    if ($uri ~ ^/(site\/ping|robots\.txt)$) {
        set $maintenance off;
    }

    if ($maintenance = on) {
        return 503; # 503 - Service unavailable
    }

    location @maintenance {
        # Redirect the request to our maintenance page in Amazon S3.
        rewrite ^(.*)$ http://mysite.s3-website-us-east-1.amazonaws.com/ break;
    }

    ...

It works great. But there is an unfortunate side-effect I wondered whether is avoidable?

The rewrite is done by Nginx using a 302 http status code to forward the request to the Amazon S3 site. Therefore, during Maintenance mode, we are not returning a 503, we are returning a 302. This isn't good etiquette and could be bad if google bot crawled us during a planned site dowmtime period. Google recommends a 503 (source).

Is there a nginx directive I can use to get the same effect but without a 302 for the redirect?


This shows maintenance mode returns a "302 Moved Temporarily" rather than the "503 Service unavailable" that I'd prefer:

> wget http://staging.example.com
--2013-11-13 10:00:47--  http://staging.example.com/
Resolving staging.example.com (staging.example.com)... 69.69.69.80
Connecting to staging.example.com (staging.example.com)|69.69.69.80|:80... connected.
HTTP request sent, awaiting response... 302 Moved Temporarily
Location: http://example.s3-website-us-east-1.amazonaws.com/ [following]
--2013-11-13 10:00:53--  http://example.s3-website-us-east-1.amazonaws.com/
Resolving example.s3-website-us-east-1.amazonaws.com (example.s3-website-us-east-1.amazonaws.com)...
1

I don't believe you can pass a redirect using a 503 as it's not intended for redirection.

You'll either need to host that specific file in a safe location so it's unaffected by whatever maintenance system is in effect, or use a proxy_pass so that nginx fetches the page from amazon and then passes it on to the client.

Something along these lines might do the trick. Haven't touched nginx in a while, but this might give you an idea of what I'm suggesting:

    error_page 503 @maintenance;
    location @maintenance {
            rewrite ^(.*)$ /maintenance.html break;
            proxy_pass http://mysite.s3-website-us-east-1.amazonaws.com;
    }

Edit: On the page referenced about Google's recommendation for a 503, someone commented a fantastic idea for how to redirect with a 503. He mentioned it for Apache, but the concept is the same with nginx:

Hi!

This might help. On Apache Servers, it's usually not possible to redirect a user with any other HTTP Status Code than of the 3xx class.

Users that visit a site under maintenance deserve to get a useful information page.

Do this with a 302 redirect first that leads to a 503 page that outputs the 503 header (i.e. via PHP or Perl). This will work fine with Google since Google will assign all target page properties to the source page when they encounter a 302 - including the header response. I've tested this on Virtual Hosts and it works as desired. If you can, choose a time with few requests for the service actions.

Regards, Thomas

  • Following on from your response, I asked "How to change http response code on an object in Amazon S3" stackoverflow.com/questions/24182458 ;) – Tom Jun 12 '14 at 10:48
  • I can confirm the proxy_pass trick works (nginx v1.4.4). Thanks very much! – Tom Jun 12 '14 at 13:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.