実際に何が起きているのか
502はNginxがプロキシ先のバックエンド(Node.js、PHP-FPM、Gunicorn、またはその他のアプリサーバー)から不正または空のレスポンスを受け取ったことを意味します。Nginx自体は正常です。問題はアップストリーム側にあります。
実際には、ほぼ必ず以下の4つのいずれかが原因です:
- アップストリームサービスがクラッシュしているか、起動していない
- Nginx設定のアップストリームアドレスまたはポートが間違っている
- アップストリームが過負荷になりタイムアウトしている
- Unixソケットパスが存在しないか、パーミッションが正しくない
ステップ1 — Nginxエラーログを確認する
推測しないでください。まずここから始めましょう:
sudo tail -n 50 /var/log/nginx/error.log
以下のいずれかの行を探してください。それぞれ異なる修正方法を示しています:
# アップストリームが接続を拒否した
connect() failed (111: Connection refused) while connecting to upstream
# アップストリームがタイムアウトした
upstream timed out (110: Connection timed out) while reading response header
# Unixソケットが存在しない
connect() to unix:/run/php/php8.1-fpm.sock failed (2: No such file or directory)
ステップ2 — アップストリームサービスが動作しているか確認する
PHP-FPMの場合:
sudo systemctl status php8.1-fpm
Node.js(PM2)の場合:
pm2 list
pm2 logs
Gunicorn / Djangoの場合:
sudo systemctl status gunicorn
停止または失敗したサービスは再起動が必要です:
# PHP-FPM
sudo systemctl restart php8.1-fpm
# PM2 Node.js
pm2 restart all
# Gunicorn
sudo systemctl restart gunicorn
ページをリロードしてください。502が消えましたか?それで完了です。まだ表示される場合は読み続けてください。
ステップ3 — Nginx設定のプロキシアドレスを確認する
サイトの設定ファイルを開きます:
sudo nano /etc/nginx/sites-available/your-site
proxy_passまたはfastcgi_passの行を探します:
# Node.js — ポートはアプリが実際にリッスンしているものと一致させる
location / {
proxy_pass http://127.0.0.1:3000;
}
# PHP-FPM — ソケットパスはディスク上に存在する必要がある
location ~ \.php$ {
fastcgi_pass unix:/run/php/php8.1-fpm.sock;
}
アプリが実際に使用しているポートを確認します:
sudo ss -tlnp | grep LISTEN
出力例:
LISTEN 0 128 127.0.0.1:3000 ... users:(("node",pid=12345))
ポートが一致しない場合は、proxy_passを更新してNginxをリロードします:
sudo nginx -t && sudo systemctl reload nginx
ステップ4 — ソケットのパーミッションを修正する(PHP-FPM)
ソケットへのアクセスが拒否される場合は、オーナーシップが正しくありません。確認してください:
ls -la /run/php/php8.1-fpm.sock
ソケットはwww-data(またはNginxが実行しているユーザー)によって所有されている必要があります。PHP-FPMプール設定を開きます:
sudo nano /etc/php/8.1/fpm/pool.d/www.conf
以下の3行がNginxユーザーと一致している必要があります:
listen.owner = www-data
listen.group = www-data
listen.mode = 0660
PHP-FPMを再起動して適用します:
sudo systemctl restart php8.1-fpm
ステップ5 — アップストリームのタイムアウトに対処する
ログにupstream timed outと表示されている場合、アプリのレスポンスに時間がかかりすぎています。Nginxのサーバーブロックにタイムアウトディレクティブを追加してください:
location / {
proxy_pass http://127.0.0.1:3000;
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
}
保存後にリロードします:
sudo nginx -t && sudo systemctl reload nginx
これは時間を稼ぐ対処療法であり、根本的な解決策ではありません。アプリが常に遅い場合は、根本原因を調査してください。遅いデータベースクエリ、ブロッキングI/O、リソース枯渇がよくある原因です。
修正を確認する
- ブラウザでページをリロードします — 502が消えているはずです。
- curlで確認します:
curl -I https://yourdomain.com
HTTP/2 200はすべてが正常に動作していることを意味します。301や302もリダイレクトなので問題ありません。5xxでないレスポンスは、NginxがバックエンドへのトラフィックをS正常に転送していることを示します。
新たな問題が発生しないよう、しばらくエラーログを監視してください:
sudo tail -f /var/log/nginx/error.log
クイックリファレンス — 502の原因と修正
- Connection refused → アップストリームサービスがダウンしているため再起動する
- No such file or directory(ソケット)→ 設定のソケットパスが間違っているか、PHP-FPMが動作していない
- Permission denied(ソケット)→ プール設定の
listen.owner/listen.groupを修正する - Upstream timed out →
proxy_read_timeoutを増やし、アプリの遅い処理を調査する - ポートの不一致 →
proxy_passをアプリの実際のポートに合わせて更新する
最後に
502のほとんどは、Nginxがバックエンドに到達できないという一点に集約されます。ログファイルを見れば正確な原因がわかります — 確認を省略しないでください。
今後は、アップストリームサービスをsystemdまたはPM2で管理し、クラッシュ時に自動再起動されるようにしましょう。さらにUptimeRobotやBetter Stackなどの稼働監視(どちらも無料プランあり)と組み合わせることで、ユーザーよりも先に次の障害を検知できます。

