Nginxで発生する404エラーの原因特定と解消方法
WebサイトやWebアプリケーションを運用する上で、404 Not Foundエラーは頻繁に遭遇する問題の一つです。NginxをWebサーバーとして使用している場合も例外ではありません。ユーザーがリクエストしたリソース(ファイルやページ)がサーバー上に見つからない場合に、サーバーはHTTPステータスコード404を返します。
このエラーは、訪問者にとっては「目的の情報にたどり着けない」という不満につながり、サイト管理者にとっては「なぜ見つからないのか?」という疑問と原因特定の必要性を生じさせます。幸いなことに、Nginxにおける404エラーのほとんどは、設定、ファイル配置、またはパーミッションの問題に起因しており、体系的に調査することで解決できます。
この記事では、Nginxで404エラーが発生する根本的な原因を深掘りし、効果的な原因特定のための手順、そして具体的な解消方法について、詳細かつ網羅的に解説します。約5000語にわたるこの解説を通じて、Nginx環境での404エラーに自信を持って対処できるようになることを目指します。
1. はじめに:404 Not Foundとは何か
HTTPステータスコード404 Not Foundは、クライアント(通常はWebブラウザ)がサーバーに送信したリクエストにおいて、サーバーが要求されたリソースを見つけることができなかったことを示す標準的な応答コードです。これはクライアント側のエラーとして分類されますが、実際にはサーバー側の設定やファイル配置の問題が原因であることがほとんどです。
重要な点として、404エラーは「サーバー自体がダウンしている」とか「リクエストの処理中にサーバーで予期しないエラーが発生した」という状況を示すものではありません(それらは5xx系のエラーコードです)。404はあくまで「リソースが存在しない」ことを伝えるための正常なレスポンスの一つです。
Nginxは、静的ファイルの配信、リバースプロキシ、ロードバランシングなど多岐にわたる役割を担いますが、いずれの役割においても、リクエストされたパスに対応するリソースを見つけられなければ404エラーを返します。
この記事では、Nginxを主に静的ファイルサーバーとして、あるいはPHP-FPMなどのバックエンドと連携させる場合の404エラーに焦点を当てて解説します。
2. 404エラーの基本的な理解:Nginxはどのようにリソースを探すのか
Nginxがクライアントからのリクエストを受け取ると、設定ファイル(通常はnginx.confや、sites-available/sites-enabled配下の設定ファイル)を基に、そのリクエストをどのように処理するかを決定します。この処理の中心となるのが、serverブロックとlocationブロックです。
serverブロックのマッチング: Nginxはまず、リクエストのホスト名(Hostヘッダー)とポート番号に基づいて、どのserverブロックを使用するかを決定します。server_nameディレクティブがここで重要な役割を果たします。locationブロックのマッチング: 使用するserverブロックが決定すると、次にNginxはリクエストされたURI(URLのドメイン名以降の部分)に基づいて、最も適切なlocationブロックを探します。locationブロックは、特定のURIパスに対する処理ルール(どのディレクトリからファイルを探すか、どのバックエンドにリクエストを転送するかなど)を定義します。- リソースの探索: 静的ファイル配信の場合、Nginxは選択された
locationブロック内で定義されているrootまたはaliasディレクティブと、リクエストされたURIの残りの部分を組み合わせて、ファイルシステムのパスを構築します。rootディレクティブ:root /var/www/html;という設定があり、リクエストURIが/css/style.cssの場合、Nginxは/var/www/html/css/style.cssというパスを探します。aliasディレクティブ:location /static/ { alias /opt/data/static/; }という設定があり、リクエストURIが/static/image.pngの場合、Nginxは/opt/data/static/image.pngというパスを探します。aliasはlocationでマッチした部分を置き換えます。indexディレクティブ: ディレクトリに対するリクエスト(例:/css/)の場合、Nginxはindexディレクティブで指定されたファイル名(例:index.html,index.php)をrootまたはaliasで構築したパスに追加してファイルを探します(例:/var/www/html/css/index.html)。try_filesディレクティブ: このディレクティブを使うと、複数のパスを順番に試すことができます。指定されたパスにファイルやディレクトリが見つからない場合に、フォールバックとして別のパスを試したり、特定のステータスコードを返したりする柔軟な設定が可能です。
- ファイル/ディレクトリの確認: Nginxは構築したファイルシステムのパスに対応するファイルまたはディレクトリが存在するか、そしてNginxワーカープロセスがそのリソースを読み取る権限を持っているかを確認します。
- レスポンス:
- ファイルが見つかり、権限があれば、Nginxはそのファイルをクライアントに送信し、HTTPステータスコード200 OKを返します。
- ディレクトリが見つかり、
indexファイルが存在すれば、そのファイルを返します(200 OK)。 - ディレクトリが見つかり、
indexファイルが存在せず、autoindex on;であればディレクトリリストを返します(200 OK)。 - ファイルもディレクトリも見つからない場合、または適切な権限がない場合、NginxはHTTPステータスコード404 Not Foundを返します。
したがって、404エラーが発生した場合、主な原因は上記の「リソースの探索」または「ファイル/ディレクトリの確認」のステップで問題が発生していることにあります。
3. Nginxで404エラーが発生する主な原因
Nginxで404エラーが発生する原因は多岐にわたりますが、ここでは特に一般的なものを詳細に見ていきます。
3.1. ファイルまたはディレクトリが存在しない (File or Directory Not Found)
これは最も直接的な原因です。Nginxが設定に基づいて計算したファイルシステムのパスに、実際にファイルまたはディレクトリが存在しないケースです。
- タイプミス: リクエストされたURLまたはサーバー上のファイル名にタイプミスがある。
- 大文字・小文字の区別: LinuxなどのUnix系システムでは、ファイル名やディレクトリ名は大文字・小文字を区別します。例えば、
image.PNGとimage.pngは異なるファイルとして扱われます。Nginxがimage.pngを探す設定になっているのに、実際のファイル名がimage.PNGである場合に404となります。Windowsサーバー上のNginxでは、デフォルトで大文字・小文字を区別しないことがありますが、設定やファイルシステムの種類によります。 - ファイル配置の誤り: ファイルが意図したディレクトリとは別の場所に配置されている。
- シンボリックリンクの問題: シンボリックリンクが壊れている(リンク先が存在しない)か、Nginxがシンボリックリンクを辿る権限がない。
disable_symlinksディレクティブの設定も影響します。 - ファイル削除: リクエストされたファイルが誤って削除された。
3.2. Nginxの設定ミス (Nginx Configuration Errors)
Nginxの設定ファイルに誤りがあると、Nginxがリソースを正しく見つけられない、あるいは不適切な処理を行ってしまうことがあります。
rootディレクティブの設定ミス:rootディレクティブで指定されたドキュメントルートのパスが間違っている。rootディレクティブがlocationブロックの外部(serverブロックなど)と内部の両方で定義されており、意図しないパスが構築されている。locationブロック内のrootは、外側のrootを上書きします。- パスが絶対パスで指定されていない。
aliasディレクティブの設定ミス:aliasで指定されたディレクトリのパスが間違っている。locationでマッチするパスとaliasで指定するパスの末尾の/の有無の組み合わせを間違えている。これは特に混乱しやすい点です。location /static/ { alias /path/to/static/; }: リクエスト/static/foo/bar.cssに対して/path/to/static/foo/bar.cssを探します。location /static { alias /path/to/static/; }: リクエスト/static/foo/bar.cssに対して/path/to/static/foo/bar.cssを探します(末尾の/はNginxが自動的に補完)。location /static/ { alias /path/to/static; }: リクエスト/static/foo/bar.cssに対して/path/to/static/foo/bar.cssを探します(非推奨。末尾に/を付けるのが一般的)。location /static { alias /path/to/static; }: リクエスト/static/foo/bar.cssに対して/path/to/staticfoo/bar.cssを探す可能性があります(これはほとんどの場合意図しない動作)。
aliasはlocationブロック内で使用する必要があり、rootと混同して使用している。
locationブロックのマッチング問題:- リクエストされたURIが、期待する
locationブロックにマッチしていない。locationのマッチング規則(順序、プレフィックスマッチ、正規表現マッチ)を理解していない。 - 複数の
locationブロックがマッチする場合、優先順位によって意図しないブロックが選択されている。 - 正規表現を使用した
locationブロックの正規表現が間違っている。
- リクエストされたURIが、期待する
indexディレクティブの設定ミス:- ディレクトリへのアクセス時(例:
/docs/)に、indexディレクティブで指定されたファイル(例:index.html,index.php)がディレクトリ内に存在しない。 indexディレクティブが指定されていない、または無効になっている。autoindex off;が設定されており、かつindexファイルが存在しないディレクトリにアクセスしている。
- ディレクトリへのアクセス時(例:
try_filesディレクティブの誤った使用:try_filesで指定されたパスのリストが間違っている。- フォールバックパスが正しく設定されていない。
- 最後の引数(フォールバックURIまたはステータスコード)の指定が間違っている。例えば、ファイルまたはディレクトリを探す意図で
/index.htmlを指定すべきところを=404としてしまっている。
- リライトルール (
rewrite) によるパスの変更ミス:rewriteディレクティブによって、存在しない、またはNginxが解決できないパスにリクエストが内部的に書き換えられている。rewriteルールのフラグ(last,break,redirect,permanent)の使い方が間違っており、処理が意図しない方向へ進んでいる。- リライト後のURIが、別の
locationブロックに意図せずマッチしている。
- バーチャルホスト(
serverブロック)の設定ミス:- リクエストの
Hostヘッダーに対応するserver_nameを持つserverブロックが存在しない。この場合、リクエストはデフォルトのserverブロックで処理されるが、そのブロックの設定がリクエストされたURIに対応していない可能性が高い。 listenディレクティブのポート番号が間違っている。
- リクエストの
- エイリアスやリダイレクトの無限ループ: 間違った設定によって、Nginxがリクエストを何度も書き換えたり、内部リダイレクトを繰り返したりして、最終的に存在しないパスにたどり着くか、サーバーエラーになる(無限ループの場合は通常500または502になるが、途中のステップで404になる可能性もある)。
3.3. パーミッションの問題 (Permission Issues)
Nginxワーカープロセスが、リクエストされたファイルまたはそれを含むディレクトリを読み取るためのファイルシステム権限を持っていない場合に404エラー(または403 Forbiddenエラー)が発生することがあります。Nginxは通常、nginx.confのuserディレクティブで指定されたユーザー(例: nginx, www-data)で動作します。
- ファイル読み取り権限がない: Nginxワーカープロセスが、リクエストされたファイルに対して読み取り権限(
r)を持っていない。 - ディレクトリの実行権限がない: Nginxワーカープロセスが、リクエストされたファイルが存在するディレクトリ、またはその親ディレクトリを辿るための実行権限(
x)を持っていない。ディレクトリの実行権限は、そのディレクトリに入り、中身をリストしたり、ファイルにアクセスしたりするために必要です。 - SELinuxやAppArmorによる制限: Linuxのセキュリティ強化機能(SELinuxやAppArmor)が、Nginxプロセスが特定のディレクトリやファイルにアクセスすることを制限している。これはファイルシステム権限とは別に考慮する必要があります。
3.4. アプリケーション側の問題 (Application-Side Issues)
NginxがリクエストをPHP-FPM、Gunicorn/uWSGI(Python)、Puma(Ruby)などのバックエンドアプリケーションにプロキシしている場合、アプリケーション自体が404エラーを生成してNginxに返すことがあります。
- アプリケーションのルーティングミス: フレームワークやアプリケーションのURLルーティング設定に誤りがあり、存在しないルートへのリクエストとして扱われている。
- アプリケーション内のファイル参照ミス: アプリケーションが内部的に読み込もうとしたテンプレートファイルやデータファイルが見つからない。
- FastCGI/WSGI/Proxy設定ミス: Nginxとアプリケーションサーバー間の連携設定(
fastcgi_pass,proxy_pass,uwsgi_passなど)に誤りがあり、アプリケーションがリクエストを正しく受け取れていない、またはアプリケーションが生成したレスポンスをNginxが正しく処理できていない。特に、SCRIPT_FILENAMEなどのFastCGIパラメータが正しく渡されていない場合に、PHP-FPMがファイルを見つけられずに404を返すことがあります。
3.5. キャッシュの問題 (Caching Issues)
古いキャッシュが原因で、実際には存在する(または新しいパスに移動した)リソースが404と表示されることがあります。
- ブラウザキャッシュ: ユーザーのブラウザに古いキャッシュが残っており、存在しないパスをリクエストしている。
- 中間キャッシュ: CDNやプロキシサーバーなど、ユーザーとNginxの間に存在するキャッシュサーバーが古い情報を保持している。
- Nginxプロキシキャッシュ: Nginx自体がリバースプロキシとして動作している場合に、Nginxのプロキシキャッシュに古い404レスポンスがキャッシュされている。
3.6. URLエンコーディングの問題 (URL Encoding Issues)
URLに使用されている文字が正しくエンコード/デコードされていない場合、Nginxが意図したパスを解決できないことがあります。特に、日本語、スペース、記号などが含まれるURLで問題が発生しやすいです。
3.7. 物理的なストレージの問題 (Physical Storage Issues)
非常に稀ですが、ファイルシステム自体の破損やディスク容量の不足が原因で、Nginxがファイルシステム上のリソースにアクセスできなくなる可能性もゼロではありません。
4. 404エラーの原因特定のためのステップ
404エラーの原因を特定するには、体系的なアプローチが必要です。以下のステップを踏むことで、効率的に問題を絞り込むことができます。
ステップ1:問題の切り分け (Isolation)
まず、問題の範囲と状況を正確に把握します。
- どのURLで発生するか? 特定の1つのURLか? 特定のディレクトリ以下のすべてのURLか? 特定のファイルタイプ(例:
.js,.css)か? Webサイト全体のどのページでも発生するか? - 全てのユーザーで発生するか? 特定のユーザーや特定の場所からのアクセスでのみ発生するか?
- 特定のブラウザやデバイスで発生するか?
- 特定の時間帯に発生するか?
- 最近、サーバー設定、Nginx設定、アプリケーションコード、ファイル配置などに変更を加えたか? もし変更があれば、それが最も有力な原因候補となります。
- 静的ファイルか、動的コンテンツか? (例:
/style.cssか/about-usか)
これらの情報を整理することで、問題の性質(グローバルな設定問題か、特定のファイルの問題か、特定の条件下で発生するかなど)が見えてきます。
ステップ2:ログの確認 (Checking Logs)
ログはサーバーの挙動を記録した宝庫です。特にNginxのログは、404エラーの原因特定に不可欠です。
- Nginxアクセスログ (
access.log):- 場所: 通常は
/var/log/nginx/access.logまたはNginx設定ファイルで指定された場所。 - 確認すべきこと:
- エラーが発生しているリクエストに対応する行を見つけます。タイムスタンプ、クライアントIP、リクエストメソッド、リクエストURI、HTTPステータスコード(404であるはずです)、レスポンスサイズ、リファラ、ユーザーエージェントなどが記録されています。
- リクエストURIが意図したものであるか確認します。ユーザーがタイプミスしている可能性も排除できません。
log_formatの設定を確認し、ログの各フィールドが何を示しているか理解しておきます。カスタムフォーマットの場合、追加情報(例:$request_filename– Nginxがファイルシステムで探したパス)が出力されていると役立ちます。
- 例:
192.168.1.100 - - [08/Nov/2023:10:30:00 +0000] "GET /nonexistent-page.html HTTP/1.1" 404 153 "-" "Mozilla/5.0..."
- 場所: 通常は
- Nginxエラーログ (
error.log):- 場所: 通常は
/var/log/nginx/error.logまたはNginx設定ファイルで指定された場所。 - 確認すべきこと:
- エラーログのメッセージは、Nginxが何に失敗したかを直接的に示してくれることが多いです。特に、リクエストされたURLに対応する時間帯のエラーメッセージを探します。
- 典型的な404関連のエラーメッセージ:
open() "/path/to/file" failed (2: No such file or directory): Nginxが特定のファイルを開こうとしたが、指定されたパスにファイルが存在しなかったことを示します。これはファイルが存在しないか、パスの構築が間違っている可能性を示唆します。open() "/path/to/directory" failed (13: Permission denied)またはstat() "/path/to/file" failed (13: Permission denied): Nginxがファイルまたはディレクトリにアクセスしようとしたが、パーミッションが拒否されたことを示します。これはファイルシステム権限またはSELinux/AppArmorの問題を示唆します。Rewriting internally the URI...:rewriteディレクティブがどのように機能しているかを示す情報が記録されていることがあります(ログレベルをinfo以上に設定している場合)。
- ログレベル:
error_logディレクティブでログレベル(debug,info,notice,warn,error,crit,alert,emerg)が設定されています。デフォルトはerrorです。原因特定のために、一時的にレベルをinfoやdebugに上げると、より詳細な処理過程が記録され役立つことがあります(ただし、ログ量が膨大になるため本番環境での常時使用は推奨されません)。
- 例:
2023/11/08 10:30:00 [error] 12345#12345: *678 open() "/var/www/html/nonexistent-page.html" failed (2: No such file or directory), client: 192.168.1.100, server: example.com, request: "GET /nonexistent-page.html HTTP/1.1", host: "example.com"
- 場所: 通常は
- システムログ (
syslog,dmesg,journalctl): SELinuxやAppArmorによる拒否、ディスク関連のエラーなど、システムレベルの問題はこれらのログに記録されることがあります。
ステップ3:Nginx設定の確認 (Reviewing Nginx Configuration)
ログで問題の兆候が見られたら、次はNginxの設定ファイルを詳細にレビューします。
- 設定ファイルの場所: Nginxのメイン設定ファイルは通常
/etc/nginx/nginx.confです。サイト固有の設定は/etc/nginx/sites-available/に置かれ、/etc/nginx/sites-enabled/からシンボリックリンクが張られている構成が一般的です。どのファイルが読み込まれているか確認します(nginx.conf内のincludeディレクティブを見ます)。 - 設定ファイルの構文チェック: 設定変更後やレビュー前に、必ず
nginx -tコマンドを実行して構文エラーがないか確認します。エラーがあれば、それを修正しないと設定は適用されません。 - 影響を受けている
serverブロックを特定: リクエストされたホスト名(ログのhostフィールドまたはリクエストヘッダーで確認)とポート番号に基づいて、どのserverブロックが使われているかを特定します。server_nameディレクティブを確認します。 - リクエストURIに対応する
locationブロックを特定: 特定したserverブロック内で、リクエストされたURI(ログのリクエストURIフィールドで確認)に最もマッチするlocationブロックを探します。locationのマッチング規則を考慮して、意図したブロックが選択されているか確認します。 root/alias/index/try_files/rewriteディレクティブを確認: 特定したlocationブロック内のこれらのディレクティブが、期待通りのパスを構築しているか、ファイルを探しているか確認します。rootやaliasで指定されているパスが正しい絶対パスか?aliasを使っている場合、locationパスとaliasパスの組み合わせは正しいか?- ディレクトリへのアクセスの場合、
indexで指定されたファイル名が存在するか? try_filesの順番と最終フォールバックは意図通りか?rewriteルールは正しく機能しており、存在しないパスに書き換えていないか?
includeディレクティブ: 使用している設定ファイル内で他のファイルがincludeされている場合、それらのファイルの内容も確認します。特に、FastCGIやProxyの設定ファイルがインクルードされている場合に、その中でパスに関連する設定(例:fastcgi_param SCRIPT_FILENAME ...)が間違っている可能性があります。- 設定の読み込み直し: 設定ファイルを変更した場合は、
sudo nginx -s reloadまたはsudo systemctl reload nginxコマンドで設定をNginxに読み込ませる必要があります。再起動が必要な変更もあります(例: listenポートの変更)。
ステップ4:ファイルシステムとパーミッションの確認 (Checking File System and Permissions)
Nginxの設定が正しいように見えても、ファイルシステム上の問題や権限の問題が原因で404になることがあります。
- ファイルの存在確認: Nginxの設定(
root/alias+ URIなど)に基づいてNginxが探していると推測されるファイルシステムのパスに対して、ls -l /path/to/expected/fileコマンドを実行し、実際にファイルが存在するか確認します。パスの途中のディレクトリもls -ld /path/to/directory/のように確認します。 - ファイル/ディレクトリの所有者とパーミッション確認:
ls -lコマンドの出力で、ファイルやディレクトリの所有者、グループ、パーミッション(rwxrwxrwxのような文字列)を確認します。 - Nginxワーカープロセスのユーザー確認:
ps aux | grep nginxコマンドを実行し、Nginxワーカープロセスがどのユーザーで実行されているか確認します(通常はnginxやwww-data)。Nginx設定ファイルのuserディレクティブも確認します。 - 権限チェック: Nginxワーカープロセスのユーザーが、問題のファイルに対して読み取り権限(
r)、およびそのファイルを含むすべての親ディレクトリに対して実行権限(x)を持っているか確認します。 - SELinux/AppArmorのステータス確認:
sestatus(SELinux) やgetenforce(SELinux),sudo aa-status(AppArmor) コマンドで、セキュリティ強化機能が有効になっているか確認します。有効な場合は、auditctl -a always,exit -F arch=b64 -S open -k file_access(SELinux) やjournalctl -f(両方) などのコマンドで、Nginxによるファイルアクセス拒否を示すログが出力されていないか確認します。SELinuxの場合は、ls -Z /path/to/fileでファイルのセキュリティコンテキストを確認し、nginx_tなどのコンテキストが適切に設定されているか見ます。
ステップ5:ブラウザツールと外部ツールの利用 (Using Browser Developer Tools and External Tools)
クライアント側からの視点も重要です。
- ブラウザの開発者ツール:
- ブラウザで問題のURLを開き、F12キーなどで開発者ツールを開きます。
- 「Network」タブに切り替えます。ページを再読み込みすると、すべてのリソース(HTML、CSS、JavaScript、画像など)のリクエストが表示されます。
- 404エラーになっているリクエスト(Status列が404になっているもの)を見つけます。
- そのリクエストをクリックして詳細を表示します。
- 「Headers」タブで、リクエストURL、リクエストメソッド(GETなど)、リクエストヘッダー(特に
Hostヘッダー)、レスポンスヘッダーを確認します。レスポンスヘッダーに含まれるServerヘッダーがNginxであることを確認できます。 - リクエストURLが正しくエンコードされているか、意図したパスになっているか確認します。
curlコマンド:- サーバー側から、または別のマシンから問題のURLに
curlコマンドでアクセスしてみます。 curl -I <URL>: ヘッダー情報のみを取得します。これにより、HTTPステータスコード(404)やレスポンスヘッダーを確認できます。Nginxが応答しているかどうかの確認にも使えます。curl <URL>: コンテンツ全体を取得します。Nginxが返している404エラーページの内容を確認できます。カスタムエラーページを設定している場合、それが正しく表示されているか確認できます。
- サーバー側から、または別のマシンから問題のURLに
- オンラインツール: ヘッダーチェッカーやWebサイト診断ツールなども、外部からの視点でリクエスト/レスポンスを確認するのに役立ちます。
5. 具体的な解消方法 (Specific Solutions)
原因特定ステップで見つかった問題に応じて、具体的な解消方法を適用します。
5.1. ファイル/ディレクトリが存在しない場合
- ファイルの配置確認:
ls -lコマンドなどで、Nginxが探しているパスにファイルが正しく配置されているか再確認します。必要であれば、ファイルを正しい場所に移動またはコピーします。 - 大文字・小文字の修正: ファイル名やディレクトリ名の大文字・小文字が、リクエストURLおよびNginx設定で期待されるものと完全に一致しているか確認します。Unix系システムでは大文字・小文字を区別するため、注意が必要です。必要であればファイル名を修正します。
- シンボリックリンクの確認/修正: シンボリックリンクを使用している場合は、
ls -lコマンドでリンク先が正しいか確認します。リンク先が存在しない場合は、リンク先を作成するか、シンボリックリンクを再作成します。また、Nginx設定でdisable_symlinksが制限的な設定になっていないか確認します。
5.2. Nginx設定の問題の場合
root/aliasの修正:rootまたはaliasで指定しているパスが、目的のファイルやディレクトリの絶対パスとして正しいか確認します。aliasを使用している場合、locationブロックのパスとaliasで指定するパスの末尾の/の有無の組み合わせが正しいか確認します。一般的には、location /path/ { alias /real/path/; }のように両方に/を付けるか、location /path { alias /real/path/; }のようにlocationの末尾には付けずaliasの末尾に付けるのが安全なパターンです。- 例 (
alias使用時の修正):
nginx
# 修正前: location /static/ { alias /data/static; } # 末尾スラッシュ不一致の可能性
# 修正後:
location /static/ {
alias /data/static/; # locationとaliasの両方のパスに末尾スラッシュを付ける
}
locationブロックのマッチング修正:- リクエストURIにマッチさせたい
locationブロックが、実際にはマッチしていない場合は、locationの定義を見直します。 - 正規表現を使用している場合は、正規表現が正しいか確認し、必要であればオンラインツールなどでテストします。
- 複数の
locationブロックがある場合、Nginxのマッチング優先順位(完全一致=, プレフィックスマッチ^~, 正規表現~or~*, プレフィックスマッチ/)を理解し、意図したブロックが選択されるように調整します。最も具体的な(長い)プレフィックスマッチが優先され、正規表現は定義順に評価されます。完全一致は最も優先されます。 - 例 (
locationマッチングの調整):/images/以下のリクエストを静的ファイルとして処理したいのに、他の正規表現ブロックに奪われている場合、^~を使って優先度を上げる。
nginx
location ^~ /images/ {
root /var/www/data; # /var/www/data/images/file.jpg を探す
expires 30d;
}
# 他の正規表現locationブロックがこれより後に定義されていても、images/以下のリクエストはここで処理される
- リクエストURIにマッチさせたい
indexディレクティブの修正:- ディレクトリへのアクセス(例:
/docs/)で404になる場合、そのディレクトリにindexディレクティブで指定されたファイル(例:index.html)が存在するか確認します。なければファイルを作成するか、indexディレクティブに別のファイル名を追加します(例:index index.htm index.php;)。 autoindex on;を設定すると、indexファイルがない場合にディレクトリの内容がリストされます(セキュリティリスクに注意)。
- ディレクトリへのアクセス(例:
try_filesディレクティブの修正:try_filesの引数の順番と内容が正しいか確認します。- 例:
/pageというリクエストに対して、まず/pages/page.htmlを試し、なければ/pages/page/index.htmlを試し、それもなければ/index.htmlを表示し、それでもなければ404を返す場合。
nginx
location / {
root /var/www/html;
try_files $uri.html $uri/index.html /index.html =404;
}
# この設定で /page にアクセスした場合、Nginxは順に以下を探します。
# 1. /var/www/html/page.html
# 2. /var/www/html/page/index.html
# 3. /var/www/html/index.html
# どれも見つからなければ 404 を返す。 $uriはリクエストURI(/page)を、$uri.htmlは/page.htmlを、$uri/は/page/を意味します。これらのパスにrootまたはaliasが適用されて実際のファイルシステムパスが構築されます。
rewriteディレクティブの修正:rewriteルールが期待通りに動作しているか確認します。エラーログのinfoレベルで出力されるリライト情報を確認すると役立ちます。- リライト後のパスが、別の
locationブロックに適切にマッチするように設定を見直します。 - 無限ループになっていないか確認します。通常、リライトの回数には上限があります。
- 例 (
rewriteの修正):/product/123を/items.php?id=123に書き換えたい場合。
“`nginx
location /product/ {
# /product/123 を /items.php?id=123 に書き換え
rewrite ^/product/(\d+)$ /items.php?id=$1 last;# 書き換え後の /items.php?id=... は別のlocation(例: location ~ \.php$)で処理される # このlocationブロック内では静的ファイルは探さないため、rootやaliasは不要または適切な設定にする}
``server
* **ブロックの修正:**server_name
*ディレクティブが、リクエストのHostヘッダーと正確に一致しているか確認します。サブドメイン(sub.example.com)、ワイルドカード(*.example.com)、正規表現なども正しく設定されているか見ます。listen
*ポートが正しいか確認します(通常は80や443)。sudo nginx -s reload
* **Nginx設定のリロード/再起動:** 設定ファイルを変更した後は、必ず設定をNginxに読み込ませる必要があります。
*: 設定ファイルを再読み込みします。ほとんどの設定変更はこのコマンドで適用できます。Nginxワーカープロセスは中断されません。sudo systemctl reload nginx
*(Systemdを使用しているシステムの場合)sudo nginx -s stop && sudo nginx
*: Nginxを完全に停止してから再起動します。listenポートの変更など、reloadでは適用できない一部の設定変更に必要です。この間、サービスは一時的に停止します。sudo systemctl restart nginx` (Systemdを使用しているシステムの場合)
*
5.3. パーミッションの問題の場合
- ファイル/ディレクトリのパーミッション修正:
chmodコマンドを使用して、ファイルやディレクトリのパーミッションを修正します。- ファイルにはNginxワーカープロセスのユーザーが読み取り権限(
r)を持っている必要があります。通常、Webで公開する静的ファイルには最低限chmod go+r file.html(group/othersに読み取り権限を付与) またはchmod o+r file.html(othersに読み取り権限を付与) を行います。よく使われるパーミッション設定は644(rw-r–r–) です。 - ディレクトリにはNginxワーカープロセスのユーザーが実行権限(
x)を持っている必要があります。これはディレクトリの中身をリストするためではなく、ディレクトリ構造を「辿る」ために必要です。通常、Webで公開するディレクトリには最低限chmod go+x directory/(group/othersに実行権限を付与) またはchmod o+x directory/(othersに実行権限を付与) を行います。よく使われるパーミッション設定は755(rwxr-xr-x) です。 - パーミッションはパスのルートディレクトリから問題のファイルまでのすべてのディレクトリに対して正しく設定されている必要があります。
- ファイルにはNginxワーカープロセスのユーザーが読み取り権限(
- ファイル/ディレクトリの所有者/グループ修正:
chownコマンドを使用して、ファイルやディレクトリの所有者やグループを、Nginxワーカープロセスのユーザーやそのユーザーが所属するグループに合わせることで、パーミッション管理を容易にすることができます。- 例:
sudo chown -R nginx:nginx /var/www/html(/var/www/html以下すべてのファイル/ディレクトリの所有者とグループをnginxユーザーに変更)
- 例:
- SELinux/AppArmorの調整:
- SELinuxやAppArmorのログを確認し、Nginxによるファイルアクセス拒否のログがあれば、それに応じて設定を調整します。
- SELinuxの場合、
chconコマンドでファイルのセキュリティコンテキストを変更したり、semanage fcontextとrestoreconで永続的なルールを追加したりします。 - デバッグ目的で一時的にSELinuxやAppArmorを無効化することも可能ですが、セキュリティリスクを高めるため、問題解決後は必ず有効に戻すか、適切な設定を行います。
- SELinuxを一時的にPermissiveモードにする:
sudo setenforce 0 - SELinuxをEnforcingモードに戻す:
sudo setenforce 1
5.4. アプリケーション側の問題の場合
- アプリケーションログの確認: PHP (
php-fpm.log), Python (gunicorn.log,uwsgi.log), Node.jsなどのアプリケーションサーバーのログを確認し、アプリケーション側で発生しているエラーがないか確認します。アプリケーションが明示的に404を返している場合、ログにその理由が記録されているはずです。 - Nginxとアプリケーションサーバー間の設定確認:
fastcgi_pass,proxy_pass,uwsgi_passなどのディレクティブで指定されたバックエンドのアドレスやポートが正しいか確認します。- FastCGIを使用している場合、
fastcgi_paramでSCRIPT_FILENAMEなどの重要なパラメータが正しく渡されているか確認します。SCRIPT_FILENAMEは、PHP-FPMが実行するPHPファイルのパスをPHP-FPMに伝えるために使用されます。このパスが間違っていると、PHP-FPMはファイルを見つけられず404を返します。 - 例 (
fastcgi_param SCRIPT_FILENAMEの修正):
nginx
location ~ \.php$ {
root /var/www/html; # PHPファイルがあるディレクトリのroot
fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock; # PHP-FPMソケットのパス
# SCRIPT_FILENAME の設定
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; # $document_root は location 内の root
# または alias を使っている場合は $document_root の代わりに alias で指定したパスを使用
# fastcgi_param SCRIPT_FILENAME /path/to/php/files$fastcgi_script_name; # aliasの場合
include fastcgi_params; # 標準のFastCGIパラメータをインクルード
} $document_rootは、現在のlocationまたはその外側のserverまたはhttpブロックで定義されているrootディレクティブの値です。$fastcgi_script_nameはリクエストURIです。これらの組み合わせで、実行するPHPファイルの物理パスが構築されます。
- アプリケーションのルーティング設定確認: アプリケーションフレームワーク(Laravel, Symfony, Django, Flaskなど)のルーティング設定ファイルを確認し、リクエストされたURLに対応するルートが定義されているか、そのルートが正しいコントローラーやビューを指しているか確認します。
5.5. キャッシュの問題の場合
- ブラウザキャッシュのクリア: ユーザー側にブラウザのキャッシュをクリアしてもらうか、スーパーリロード(Ctrl+Shift+R または Cmd+Shift+R)を試してもらいます。
- CDNキャッシュのパージ: CDNを利用している場合は、CDNの管理画面からキャッシュのパージ(削除)を行います。
- Nginxプロキシキャッシュのクリア: Nginxをプロキシとして使用していてキャッシュが有効な場合、キャッシュディレクトリの内容を削除することでキャッシュをクリアできます(Nginxの設定でキャッシュパスを確認)。
- 例:
sudo rm -rf /var/cache/nginx/my_proxy_cache/*(Nginx停止中に行うのが安全)
- 例:
5.6. URLエンコーディングの問題の場合
- リクエストURLに特殊文字が含まれている場合は、それがRFC 3986に沿って正しくエンコードされているか確認します。ブラウザは通常自動的にエンコードしますが、生成されたリンクや入力フォームからの送信で問題が発生することがあります。
- Nginxの
merge_slashesディレクティブは、連続するスラッシュを1つにまとめる挙動を制御しますが、これが特定の状況で意図しないパス変更を引き起こすことがあります。デフォルトはonです。特定のパスで問題が発生する場合、この設定が影響していないか確認します。
6. 高度なデバッグテクニック (Advanced Debugging Techniques)
上記の手順で原因が特定できない場合、より高度なデバッグ手法が必要になることがあります。
error_logレベルをdebugに設定: Nginx設定のerror_logディレクティブのログレベルをdebugに一時的に変更します(例:error_log /var/log/nginx/error_debug.log debug;)。これにより、Nginxがリクエストを処理する際の内部的なステップ(設定の読み込み、serverブロックのマッチング、locationブロックの選択、ファイルパスの構築、ファイルへのアクセス試行など)に関する膨大な情報がログに出力されます。ログの量が非常に多くなるため、デバッグ対象のリクエスト時のみ有効にする、またはデバッグ用のNginxインスタンスを立てるなどの工夫が必要です。本番環境で長時間有効にすると、ディスク容量を圧迫し、パフォーマンスに影響を与える可能性があります。straceコマンド:straceは、Linuxプロセスが実行するシステムコールを追跡するための強力なツールです。NginxワーカープロセスのPIDを特定し、sudo strace -p <PID> -f -o nginx_strace.logのように実行すると、Nginxプロセスがどのようなファイルを開こうとしたか(openat,stat,accessシステムコールなど)、パーミッションが拒否されたか、といった詳細な情報を取得できます。特定のファイルパスに関連するエラーを探すのに役立ちます。これも出力が膨大になるため、フィルタリングオプション(例:-s 256 -e trace=file) を使用したり、対象のプロセスを絞ったりする工夫が必要です。- Nginxデバッグビルド: 標準のNginxビルドにはデバッグシンボルが含まれていないことがありますが、デバッグフラグ付きでNginxをビルドすることで、より詳細なデバッグ情報(GDBなどを使った調査)が可能になります。これは通常、Nginx自体の深いレベルの問題調査やモジュールのデバッグに使用されるため、一般的な404エラーのデバッグには上記の方法で十分なことが多いです。
7. 予防策 (Prevention)
404エラーの発生を未然に防ぐための対策も重要です。
- Nginx設定変更時の注意:
- 設定変更前に必ず設定ファイルのバックアップを取ります。
- 変更後は必ず
sudo nginx -tで構文チェックを行います。 - 大きな変更は一度に行わず、段階的に適用します。
- 変更内容に応じて、
reloadで済むかrestartが必要か判断します。 - 本番環境への適用前に、ステージング環境などで十分にテストを行います。
- ファイル配置とパス管理のルール化: Webコンテンツの配置ディレクトリ構造を明確にし、ファイルの移動や削除時には影響範囲を考慮します。
- パーミッション管理の徹底: Webサーバーのドキュメントルート以下のファイルおよびディレクトリに対して、Nginxワーカープロセスが必要なパーミッションを持っていることを確認し、定期的にレビューします。
- 定期的なログ監視: Nginxのエラーログやアクセスログを定期的に監視し、異常な404エラーの増加がないかチェックします。ログ監視ツールやアラートを設定すると、問題発生時に迅速に気づくことができます。
- リンクチェック: Webサイト内の内部リンク切れがないか、定期的にリンクチェッカーツールなどで確認します。
8. まとめ (Conclusion)
Nginxにおける404 Not Foundエラーは、「リクエストされたリソースがサーバー上で見つからない」という状況を示します。その原因は、ファイルが存在しない、Nginxの設定ミス、パーミッションの問題、アプリケーション側の問題、キャッシュ、URLエンコーディングなど、多岐にわたります。
原因特定のためには、まず問題の発生状況を詳細に切り分け、次にNginxのアクセスログとエラーログを徹底的に確認することが出発点となります。ログメッセージから、Nginxがどのファイルをどのパスで探しているか、そして何に失敗したか(ファイルが見つからないのか、パーミッションがないのかなど)の手がかりを得られます。
続いて、Nginx設定ファイル(特にserver、location、root、alias、index、try_files、rewriteディレクティブ)、ファイルシステムの実際のパスとパーミッション、そしてSELinux/AppArmorの設定を確認します。プロキシ設定の場合は、バックエンドアプリケーションの設定やログも調査範囲に含めます。
ブラウザの開発者ツールやcurlコマンドなどの外部ツールも、リクエストとレスポンスの詳細を確認するのに役立ちます。
原因が特定できれば、ファイルの配置修正、Nginx設定ファイルの修正(パス、マッチングルール、フォールバックなど)、ファイルパーミッションの修正、アプリケーション設定の修正、キャッシュのクリアなど、具体的な解決策を実行します。変更後は必ずNginx設定の再読み込みまたは再起動を忘れずに行います。
体系的な調査ステップを踏み、ログと設定ファイル、ファイルシステム上の情報から得られる手がかりを注意深く追うことで、Nginxで発生する404エラーのほとんどは解決可能です。また、適切な設定管理やログ監視といった予防策を講じることで、将来的なエラー発生リスクを低減することができます。
この詳細な解説が、あなたのNginx環境における404エラー問題の解決に役立つことを願っています。