2026年5月17日

2026年5月17日

502 Bad Gateway(Nginx)の原因と直し方|エラーログで切り分け、PHP-FPM の停止・ソケット・タイムアウトを順に確認

Nginx の 502 Bad Gateway は、Nginx が処理を渡した先(アップストリーム)から正しい応答を受け取れなかったときに返されます。WordPress では、渡す先はほとんどの場合 PHP-FPM です。つまり 502 は「Nginx は動いているが、PHP-FPM との間で問題が起きている」という合図です。

この記事では、エラーログのメッセージから原因を見分け、順に直す手順を説明します。パスやバージョンは2026年10月時点の Ubuntu 24.04(PHP 8.3)を例にしています。Debian 12 なら PHP 8.2 になるので、8.3 の部分を読み替えてください。

502と504の違い

ステータス 意味 WordPress での主な原因
502 Bad Gateway PHP-FPM に接続できない、または応答が途中で切れた PHP-FPM が停止している、ソケットのパス違い・権限、ワーカーの強制終了
504 Gateway Timeout PHP-FPM に接続できたが、応答が時間内に返らなかった 重い処理、fastcgi_read_timeout の不足

504 の場合は、タイムアウトの設定を見直します(Nginxのタイムアウト設定を参照)。以下は 502 の調べ方です。

1. Nginxのエラーログを確認する

最初に、Nginx のエラーログで具体的なメッセージを確認します。

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

サイトごとに error_log を設定している場合は、その設定のファイルを見ます。502 のときに出る主なメッセージと原因は次のとおりです。

メッセージ(抜粋) 原因 見る項目
connect() to unix:/run/php/php8.3-fpm.sock failed (2: No such file or directory) PHP-FPM が動いていない、またはソケットのパスが違う 2・3
connect() to unix:... failed (13: Permission denied) Nginx のユーザーがソケットに接続する権限を持っていない 4
connect() failed (111: Connection refused) TCP(127.0.0.1:9000 など)で待ち受けているはずの PHP-FPM がいない 2・3
connect() to unix:... failed (11: Resource temporarily unavailable) ワーカーがすべて使用中で、接続の待ち行列もあふれている 5
upstream prematurely closed connection while reading response header from upstream PHP-FPM のワーカーが処理の途中で終了した 6
upstream sent too big header while reading response header from upstream PHP が返したヘッダーが Nginx のバッファーより大きい 7

2. PHP-FPMが動いているか確認する

# サービスの状態
sudo systemctl status php8.3-fpm

# インストールされている PHP のバージョンと、ソケットの有無
ls /etc/php/
ls -l /run/php/

停止していれば起動し、起動に失敗する場合は設定の誤りを確認します。

sudo php-fpm8.3 -t
sudo systemctl start php8.3-fpm
sudo journalctl -u php8.3-fpm -n 50

PHP のバージョンを上げたあとに 502 になった場合は、古いバージョン(たとえば php8.1-fpm)のソケットを指したままになっていることがよくあります。

3. fastcgi_passのソケットのパスを合わせる

Nginx の fastcgi_pass と、PHP-FPM のプール設定の listen が同じ場所を指している必要があります。

# PHP-FPM が待ち受けている場所
grep -E "^listen" /etc/php/8.3/fpm/pool.d/www.conf

# Nginx が接続しに行く場所
sudo grep -rn "fastcgi_pass" /etc/nginx/sites-enabled/ /etc/nginx/conf.d/

WordPress 用の Nginx の設定は、PHP ファイル(.php で終わるリクエスト)だけを PHP-FPM に渡し、それ以外は try_files で静的ファイルか index.php に振り分けます。location / の中で fastcgi_pass を書くと、画像や CSS まで PHP-FPM に渡され、正しく動きません。

server {
    listen 80;
    server_name example.com;
    root /var/www/html;
    index index.php index.html;

    location / {
        try_files $uri $uri/ /index.php?$args;
    }

    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/run/php/php8.3-fpm.sock;
    }
}

snippets/fastcgi-php.conf は Debian・Ubuntu の Nginx パッケージに含まれるファイルで、SCRIPT_FILENAME などの設定と、存在しない PHP ファイルを 404 にする処理が入っています。RHEL 系(AlmaLinux・Rocky Linux など)では既定のソケットが /run/php-fpm/www.sock で、このファイルは無いため、fastcgi_params を読み込んで SCRIPT_FILENAME を自分で設定します。

4. ソケットの権限を確認する

ソケットに接続できるのは、PHP-FPM のプール設定の listen.owner・listen.group・listen.mode で許可されたユーザーです。Ubuntu の既定は次のとおりで、Nginx の実行ユーザー www-data が接続できます。

