症状
nginx で proxy_pass を設定したが、バックエンドに転送されない、または 502 Bad Gateway が表示される。
結論:まずこれを確認
- バックエンドのプロセスが起動しているか確認する
proxy_passの URL 末尾のスラッシュ有無を確認する- nginx のエラーログ
/var/log/nginx/error.logを確認する
トラブルシューティングフロー
flowchart TD
A[proxy_pass が動かない] --> B{バックエンドは起動している?}
B -->|No| C[バックエンドを起動する]
B -->|Yes| D{nginx error.log にエラーあり?}
D -->|Connection refused| E[ポート番号を確認]
D -->|Permission denied| F[SELinux/権限を確認]
D -->|Timeout| G[バックエンドの応答を確認]
D -->|No error| H{ブラウザで直接アクセスできる?}
H -->|Yes| I[location ブロックの設定を確認]
H -->|No| J[ファイアウォールを確認]
よくある原因
- バックエンドが起動していない - プロセスが落ちている、ポートが Listen されていない
- proxy_pass の URL 末尾スラッシュ問題 - スラッシュの有無でパスの扱いが変わる
- ポート番号の間違い - バックエンドの Listen ポートと proxy_pass の指定が一致していない
- SELinux が接続をブロック - httpd_can_network_connect が無効
- upstream の名前解決失敗 - DNS や /etc/hosts の問題
- タイムアウト設定が短すぎる - バックエンドの応答より前に nginx が切断
- location ブロックのマッチ優先度 - 別の location が先にマッチしている
確認手順
ステップ1: バックエンドの起動状態を確認する
# バックエンドのポートが Listen されているか確認
ss -tlnp | grep :3000
# または
netstat -tlnp | grep :3000
🔍 チェックポイント: LISTEN 状態で対象ポートが表示されれば正常
# プロセスが起動しているか確認(例: Node.js)
ps aux | grep node
ステップ2: nginx のエラーログを確認する
# 最新のエラーを確認
sudo tail -50 /var/log/nginx/error.log
🔍 チェックポイント: 以下のエラーを探す
connect() failed (111: Connection refused)→ バックエンド未起動connect() failed (13: Permission denied)→ SELinuxupstream timed out→ タイムアウト
ステップ3: proxy_pass の URL 形式を確認する
# 末尾スラッシュなし - location のパスがそのまま転送される
location /api {
proxy_pass http://localhost:3000;
}
# /api/users → http://localhost:3000/api/users
# 末尾スラッシュあり - location のパスが置換される
location /api/ {
proxy_pass http://localhost:3000/;
}
# /api/users → http://localhost:3000/users
🔍 チェックポイント: バックエンドが期待するパスと一致しているか確認する
ステップ4: nginx の設定構文を確認する
# 構文チェック
sudo nginx -t
🔍 チェックポイント: syntax is ok と test is successful が表示されれば正常
# 設定を再読み込み
sudo nginx -s reload
ステップ5: curl でバックエンドに直接アクセスする
# nginx を経由せず直接確認
curl -v http://localhost:3000/
🔍 チェックポイント: 200 OK が返れば、バックエンド自体は正常
# nginx 経由で確認
curl -v http://localhost/api/
ステップ6: SELinux の状態を確認する(RHEL/CentOS系)
# SELinux の状態を確認
getenforce
🔍 チェックポイント: Enforcing の場合、ネットワーク接続がブロックされている可能性がある
# httpd のネットワーク接続を許可
sudo setsebool -P httpd_can_network_connect 1
ステップ7: ファイアウォールを確認する
# バックエンドポートがローカルからアクセス可能か確認
curl -v http://127.0.0.1:3000/
🔍 チェックポイント: localhost と 127.0.0.1 の両方で確認する
🚨 この結果が出たらヤバい
| 症状 | 意味 | 緊急度 |
|---|---|---|
Connection refused が繰り返し出る |
バックエンドが完全に停止している | 高 |
Too many open files |
ファイルディスクリプタ枯渇 | 高 |
upstream sent too big header |
バックエンドの応答ヘッダーが大きすぎる | 中 |
no live upstreams |
upstream 内の全サーバーが dead 扱い | 高 |
NG行動(やってはいけないこと)
- nginx を再起動せずに設定変更を期待する -
nginx -s reloadまたはsystemctl reload nginxが必要 - SELinux を無効化して放置する - 一時的な確認後は適切なポリシーを設定する
- エラーログを見ずに設定を変更し続ける - 原因特定が遅れる
- proxy_pass と location のスラッシュを適当に変更する - パスの扱いが変わり別の問題が発生する
よくある質問(FAQ)
Q1: upstream で複数サーバーを指定しているが、1台に偏る
A: デフォルトはラウンドロビン。weight パラメータや least_conn ディレクティブを確認する。バックエンドが落ちていると、生きているサーバーに集中する。
Q2: proxy_pass で WebSocket が動かない
A: Upgrade と Connection ヘッダーの転送が必要。以下を追加する:
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
Q3: 502 と 504 の違いは?
A: 502 はバックエンドに接続できない。504 は接続はできたが応答がタイムアウトした。
関連するエラー・症状
- (関連記事準備中)
- (関連記事準備中)
- (関連記事準備中)
解決しない場合
- nginx 公式ドキュメント - proxy_pass
- 確認すべきログファイル:
/var/log/nginx/error.log/var/log/nginx/access.log- バックエンドアプリケーションのログ
- 次に調べるキーワード:
nginx upstream connection refused,nginx proxy_pass path rewrite