nginxで特定ホスト以外からのアクセスをメンテナンス画面にする方法 (2)

d:id:sfujiwara:20100812:1281587030 の revise。

Nginxのifは条件節に&&(and)が使えない、ifのネストもできないので、複数の条件で判別したい場合は変数を使うといいよって感じです。

server {

  ...

  #error_page   500 502 503 504  /static/50x.html;
  ### maintenance
  error_page   500 502 504  /static/50x.html;
  set $go_maintenance "true";

  if ($uri ~ "^/error/") {
    set $go_maintenance "false";
  }
  if ($remote_addr ~ "^192\.0\.2\.") {
    set $go_maintenance "false";
  }
  if ($remote_addr ~ "^10\.0\.0\.") {
    set $go_maintenance "false";
  }
  if ($http_user_agent ~ "nakanohito-desu") {
    set $go_maintenance "false";
  }
  if ($http_x_open = "sesame!") {
    set $go_maintenance "false";
  }

  error_page 503 /error/503.html;
  location /error/ {}
  if ($go_maintenance = "true") { return 503; } # maintenance
  ### /maintenance

  location /static {
    alias  /usr/irori/contents/example.com/static;
    expires 1h;
    gzip on;
    gzip_types text/css application/javascript application/x-javascript;

    keepalive_timeout 3 3;
  }

  location / {
    proxy_pass  http://127.0.0.1:2006;
    ...
  }

  location ... {
    ...
  }

}
  • ミソは「### maintenance」から「### /maintenance」まで。
  • カスタムのメンテページを出したい && 既存の設定(error_page)で503の制御をしている場合はコメントアウトして503だけはカスタムのメンテページを表示するようにする。
  • カスタムメンテページは /error/ 下に配置する。メンテページで画像とか使う場合もこのディレクトリ配下に置く。
  • 既存設定のlocationに食われないように、location /error/ {}と設定しておく。
  • 503にするかどうかは変数$go_maintenanceで判断する。初期値は"true"。(メンテ前は"false"にしておけばよろし)
  • カスタムメンテページは503になっちゃまずいので、^/error/ は "false"
  • ほか、メンテ中に中の人が動作確認したい条件をひっかけて "false" にする
    • $remote_addr でアクセス元のIPアドレスとか
      • $remote_addrをたくさん羅列したい場合は、HttpGeoModuleを使った方が効率的。
    • $http_user_agent でUser-Agentヘッダとか
    • $http_x_open とかでカスタムのHTTPリクエストヘッダとか
  • で、if ($go_maintenance = "true") { return 503; }
    • server {}の中でreturn 503してるので、後続にlocationブロックがたくさんあってもこれだけでOK