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.

4 Answers 4

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.

1
  • 1
    A possible problem with returning 503 is that you don't know if the shutdown was for maintenance purposes, or there is an issue with the web application. Am I right? Commented Jul 18, 2021 at 12:04
38

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.

7
  • 2
    Yeah, that is the same code that is on the link in the question. I'm actually asking if it's safe to use ifs in this case since it should not be used according to documentation.
    – NeDark
    Commented Sep 13, 2011 at 19:43
  • 1
    And that same documentation: In some cases it's also possible to move ifs to server level (where it's safe as only other rewrite module directives are allowed within it). The maintenance error_page as Mike showed is normally set in server {} context.
    – Regan
    Commented Nov 13, 2013 at 13:18
  • 1
    I did the same except just did a 'return 503' without checking the existence of the file. That way I can just enable/disable the site (using Debian's "sites-available"/"sites-enabled" layout) by symlinking and turn on the maintenance page. Commented Jul 14, 2015 at 11:18
  • 7
    Sounds like this would be a performance hit: NGINX will need to check for the existance of a file for every request...
    – Marc
    Commented Sep 14, 2017 at 7:32
  • 3
    Marc, it isn't since commonly accessed files are stored in filesystem cache which is in memory.
    – Mike
    Commented Feb 19, 2018 at 3:00
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.

1
  • Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.
    – Community Bot
    Commented May 17, 2023 at 10:26
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

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .