【Nginx on EC2】トラブルシューティング完全ガイド！Linuxコマンドで原因を特定・解決

# はじめに
EC2インスタンス上でNginxを動かしているけれど、「Webサイトが表示されない！」「設定変更したのに反映されない！」「502 Bad Gatewayエラーが頻発する…」といったトラブルに直面していませんか？

Nginxは非常に高性能で安定したWebサーバーですが、設定ミスやリソースの問題、バックエンドとの連携不備など、様々な原因で問題が発生することがあります。このような時、EC2インスタンスにSSHで入り、Linuxコマンドを駆使して調査するスキルが非常に重要になります。

この記事では、EC2上で動作するNginxのトラブルシューティングに焦点を当て、問題の原因を特定し解決するための具体的なLinuxコマンドと、その実践的な使用方法をステップバイステップで詳しく解説します。

# Nginxトラブルシューティングの基本ステップとLinuxコマンド
問題解決の近道は、体系的に原因を切り分けていくことです。以下のステップで確認していきましょう。

### ステップ1: Nginxプロセスの状態確認
まず、Nginxサービス自体が正常に動作しているかを確認します。

`systemctl status nginx` : **Nginxサービスの稼働状況確認**

**何をするか？**: Nginxサービスが起動しているか、エラーで停止していないか、最近のログの概要などを確認します。

**どう使うか？**:
```Bash
sudo systemctl status nginx
```

**実例と確認ポイント**:
`Active: active (running)` と表示されれば、サービスは起動中です。
`Active: failed (Result: exit-code) ...` のように表示された場合は、Nginxが起動に失敗しています。ログに表示されたエラーメッセージや、後述する `nginx -t` で設定ファイルのエラーを確認しましょう。
```
● nginx.service - A high performance web server and a reverse proxy server
   Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; vendor preset: disabled)
   Active: failed (Result: exit-code) since Tue 2025-05-06 20:00:00 JST; 5s ago
  Process: 12345 ExecStartPre=/usr/sbin/nginx -t -q -g daemon on; master_process on; (code=exited, status=1/FAILURE)

May 06 20:00:00 ip-172-31-0-10.ap-northeast-1.compute.internal systemd[1]: Starting A high performance web server and a reverse proxy server...
May 06 20:00:00 ip-172-31-0-10.ap-northeast-1.compute.internal nginx[12345]: nginx: [emerg] unknown directive "typo_directive" in /etc/nginx/conf.d/default.conf:5
May 06 20:00:00 ip-172-31-0-10.ap-northeast-1.compute.internal nginx[12345]: nginx: configuration file /etc/nginx/nginx.conf test failed
```
上記のように `ExecStartPre` で `nginx -t` が失敗している場合、設定ファイルに問題があることが示唆されます。

`ps aux | grep nginx` : **Nginxプロセスの詳細確認**

**何をするか？**: Nginxのマスタープロセスとワーカープロセスが実際に起動しているか、どのユーザーで実行されているかなどを確認します。

**どう使うか？**:
```Bash
ps aux | grep nginx
```
**実例と確認ポイント**:
```
root      12301  0.0  0.1  12345  6789 ?        Ss   19:50   0:00 nginx: master process /usr/sbin/nginx -g daemon on; master_process on;
nginx     12302  0.0  0.2  12378  7890 ?        S    19:50   0:00 nginx: worker process
nginx     12303  0.0  0.2  12378  7890 ?        S    19:50   0:00 nginx: worker process
```
`master process` と複数の `worker process` が表示されていれば正常です。
ワーカープロセスが起動していない場合、設定ミスやリソース不足の可能性があります。
ワーカープロセスの実行ユーザー（上記例では `nginx`）が、`nginx.conf` の `user` ディレクティブで指定したユーザーと一致しているか確認します。このユーザーがドキュメントルートやログファイルにアクセス権限を持っている必要があります。

`nginx -t` : **設定ファイルの構文チェック**

**何をするか？**: Nginxの設定ファイル（`nginx.conf` およびインクルードされているファイル）に文法的な誤りがないかチェックします。Nginxを再起動/リロードする前に必ず実行しましょう。

**どう使うか？**:
```Bash
sudo nginx -t
```
**実例と確認ポイント**:
正常な場合:
```
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
```
エラーがある場合:
```
nginx: [emerg] directive "proxy_passs" is misspelled in /etc/nginx/conf.d/my_site.conf:15
nginx: configuration file /etc/nginx/nginx.conf test failed
```
エラーメッセージにファイル名と行番号が示されるので、該当箇所を修正します。上記例では `proxy_passs` というタイポがあります。

