症状

nginxにアクセスすると「502 Bad Gateway」エラーが表示される。

結論:まずこれを確認

  1. バックエンド(upstream)のプロセスが起動しているか確認
  2. sudo tail -f /var/log/nginx/error.log でエラー内容を特定
  3. バックエンドのポート・ソケットパスが設定と一致しているか確認

トラブルシューティングフロー

    flowchart TD
    A[502 Bad Gateway 発生] --> B{error.log を確認}
    B -->|connect refused| C[バックエンドプロセス確認]
    B -->|upstream timed out| D[タイムアウト設定確認]
    B -->|no live upstreams| E[upstream設定確認]
    B -->|Permission denied| F[ソケット権限確認]
    C --> G{プロセス起動中?}
    G -->|No| H[バックエンドを起動]
    G -->|Yes| I[ポート/ソケット設定確認]
    D --> J[proxy_read_timeout 調整]
    E --> K[upstream ブロック確認]
    F --> L[ソケットファイル権限確認]
  

よくある原因

  • バックエンドプロセスが停止している - PHP-FPM、Node.js、Gunicornなどが起動していない
  • ポート番号の不一致 - nginxの設定とバックエンドのリッスンポートが異なる
  • Unixソケットのパス間違い - .sock ファイルのパスが設定と異なる
  • ソケットファイルの権限不足 - nginxユーザーがソケットにアクセスできない
  • バックエンドのタイムアウト - 処理に時間がかかりすぎてnginxが切断
  • upstreamサーバーの過負荷 - バックエンドがリクエストを処理しきれない
  • SELinux/AppArmorによるブロック - セキュリティモジュールが通信を遮断

確認手順

ステップ1: nginxエラーログを確認する

    sudo tail -50 /var/log/nginx/error.log
  

🔍 チェックポイント: connect() failedupstream timed outno live upstreams などのメッセージを探す

ステップ2: バックエンドプロセスの状態を確認する

PHP-FPMの場合:

    sudo systemctl status php-fpm
# または
sudo systemctl status php8.2-fpm  # バージョンは環境による
  

Node.jsの場合:

    ps aux | grep node
# PM2使用時
pm2 status
  

Gunicorn/uWSGIの場合:

    sudo systemctl status gunicorn
# または
ps aux | grep gunicorn
  

🔍 チェックポイント: active (running) と表示されれば起動中。inactivefailed なら停止している

ステップ3: リッスンポート/ソケットを確認する

ポートの場合:

    sudo ss -tlnp | grep -E '(9000|3000|8000)'  # ポート番号は環境による
  

Unixソケットの場合:

    ls -la /var/run/php/php-fpm.sock  # パスは環境による
# または
ls -la /run/gunicorn.sock
  

🔍 チェックポイント: ポートがLISTEN状態、またはソケットファイルが存在すること

ステップ4: nginx設定のupstream先を確認する

    sudo grep -r "proxy_pass\|fastcgi_pass" /etc/nginx/
  

🔍 チェックポイント: 設定のポート番号/ソケットパスがステップ3の結果と一致していること

ステップ5: ソケット権限を確認する(Unixソケット使用時)

    ls -la /var/run/php/php-fpm.sock
  

出力例:

    srw-rw---- 1 www-data www-data 0 Jan 12 10:00 /var/run/php/php-fpm.sock
  

🔍 チェックポイント: nginxの実行ユーザー(通常 www-data または nginx)がソケットにアクセスできる権限があること

ステップ6: nginx設定の文法を確認する

    sudo nginx -t
  

🔍 チェックポイント: syntax is oktest is successful が表示されること

ステップ7: タイムアウト設定を確認する(upstream timed outの場合)

    sudo grep -r "proxy_read_timeout\|proxy_connect_timeout\|fastcgi_read_timeout" /etc/nginx/
  

🔍 チェックポイント: デフォルトは60秒。処理に時間がかかる場合は値を増やす

NG行動(やってはいけないこと)

  • ログを見ずにnginxを再起動する - 原因が分からないまま再起動しても再発する
  • バックエンドの設定を変更後、再起動を忘れる - 設定変更は再起動まで反映されない
  • 本番環境で chmod 777 する - セキュリティリスクが高い。適切な権限設定を行う
  • SELinuxを無効化して解決とする - 根本対処ではない。ポリシー設定で対応する
  • タイムアウトを極端に長くする - 問題を隠蔽するだけ。バックエンドの処理を改善する

よくある質問(FAQ)

Q1: 突然502が出るようになった。何も変更していないのになぜ?

A: 以下を確認する:

  • バックエンドプロセスがメモリ不足でOOM Killerに停止させられた(dmesg | grep -i kill
  • ディスク容量不足でログが書けなくなった(df -h
  • バックエンドのワーカープロセス数が上限に達した

Q2: 特定のページだけ502になる

A: そのページの処理に時間がかかっている可能性がある:

  • バックエンドのアプリケーションログを確認
  • スロークエリやAPIタイムアウトを調査
  • proxy_read_timeout を一時的に延長して切り分け

Q3: 502と504の違いは?

A:

  • 502 Bad Gateway: バックエンドに接続できない、または不正な応答を受けた
  • 504 Gateway Timeout: バックエンドに接続はできたが、応答が時間内に返ってこなかった

関連するエラー・症状

  • (関連記事準備中)
  • (関連記事準備中)
  • (関連記事準備中)

解決しない場合

公式ドキュメント

確認すべきログファイル

    # nginx
/var/log/nginx/error.log
/var/log/nginx/access.log

# PHP-FPM
/var/log/php-fpm/error.log
/var/log/php8.2-fpm.log  # バージョンは環境による

# systemd
journalctl -u nginx
journalctl -u php-fpm
  

次に調べるキーワード

  • nginx upstream connection refused
  • nginx proxy_pass socket permission
  • php-fpm www.conf listen
  • nginx upstream timed out 110 connection timed out