32

I want to configure the server to show a maintenance page when it exist. I tried this code and works:

location / {
    try_files /maintenance.html $uri $uri/ @codeigniter;
}

But I noticed it would be served with a 200 status code, and it can cause confusion to search engines. I think the best practice would be returning a 503 status code. On google I find several relevant pages about it, like this. However, they use if to make the redirect and according to nginx documentation it isn't safe to use ifs.

Is there a way of doing it without using if? Is safe to use if in this case?

Thanks.

NeDark
  • 473

4 Answers4

40

Here is what I do.

            if (-f $document_root/maintenance.html) {
                    return 503;
            }
            error_page 503 @maintenance;
            location @maintenance {
                    rewrite ^(.*)$ /maintenance.html break;
            }

If the file is there it will show the maintenance page. Once you remove the file you will go back to normal.

Mike
  • 22,748
10

I think the best practice would be returning a 500 status code.

I think you mean 503 instead of 500.

they use if to make the redirect and according to nginx documentation it isn't safe to use ifs.

No. Only return is 100% safe inside if in location context.

According to nginx documentation, you can specify an HTTP status code as the last argument to try_files. I've tried this but it didn't work.

quanta
  • 52,423
3

This config works for me:

server {
  server_name _;
  listen 443 ssl http2;
  listen [::]:443 ssl http2;
  location ~* \.(css|png|js|jpg|jpeg|ico) {
      root /static/maintenance;
  }
  error_page 503 @maintenance;
  location @maintenance {
    root /static/maintenance;
    rewrite ^(.*)$ /index.html break;
  }
  location / {
    return 503;
  }
}

It returns /static/maintenance/index.html file with code 503 for every request.

It doesn't change URL with redirections.

Resources like

  • /static/maintenance/main.css,
  • /static/maintenance/favicon.ico,
  • etc.

are available with code 200.

vdshb
  • 211
2

If the maintenance page only has HTML

No asset file (CSS, JS, ...)

location = @maintenance {
    root html/;
    # `break`: use this `location` block
    rewrite ^ "/maintenance.html" break;
}

location / { error_page 503 @maintenance; return 503;

# ...

}

For maintenance page that has asset file (CSS / JS / ...)

The flow of this is:

  • If URI is /, return 503
    • Internal redirect to /maintenance.html
  • If URI found in maintenance directory (for asset), return file with status 200
  • All other request, redirect to /
# for handle maintenance web page
server {
    listen unix:/var/run/maintenance.nginx.sock;
# for Windows
# listen 8000;

location @index {
    # use redirect because if URI has sub-folder ($uri == /path/path/),
    # the relative path for asset file (CSS, JS, ...) will be incorrect
    rewrite ^ / redirect;
}

location = / {
    # maintenance page URI
    error_page 503 /maintenance.html;

    return 503;
}

# use RegExp because it has higher priority
location / {
    root html/maintenance/;

    # redirect all URI to index (503) page (except asset URI),
    # asset URI still return status 200
    try_files $uri @index;
}

}

original server block

server { listen 80; location / { proxy_pass http://unix:/var/run/maintenance.nginx.sock:;

    # for Windows
    # proxy_pass http://127.0.0.1:8000;
}

# ...

}

  • You can put the config in a maintenance.conf, include maintenance.conf when in maintenance.

  • I will not use if (-f <file>) because it will try to check if the file exist on every request

If you need bypass some IP address

More detail here

Ref: Nginx Maintenance