`sudo systemctl restart nginx` / `sudo systemctl reload nginx` : **設定の反映と動作確認**

**何をするか？**: 設定ファイルを変更した後、Nginxに設定を再読み込みさせるか、サービスを再起動します。`reload` はサービスを停止せずに設定を反映できるため、可能な限りこちらを使用します。

**どう使うか？**:
```Bash
sudo systemctl reload nginx  # 推奨
```
または
```Bash
sudo systemctl restart nginx
```
**確認ポイント**: コマンド実行後にエラーが表示されないか確認します。エラーが出た場合は、`systemctl status nginx` やエラーログで詳細を確認します。

### ステップ2: Nginxログファイルの徹底調査
ログは問題解決の最大のヒントです。アクセスログとエラーログの両方を確認しましょう。ログファイルのパスは `nginx.conf` で確認できます（デフォルトは `/var/log/nginx/` 配下）。

**アクセスログ** (`access.log`)

**何をするか？**: Nginxにどのようなリクエストが来て、Nginxがどのようなレスポンスを返したかを確認します。

**どう使うか？**:
リアルタイム監視:
```Bash
tail -f /var/log/nginx/access.log
```
特定のエラーステータスコード (4xx, 5xx) を抽出:
```Bash
grep " 404 " /var/log/nginx/access.log | less
grep " 502 " /var/log/nginx/access.log | tail -n 20 # 直近20件
```
特定のIPアドレスからのアクセスを確認:
```Bash
grep "192.0.2.123" /var/log/nginx/access.log
```
**実例と確認ポイント**:
`404 Not Found`: リクエストされたファイルが存在しない。root ディレクティブのパスやファイル名を確認。
`403 Forbidden`: アクセス権限がない。ファイルパーミッションやNginxの設定 (allow/denyなど) を確認。
`500 Internal Server Error`: Nginx自体ではなく、連携しているアプリケーション (PHP-FPMなど) でエラーが発生している可能性が高い。アプリケーション側のログも確認。
`502 Bad Gateway`: リバースプロキシ構成で、バックエンドサーバーが応答しないか、不正な応答を返した。バックエンドの状態を確認。
`504 Gateway Timeout`: バックエンドサーバーの応答が遅すぎる。

**エラーログ** (`error.log`)

**何をするか？**: Nginx自体のエラー、設定ミス、バックエンドとの接続エラー、パーミッション関連のエラーなど、より詳細な問題の原因を探ります。

**どう使うか？**:
リアルタイム監視:
```Bash
tail -f /var/log/nginx/error.log
```
特定のエラーメッセージを検索:
```Bash
grep -i "permission denied" /var/log/nginx/error.log # 大文字小文字無視
grep "connect() failed" /var/log/nginx/error.log
grep "upstream timed out" /var/log/nginx/error.log
```
**実例と確認ポイント**:
`[crit] ... connect() to unix:/run/php/php7.4-fpm.sock failed (13: Permission denied) while connecting to upstream`: PHP-FPMとのソケットファイルのパーミッションに問題があることを示唆。`ls -l /run/php/php7.4-fpm.sock` でパーミッションを確認し、Nginxの実行ユーザーがアクセスできるように修正します。

`[crit] ... SSL_CTX_use_PrivateKey_file("/etc/nginx/ssl/private.key") failed (SSL: error:0200100D:system library:fopen:Permission denied:fopen('/etc/nginx/ssl/private.key','r') error:20074002:BIO routines:file_ctrl:system lib error:140B0002:SSL routines:SSL_CTX_use_PrivateKey_file:system lib)`: SSL秘密鍵ファイルへのアクセス権限がない。`ls -l /etc/nginx/ssl/private.key` でパーミッションを確認し、Nginxの実行ユーザー（通常はrootで読み込み、ワーカープロセスは継承）が読めるようにします。通常、秘密鍵は所有者のみ読み取り可能 (`chmod 600`) ですが、Nginxのマスタープロセスはrootで起動し、その後ワーカープロセスが指定ユーザーに権限を落とすため、マスタープロセスが読めれば問題ありません。

`[error] ... *1 open() "/var/www/html/favicon.ico" failed (2: No such file or directory)`: ドキュメントルートに指定されたファイルが存在しない。
### ステップ3: 設定ファイル (`nginx.conf` と関連ファイル) の確認
Nginxの挙動は設定ファイルによって決まります。設定の不備がトラブルの原因となることは非常に多いです。

**設定ファイルの場所とパーミッション**

メイン設定ファイル: 通常 `/etc/nginx/nginx.conf`
サイトごとの設定ファイル: 通常 `/etc/nginx/conf.d/*.conf` や `/etc/nginx/sites-available/`, `/etc/nginx/sites-enabled/` (シンボリックリンク)

**どう使うか？**:
```Bash
ls -l /etc/nginx/nginx.conf
ls -lR /etc/nginx/conf.d/ # 再帰的に表示
```
Nginxの実行ユーザー（またはroot）がこれらのファイルを読み込めるか確認します。
`nginx.conf` (メイン設定ファイル) の確認ポイント
`user nginx;` : ワーカープロセスを実行するユーザー。このユーザーがドキュメントルートやログファイルなどにアクセスできる必要があります。
`worker_processes auto;` (または数値): CPUコア数に応じて適切に設定されているか。
`worker_connections 1024;` : 1ワーカープロセスあたりの最大同時接続数。
`include /etc/nginx/conf.d/*.conf;` : サイト別設定ファイルが正しくインクルードされているか。
サイト別設定ファイル (例: `/etc/nginx/conf.d/my_site.conf`) の確認ポイント
`listen 80;` / `listen 443 ssl;` : 正しいポートをリッスンしているか。IPv6の場合は `listen [::]:80;` など。
`server_name example.com www.example.com;` : 対象のドメイン名が正しく設定されているか。
`root /var/www/html/my_site;` : ドキュメントルートのパスは正しいか？
確認コマンド: `ls -ld /var/www/html/my_site` (ディレクトリの存在とパーミッション確認)
確認コマンド: `ls -l /var/www/html/my_site/index.html` (インデックスファイルの存在とパーミッション確認)
SSL/TLS設定 (HTTPSの場合):
`ssl_certificate /etc/nginx/ssl/my_site.crt;`
`ssl_certificate_key /etc/nginx/ssl/my_site.key;`
これらの証明書ファイルや秘密鍵ファイルのパスは正しいか？ Nginxが読み取れるパーミッションになっているか？
確認コマンド: `ls -l /etc/nginx/ssl/my_site.crt` `sudo ls -l` `/etc/nginx/ssl/my_site.key` (秘密鍵は通常rootのみアクセス可能)
location ブロック:
PHPなどアプリケーションサーバーとの連携設定は正しいか？ (例: `fastcgi_pass`)
```Nginx
location ~ \.php$ {
    include snippets/fastcgi-php.conf;
    fastcgi_pass unix:/run/php/php7.4-fpm.sock; # または 127.0.0.1:9000
}
```
`fastcgi_pass` で指定したソケットファイルやTCPポートは正しいか？ PHP-FPM側も同じ設定になっているか？
リバースプロキシ設定は正しいか？ (例: `proxy_pass`)
```Nginx
location /app/ {
    proxy_pass http://backend-server-ip:8080/;
}
```
`proxy_pass` のURLは正しいか？ 末尾のスラッシュの有無で挙動が変わる点に注意。
実例: エラーログに `open() "/usr/share/nginx/html/image.jpg" failed (2: No such file or directory)` とあるが、設定ファイルで `root /var/www/my_app;` となっていた。ドキュメントルートの不一致。
### ステップ4: ネットワーク関連の確認 (EC2内部とAWS環境)
Nginxの設定が正しくても、ネットワークの問題でアクセスできないことがあります。

**EC2内部からの接続確認**

**何をするか？**: NginxがEC2インスタンス内部で正しくポートをリッスンし、応答するか確認します。

**どう使うか？**:
Nginxがリッスンしているポートを確認:
```Bash
sudo ss -tulnp | grep nginx
# 出力例 (80番と443番でリッスン)
# tcp   LISTEN  0    511         0.0.0.0:80        0.0.0.0:* users:(("nginx",pid=12302,fd=6))
# tcp   LISTEN  0    511         0.0.0.0:443       0.0.0.0:* users:(("nginx",pid=12302,fd=8))
# tcp   LISTEN  0    511            [::]:80           [::]:* users:(("nginx",pid=12302,fd=7))
# tcp   LISTEN  0    511            [::]:443          [::]:* users:(("nginx",pid=12302,fd=9))
```
ここに表示されない場合、Nginxが起動していないか、`listen`ディレクティブの設定ミス。
ローカルホストからの接続テスト:
```Bash
curl -I http://localhost   # HTTPの場合
curl -I http://127.0.0.1
curl -I -k https://localhost # HTTPSの場合 (-kで自己署名証明書エラーを無視)
```
ここで接続できない場合、Nginxの設定やプロセス自体に問題があります。

