[Nginx]locationとrootの罠

TIPS

Nginxの locationroot ディレクティブが持つ「独特なパス解決の仕様」について、誰もが一度はハマる罠と、それを美しく解決する方法をステップ・バイ・ステップで解説します。

昔ながらのWebサーバー「Apache」との設計思想の違いも交えているので、仕組みを根本から理解したい方はぜひ参考にしてください!

背景:やりたかったことと、発生したトラブル

構築していたシステムの状況は以下の通りです。

  • URLの見た目: http://localhost/server/index.html のように /server/ でアクセスさせたい。
  • 実際のサーバー内のフォルダ: /var/www/html/ の中に動画ポータル用のファイルが置いてある。

URLは /server/ なのに、実際の配備フォルダは /var/www/html/。この「ズレ」を解消しようとして、最初は以下のような設定を書きました。

location /server/ {    root /var/www/html/;
    index index.html;
    try_files $uri $uri/ @flask; # ファイルがなければ裏のPythonへ
}

一見良さそうに見えますが、これでアクセスすると無情にも 404 Not Found

最終的に、root を1階層上のフォルダ(/var/www)に変更し、フォルダ名自体を html から server にリネーム(/var/www/server)する」 という対応で無事に解決しました。

なぜ最初のはダメで、リネームしたら動いたのか。その理屈を紐解いていきましょう。

Step 1:ApacheとNginxの「設計思想」の違いを知る

理屈を理解する最大の近道は、Apache(アパッチ) と比較することです。

Apacheの場合(フォルダを直接指定する)

Apacheで同じような設定(Alias)を書く場合、「このURLが来たら、このフォルダの中身をそのまま見せなさい」という 1対1のすり替え を行います。

  • /server/ にアクセスが来たら、/var/www/html/ の中身をダイレクトに見せる」が直感的に動きます。

Nginxの場合(URLとフォルダ構造を一致させる)

一方、Nginxの root ディレクティブは全く異なる動きをします。

Nginxは、root で指定したパスの末尾に、URLのパスをそのままガッチャンコと結合する」 という超機械的なルールを持っています。

まずはこの「Nginxは結合する」という性質を頭に入れておいてください。

Step 2:なぜ最初は404エラーになったのか?(失敗の理由)

では、失敗した時のNginxの脳内をのぞいてみましょう。

  • 設定:location /server/ { root /var/www/html/; }
  • アクセスしたURL:/server/index.html

Nginxは先ほどのルールの通り、指定された root の後ろに、URL의 パスをそのままくっつけます。

$$\text{探す場所} = \text{rootのパス} + \text{URLのパス}$$

【Nginxの計算式】

/var/www/html//server/index.html

/var/www/html/server/index.html

お分かりでしょうか。Nginxは html フォルダの中に、さらに server という名前のフォルダ を探しに行ってしまっていたのです。

実際のサーバー内にはそんなフォルダはないため、「ファイルがありません」ということで404エラーになっていた、というのが真相です。

Step 3:なぜ「1階層上 + リネーム」で動いたのか?

この罠を回避するための最も美しく、Nginxの仕様に沿った解決策が、今回実施した「rootを1階層上にして、フォルダ名をURLと一致させる」方法です。

  • 変更後の設定:location /server/ { root /var/www; }
  • フォルダ名の変更:htmlserver にリネーム(実パス:/var/www/server/
  • アクセスしたURL:/server/index.html

この状態でもう一度、Nginxに計算させてみます。

【変更後の計算式】

/var/www/server/index.html

/var/www/server/index.html

今度はフォルダ名を server に変えたおかげで、Nginxが自動で組み立てたパスと、実際のサーバー内のフォルダ構造が100%完全に一致しました!

パズルのピースが綺麗にハマり、try_files も無事に物理ファイルを見つけられるようになったため、正常に動くようになりました。

まとめ:Nginxでローカルサーバーを建てる時の鉄則

フォルダ名が違っていても動く alias という設定方法もありますが、alias は記述を1文字ミスするだけでセキュリティ脆弱性(他のファイルが丸見えになるバグ)を生みやすいというデメリットがあります。

今回行き着いた、「1階層上のフォルダを root に指定し、サーバー内のフォルダ名をURL(Location)と同じ名前に統一する」 という手法は、Nginxにおいて最もバグが起きにくく、動作も高速な 「王道のベストプラクティス」 です。

「Nginxのrootは、URLをそのまま後ろに結合する!」

この性質さえ覚えておけば、今後新しいフォルダやURLを追加する時も、もう迷うことはありません。快適なサーバーライフを!

コメント

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