nginxでバーチャルホストを複数設定しているとき、それぞれにカスタムエラーページを定義する方法のメモ。
やりたいこと
- Webサーバーはnginx
- バーチャルホストは複数定義
- バーチャルホストごとに404エラーのカスタムページを用意
- 40x系のエラーはすべて404エラーとして表示
- 50x系のエラーはすべて503エラーとして表示
- バーチャルホストにカスタムエラーページがない場合には、デフォルトサーバーのカスタムエラーページを使用
ハマったこと
serverディレクティブごとに次のようにerror_pageを定義してみたが、なぜかdefault_server用に定義したものしかカスタムエラーページが有効にならなかった。
server {
server_name _;
listen 443 ssl default_server;
http2 on;
error_page 400 403 404 =404 /404.html;
error_page 500 502 503 =503 /503.html;
location /404.html {
root /www/default;
internal;
}
location /503.html {
root /www/default;
internal;
}
(略)
}
server {
server_name some.host.name.jp;
listen 443 ssl;
http2 on;
error_page 400 403 404 =404 /404.html;
error_page 500 502 503 =503 /503.html;
location /404.html {
root /www/some;
internal;
}
location /503.html {
root /www/some;
internal;
}
(略)
}
上記の設定で動かすと、default_serverに定義したものは、error_pageで指定したファイルが表示される。が、some.host.name.jpで404エラーが出たときには、指定したページではなく、nginxのデフォルトエラーが表示されてしまう。
つまり、複数のバーチャルホストがあるときには、最初に定義したカスタムエラーページ(またはdefault_server)だけが有効になる。
解決策
次のようにカスタムエラーページを定義したところ、期待どおりに動くようになった。
まず、エラーを定義するerror.confを、次の内容で作成。
error_page 400 403 404 =404 @404;
error_page 500 502 503 =503 @503;
location @404 {
try_files /404.html @404_fallback;
}
location = /404.html {
return 404;
}
location @404_fallback {
root /www/default;
try_files /404.html =404;
}
location @503 {
try_files /503.html @503_fallback;
}
location = /503.html {
return 404;
}
location @503_fallback {
/www/default;
try_files /503.html =503;
}
作成したerror.confを、次のように各バーチャルホストの定義中にincludeで読み込む。
server {
server_name _;
listen 443 ssl default_server;
http2 on;
include error.conf;
(略)
}
server {
server_name some.host.name.jp;
listen 443 ssl;
http2 on;
include error.conf;
(略)
}
原理はよくわからないけど、これで期待通りに動く。
参考ページ
- Default error_page for multiple vhosts (ruby-forum.com)
- Using error_page to a named location – possible? (ruby-forum.com)