**バックエンドへの接続確認 (リバースプロキシ構成の場合)**

**何をするか？**: Nginxからリバースプロキシ先のバックエンドサーバーへ正常に通信できるか確認します。

**どう使うか？**: 
EC2インスタンスのターミナルから実行します。
```Bash
ping <バックエンドサーバーのIPアドレス>
curl -I http://<バックエンドサーバーのIPアドレス>:<バックエンドのポート>
# 例: curl -I http://10.0.1.50:8080
```
**実例**: `curl` でバックエンドに接続しようとすると `Connection refused` や `No route to host` となる場合、バックエンドサーバーが起動していない、ポートが開いていない、またはEC2インスタンスからバックエンドへのネットワーク経路 (セキュリティグループ、NACL、ルートテーブルなど) に問題があります。

**ファイルディスクリプタ数の上限**

**何をするか？**: Nginxは多くの接続を処理するため、ファイルディスクリプタを多数消費します。上限に達すると新規接続を受け付けられなくなります。

**どう使うか？**:
Nginxプロセスの上限確認 (PIDは `ps aux | grep "nginx: worker process"` などで特定):
```Bash
cat /proc/<NginxワーカープロセスのPID>/limits | grep "Max open files"
```
OS全体の上限確認: `ulimit -n` (現在のセッション) または `sysctl fs.file-max` (システム全体)
Nginxエラーログに `"too many open files"` というエラーが出ていないか確認します。
対処: 必要に応じて `nginx.conf` の `worker_rlimit_nofile` ディレクティブでNginxの上限を引き上げるか、`/etc/security/limits.conf` などでOSレベルの上限を変更します。

### ステップ5: AWS環境設定の確認
EC2インスタンスやNginxの設定が完璧でも、AWS側のネットワーク設定が原因で外部からアクセスできないことがあります。

**セキュリティグループ**:
EC2インスタンスにアタッチされているセキュリティグループの インバウンドルール を確認。
Nginxがリッスンしているポート (通常 TCP 80, TCP 443) が、適切な送信元 (例: インターネットからのアクセスなら `0.0.0.0/0` や `::/0`) から許可されているか確認します。

**ネットワークACL (NACL)**:
EC2インスタンスが所属するサブネットに関連付けられているNACLを確認。
インバウンドルールとアウトバウンドルールの両方で、Nginxが使用するポートのトラフィック (およびエフェメラルポートの戻りトラフィック) が許可されているか確認します。NACLはステートレスなので双方向の許可が必要です。

**ルートテーブル**:
EC2インスタンスがパブリックサブネットにある場合、ルートテーブルにインターネットゲートウェイ (`0.0.0.0/0 -> igw-xxxxxx`) へのルートがあるか確認します。
プライベートサブネットからNATゲートウェイ経由で外部と通信する場合なども同様にルートを確認します。

**Elastic IP / Public IP**:
インスタンスにパブリックIPアドレス (Elastic IPまたは自動割り当てパブリックIP) が正しく割り当てられているか、AWSコンソールで確認します。

**DNS (Route 53など)**:
ドメイン名でアクセスしている場合、DNSレコードがEC2インスタンスの正しいパブリックIPアドレスを指しているか確認します。ローカルPCのターミナルから `dig example.com` や `nslookup example.com` を実行して確認できます。

# よくあるNginxエラーメッセージと対処法 (Linuxコマンドでの確認)
ここでは、代表的なHTTPステータスコードと、その原因調査に役立つLinuxコマンドを紹介します。

