問題の概要
Nginxをセットアップしてブラウザを開くと、何の情報もない 403 Forbidden が表示されます。スタックトレースも説明メッセージもありません。ほとんどの場合、2つの原因のどちらかです:パーミッションの問題でNginxがファイルを読み取れないか、存在しないインデックスファイルを探しているかのどちらかです。
9割以上のケースで、サーバーの初期セットアップ直後、rootユーザーでファイルをデプロイした後、またはconfigのドキュメントルートを変更した後に発生します。
まずデバッグ:エラーログを確認する
まだ何も変更しないでください。Nginxが実際に何を訴えているのか確認しましょう:
sudo tail -f /var/log/nginx/error.log
以下の2つのパターンのどちらかが表示されます:
# ケース1 — ファイルの読み取りが拒否された場合
2024/01/15 10:23:45 [error] 1234#0: *1 open() "/var/www/html/index.html" failed (13: Permission denied)
# ケース2 — ディレクトリにインデックスファイルが見つからない場合
2024/01/15 10:23:45 [error] 1234#0: *1 directory index of "/var/www/html/" is forbidden
原因が異なれば修正方法も異なります。どちらの問題かを把握することで、見当違いの解決策を追いかける時間を節約できます。
修正1:ファイルまたはディレクトリのパーミッションの誤り
Permission denied というメッセージは、NginxのワーカープロセスがファイルをRead できないことを意味します。ワーカーは特定のユーザーとして実行されます。Debian/Ubuntuでは www-data、CentOS/RHELでは nginx です。
現在のパーミッションを確認する
ls -la /var/www/html/
ほとんどのケースは2つの数値で対応できます:
- ディレクトリ:
755— 実行可能(トラバース可能)である必要があります - ファイル:
644— 全員が読み取り可能、書き込みはオーナーのみ
パーミッションを再帰的に修正する
# すべてのディレクトリのパーミッションを修正する
sudo find /var/www/html -type d -exec chmod 755 {} \;
# すべてのファイルのパーミッションを修正する
sudo find /var/www/html -type f -exec chmod 644 {} \;
所有者を修正する
パーミッションが正しくても、ファイルがrootの所有でNginxが www-data として実行されている場合、アクセスは失敗します:
# ワーカーが実行されているユーザーを確認する
ps aux | grep nginx | grep worker
# 所有者を修正する(CentOS/RHELではwww-dataをnginxに変更する)
sudo chown -R www-data:www-data /var/www/html/
親ディレクトリも忘れないでください。NginxはWebルートだけでなく、パス上のすべてのディレクトリに実行パーミッションが必要です:
ls -la /var/
ls -la /var/www/
修正2:インデックスファイルの欠落
directory index is forbidden が表示されましたか?Nginxはディレクトリを正常に見つけましたが、提供できる一致するインデックスファイルがなく、デフォルトで autoindex がオフになっているためディレクトリの内容を一覧表示しません。
Nginxが期待するインデックスファイルを確認する
grep -r "index" /etc/nginx/sites-enabled/
# またはhttpブロックのデフォルトを確認する
grep "index" /etc/nginx/nginx.conf
デフォルトは通常 index index.html index.htm か、PHPスタックの場合は index index.php index.html です。
ファイルが存在するか確認する
ls -la /var/www/html/
home.html しかないのにNginxが index.html を探している場合は、以下のどちらかの修正を選んでください:
オプションA — インデックスファイルを作成またはリネームする:
mv /var/www/html/home.html /var/www/html/index.html
オプションB — Nginxのサーバーブロックを更新して実際のファイル名を含める:
server {
listen 80;
server_name example.com;
root /var/www/html;
index home.html index.html index.htm;
}
ディレクトリリストを表示したい場合は?
server {
location /files/ {
autoindex on;
}
}
機密性のないパスにのみ有効にしてください。Webルートには絶対に設定しないでください。
修正3:SELinuxによるアクセスのブロック(CentOS/RHEL)
RHELベースのシステムでは、パーミッションと所有者が正しく見えていても、SELinuxがNginxを静かにブロックすることがあります:
# Nginxの拒否に関する監査ログを確認する
sudo audit2why -a | grep nginx
# 正しいSELinuxコンテキストを復元する
sudo restorecon -Rv /var/www/html/
# または手動で設定する
sudo chcon -Rt httpd_sys_content_t /var/www/html/
修正の確認
# 設定をテストし、ダウンタイムなしでリロードする
sudo nginx -t && sudo systemctl reload nginx
# レスポンスを確認する
curl -I http://localhost
# 期待される結果: HTTP/1.1 200 OK
# エラーログがクリアになったか確認する
sudo tail -20 /var/log/nginx/error.log
クイックチェックリスト
- エラーログに Permission denied と表示される →
chmodとchownを修正する - エラーログに directory index is forbidden と表示される → インデックスファイルを追加するか指定する
- ディレクトリは
755、ファイルは644 - 所有者がNginxワーカーユーザー(
www-dataまたはnginx)と一致している - 親ディレクトリもトラバース可能である
- RHEL/CentOSでSELinuxコンテキストが正しく設定されている
ヒント:推測なしでパーミッションを計算する
644 や 755 以外のパーミッションが必要で8進数の値がわからない場合は、ToolCraftのUnix Permissions Calculator が便利です。owner/group/otherのチェックボックスをクリックするだけで数値が表示されます。アップロードディレクトリや非標準のパーミッション要件を持つCGIスクリプトのセットアップ時に役立ちます。
まとめ
403エラーのほとんどは2つの習慣に起因します:rootとしてファイルをデプロイした後に所有者を修正しないこと、そしてインデックスファイル名がNginxの設定と一致するか確認しないことです。エラーログはそれについて率直に教えてくれます。正確なファイルと正確な理由を名指しします。ブラウザのメッセージからではなく、そこから始めれば、通常2分以内に修正できます。

