четверг, 19 января 2012 г.

Maintenance page для сайтов, которые обслуживаются Nginx

Вчера потребовалось отключить пару сайтов, которые обслуживаются Nginx. В загашнике у меня есть папка maintenance, которую я кладу на место исходников, когда нужно быстро отключить сайт.

<html>
<head>
<title>Server Maintenance</title>
</head>
<body>
<center>
<h1>Server maintenance</h1>
Our apologies for the temporary inconvenience. The page is temporarily unavailable as server is down for scheduled maintenance. We will be back soon.
</center>
</body>
</html>
/var/www/maintenance/maintenance.html

<IfModule mod_rewrite.c>
    RewriteEngine on

    RewriteCond %{REQUEST_URI} !^/maintenance.html$
    RewriteRule .* /maintenance.html [R=302,L]
</IfModule>
/var/www/maintenance/.htaccess


Это позволяет отключать сайты вот так:
$ mv /path/to/siteroot /path/to/siteroot~disabled && \
cp -a /path/to/maintenance /path/to/siteroot

Этот способ хорош для apache, который обрабатывает .htaccess. Для Nginx поступил иначе:
  • Поместил директорию maintenance в /var/www
  • Создал конфиг /etc/nginx/maintenance-page
    location / {
        return 503;
    }
    
    error_page 503 /maintenance.html;
    
    location /maintenance.html {
        internal;
        root /var/www/maintenance;
    }
    /etc/nginx/maintenance-page

  • Теперь чтобы отключить сайт /etc/nginx/sites-enabled/example.com (symlink на /etc/nginx/sites-available/example.com), нужно:
    # rm -f /etc/nginx/sites-enabled/example.com
    # cat > /etc/nginx/sites-available/example.com~maintenance <<EOF
    server {
        listen 80;
        server_name example.com;
        include /etc/nginx/maintenance-page;
    }
    EOF
    
    # ln -s /etc/nginx/sites-{available,enabled}/example.com~maintenance
  • Остается перечитать конфиг в Nginx
    nginx -t && nginx -s reload

UPDATE: В комментариях подсказали более простой (и скорее всего более быстрый) способ для maintenance страницы. Поправил код в посте. Директива internal в секции location не даст напрямую обращаться к /maintenance.html.

4 комментария:

  1. Странно, что оно вообще у вас работает, а не входит в бесконечный цикл редиректов.

    Правильно:

    location / {
    return 503;
    }

    error_page 503 /maintenance.html;

    location /maintenance.html {
    internal;
    root /var/www/maintenance;
    }

    http://mailman.nginx.org/pipermail/nginx/2011-November/thread.html#30164
    http://mailman.nginx.org/pipermail/nginx/2011-November/030164.html

    ОтветитьУдалить
    Ответы
    1. А почему оно должно входить в цикл? Ведь идет отдача страницы, которая привязана к 503 ошибке. Смены Location: нет.

      Удалить
    2. Да, не будет, это я break с last перепутал.

      Тем не менее, rewrite тут не нужен совсем (как я показал выше), не говоря уж о том, что "^(.*)$" - это просто трата ресурсов. Если хочется именно rewrite, то:
      rewrite ^ /maintenance.html break;

      Удалить
    3. Попробовал ваш первый вариант - он наверняка будет быстрее моего реврайта.

      Удалить