メンテナンスをする度にnginxの設定ファイルを編集するのはドキドキする & 構成管理的によろしくない。何より障害発生時は一刻を争うので、nginx の設定で時間を浪費したくない。
そこで、編集なしでメンテナンスページに切り替える方法を検討してみた。
実現したいこと
- 設定ファイルを編集することなく、メンテナンスページに切り替えたい
- 内部アクセス(例えばオフィス)では検証のため、メンテナンスにはしたくない
- オフィスのIPアドレスは増えるかもしれないのでそれを見越しておきたい
設定
いろいろ調べた上での結論から。
http {
geo $access_from {
default external;
203.0.113.0/24 internal;
}
server {
error_page 503 @maintenance;
set $maintenance false;
if (-e /var/tmp/nginx/maintenance) {
set $maintenance true;
}
if ($access_from !~ external) {
set $maintenance false;
}
if ($maintenance = true) {
return 503;
}
location @maintenance {
root /var/www/html/static;
rewrite ^(.*)$ /50x.html break;
}
}
}
こうしておけば、メンテナンスモードはファイルに touch するだけで発動することができます。便利。
$ touch /var/tmp/nginx/maintenance
調査 & 工夫したこと
geo
ngx_http_geo_module を利用して、 $access_from という独自変数を定義しています。
オフィスのゲートウェイIPが増えたとしても、 geo モジュールで internal とラベリングするだけでよく、if 文を連発しなくても済むいうのがミソ。
今回の設定例では一筆書きですが、/etc/nginx/conf.d/geo.conf 等に分離するのもアリです。
If is Evil?
If Is Evil という有名? なドキュメントがあります。設定間違えると、SIGSEGV するかもよ、と書かれててドキリとします。
よく読むと、
"Directive if has problems when used in location context"
や
"There are cases where you simply cannot avoid using an if, for example, if you need to test a variable which has no equivalent directive."
と書かれているので、用法用量を間違わなければ問題ナシです。
今回の例も evil にならないような設定をしている(はず)。