; /etc/php/8.3/fpm/pool.d/www.conf
listen = /run/php/php8.3-fpm.sock
listen.owner = www-data
listen.group = www-data
listen.mode = 0660

Nginx の実行ユーザー(/etc/nginx/nginx.conf の user)を変えている場合は、そのユーザーが接続できるように listen.owner・listen.group を合わせます。

grep -E "^user" /etc/nginx/nginx.conf
ls -l /run/php/php8.3-fpm.sock

5. ワーカーが足りているか確認する

PHP-FPM が同時に処理できるリクエストの数は pm.max_children が上限です。Ubuntu の既定値は 5 で、アクセスが多いサイトや遅い処理があるサイトではすぐに足りなくなります。上限に達すると、PHP-FPM のログに次のように記録されます。

sudo grep "max_children" /var/log/php8.3-fpm.log | tail -n 5
# 例: WARNING: [pool www] server reached pm.max_children setting (5), consider raising it

pm.max_children は、メモリーに収まる範囲で決めます。1ワーカーの平均のメモリー使用量を調べ、「PHP-FPM に使えるメモリー ÷ 1ワーカーの使用量」を目安にします。

ps --no-headers -o rss -C php-fpm8.3 | awk '{s+=$1; n++} END {printf "%.0f MB\n", s/n/1024}'
; /etc/php/8.3/fpm/pool.d/www.conf(メモリー 2GB 程度を PHP-FPM に使える場合の例)
pm = dynamic
pm.max_children = 20
pm.start_servers = 4
pm.min_spare_servers = 2
pm.max_spare_servers = 6
pm.max_requests = 500

メモリーを超える値にするとスワップが増え、かえって遅くなります。ワーカーを増やす前に、ページキャッシュで PHP まで届くリクエストを減らすことも検討してください。

6. ワーカーが途中で終了していないか確認する

upstream prematurely closed connection は、PHP-FPM のワーカーが応答を返す前に終了したことを示します。PHP-FPM のログとカーネルのログで理由を確認します。

sudo tail -n 50 /var/log/php8.3-fpm.log
sudo journalctl -k | grep -i -E "oom|killed process" | tail -n 5
ログの内容 原因と対処
execution timed out (… sec), terminating request_terminate_timeout の秒数を超えたため、PHP-FPM がワーカーを強制終了した
exited on signal 11 (SIGSEGV) PHP の拡張モジュールなどが異常終了した。直前に入れた拡張・プラグインを確認する
カーネルのログに Out of memory: Killed process メモリー不足で OS がワーカーを終了させた。pm.max_children を減らすかメモリーを増やす

request_terminate_timeout は、1つのリクエストの処理時間の上限です。既定値は 0(無効)で、設定すると時間制限が加わり、超えた処理は 502 で終わります。延長する設定ではない点に注意してください。設定する場合は、PHP の max_execution_time 以上の値にします。

; /etc/php/8.3/fpm/pool.d/www.conf
; 0 なら無効(既定)。設定するなら max_execution_time 以上にする
request_terminate_timeout = 300

7. ヘッダーが大きすぎる場合

upstream sent too big header は、PHP が返した応答ヘッダー(Cookie が多い、長いリダイレクト先など)が、Nginx のバッファーに収まらないときに出ます。PHP を渡している location でバッファーを大きくします。

location ~ \.php$ {
    include snippets/fastcgi-php.conf;
    fastcgi_pass unix:/run/php/php8.3-fpm.sock;
    fastcgi_buffer_size 32k;
    fastcgi_buffers 16 16k;
}

8. 設定を確認して反映する

設定を変えたら、構文を確認してから反映します。reload なら処理中の接続を切らずに設定を読み直せます。

sudo php-fpm8.3 -t && sudo systemctl reload php8.3-fpm
sudo nginx -t && sudo systemctl reload nginx

反映後、ブラウザでページを開くか、次のコマンドでステータスコードを確認します。

curl -s -o /dev/null -w "%{http_code}\n" https://example.com/

まとめ

  • 502 は Nginx と PHP-FPM の間の問題。まず /var/log/nginx/error.log のメッセージで原因を見分ける
  • No such file or directory・Connection refused は PHP-FPM の停止か fastcgi_pass のパス違い。PHP のバージョンを上げたあとに多い
  • Permission denied は listen.owner・listen.group・listen.mode と Nginx の実行ユーザーを合わせる
  • server reached pm.max_children が出ていれば、メモリーの範囲で pm.max_children を増やす
  • upstream prematurely closed connection はワーカーの終了。request_terminate_timeout(設定すると制限になる)やメモリー不足を確認する
  • PHP は location ~ \.php$ だけで PHP-FPM に渡し、location / では try_files を使う

関連記事:

お気軽にご相談ください

お見積りへ お問い合わせへ
▲