nginxでバーチャルホストごとにerror_pageを設定

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;
    (略)
}

原理はよくわからないけど、これで期待通りに動く。

参考ページ

タイトルとURLをコピーしました