**403 Forbidden**
原因: アクセス権限がない。
確認:
ドキュメントルートや対象ファイルのパーミッション: `ls -ld /var/www/html/my_site`, `ls -l /var/www/html/my_site/secret.html` (Nginx実行ユーザーが読み取れるか？ディレクトリの場合は実行権限も必要)
Nginx設定ファイルの `allow`/`deny` ディレクティブ。
インデックスファイル (`index.html` など) が存在しない、またはパーミッションがない (ディレクトリにアクセスしようとした場合)。Nginx設定で `autoindex on;` が有効ならファイル一覧が表示されることも。
SELinuxが有効な場合: `getenforce` で状態確認。`sudo ausearch -m avc -ts recent` や `/var/log/audit/audit.log` で拒否ログ確認。`sudo setenforce 0` で一時的に無効化してテスト (非推奨、恒久的にはポリシー修正)。

**404 Not Found**
原因: リクエストされたリソースが見つからない。
確認:
Nginx設定ファイルの root ディレクティブのパスが正しいか。
実際にそのパスにファイルが存在するか: `ls -l <rootで指定したパス>/<リクエストされたファイルパス>`
シンボリックリンクの場合、リンク先が存在するか、パーミッションは適切か。
`try_files` ディレクティブの設定が意図通りか。

**500 Internal Server Error**
原因: サーバー内部で予期せぬエラー。多くはNginx自体ではなく、連携するバックエンドアプリケーション (PHP, Python, Node.jsなど) のエラー。
確認:
Nginxのエラーログ (`/var/log/nginx/error.log`): バックエンドからのエラーメッセージが記録されている場合がある。
バックエンドアプリケーションのログ: PHP-FPMなら `/var/log/php7.4-fpm.log` (バージョンによる)、Unicorn/Pumaならアプリケーションごとのログファイルなど。

**502 Bad Gateway**
原因: Nginxがリバースプロキシとして動作している際、バックエンドサーバーから無効な応答を受け取ったか、応答がなかった。
確認:
Nginxのエラーログ: バックエンドへの接続試行時のエラー詳細 (`connect() failed`, `upstream prematurely closed connection` など)。
バックエンドサーバーは起動しているか？ (バックエンドサーバーのホストでプロセス確認)
Nginxからバックエンドサーバーへネットワーク的に到達可能か？ (EC2インスタンスから `ping <backend_ip>`, `curl http://<backend_ip>:<backend_port>`)
バックエンドサーバーのポートは正しくリッスンしているか？ (バックエンドサーバーのホストで `ss -tulnp | grep <port>`)
バックエンドアプリケーションのログ。
`proxy_pass` ディレクティブのURLが正しいか。

**504 Gateway Timeout**
原因: Nginxがバックエンドサーバーからの応答を待ったが、タイムアウト時間内に応答が得られなかった。
確認:
バックエンドサーバーの処理が非常に重い、またはハングアップしている。バックエンドのCPU、メモリ、ログを確認。
Nginxの設定でタイムアウト値 (`proxy_connect_timeout`, `proxy_send_timeout`, `proxy_read_timeout`, `fastcgi_read_timeout` など) が短すぎないか。
ネットワーク遅延が大きい。

# それでも解決しないときは
**Nginxのデバッグログを有効化する**: `nginx.conf` の `error_log` ディレクティブでログレベルを `debug` に変更します (例: `error_log /var/log/nginx/error.log debug;`)。ただし、大量のログが出力されるため、問題解決後は元に戻しましょう。デバッグログを有効にするには、Nginxがデバッグオプション付きでコンパイルされている必要があります (`nginx -V` を実行し、出力の中に `--with-debug` が含まれているか確認します)。

**高度なLinuxコマンド**: `strace -p <NginxワーカーPID>` でシステムコールを追跡したり、`lsof -i :80 -Pni` や `lsof -p <PID>` でNginxが開いているファイルやソケットを確認したりすることも、原因究明の手がかりになることがあります（上級者向け）。

**AWSサポート**: どうしても解決しない場合は、AWSサポートに問い合わせることも検討しましょう。その際、ここまでの調査内容を伝えることで、よりスムーズなサポートが期待できます。

# まとめ
EC2インスタンス上で稼働するNginxのトラブルシューティングは、一見難しそうに思えるかもしれません。しかし、今回紹介したLinuxコマンドを使いこなし、Nginxのプロセス状態、ログ、設定ファイル、そしてAWSのネットワーク環境を体系的に確認していくことで、多くの場合、原因を特定し解決に導くことができます。

重要なのは、慌てずに一つ一つ可能性を潰していくことと、ログをしっかり読む習慣をつけることです。この記事が、皆さんのNginxトラブルシューティングの一助となれば幸いです。