2026年8月31日
2026年8月31日
NginxとPHP-FPMを連携してPHPを動かす設定方法(Ubuntu 24.04・RHEL系)
Nginx は PHP を自分では実行しません。PHP のリクエストを受けると、FastCGI という方式で PHP-FPM(PHP FastCGI Process Manager)に処理を渡し、返ってきた結果をブラウザへ返します。そのため、Nginx で PHP を動かすには PHP-FPM を入れ、Nginx の設定で「.php へのリクエストを PHP-FPM へ渡す」ことを書く必要があります。
この記事の手順は、2026年11月時点の Ubuntu 24.04(Nginx 1.24、PHP 8.3)で動作を確かめています。RHEL 系(AlmaLinux/Rocky Linux 9)での違いも後半で説明します。
Ubuntu/Debian で設定する
1. Nginx と PHP-FPM を入れる
sudo apt update
sudo apt install nginx php-fpm
php-fpm は、そのディストリビューションの標準の PHP バージョンの FPM を入れるパッケージです。Ubuntu 24.04 では php8.3-fpm が入ります。Debian など別のディストリビューションではバージョンが異なるので、次の手順で実際の名前を確かめます。
2. PHP-FPM のソケットを確かめる
Nginx から PHP-FPM へは、UNIX ドメインソケットというファイルを通じて接続します。ソケットのパスはバージョンによって変わるので、推測せずに確認してください。
ls /run/php/
grep '^listen =' /etc/php/*/fpm/pool.d/www.conf
systemctl status php8.3-fpm --no-pager
Ubuntu 24.04 では listen = /run/php/php8.3-fpm.sock です。この値を次の Nginx の設定で使います。
インターネット上の古い記事や、Ubuntu 24.04 の /etc/nginx/sites-available/default に残っているコメントには php7.4-fpm.sock と書かれていますが、PHP 7.4 は入っていないので、そのまま使うと 502 エラーになります。
3. Nginx の server ブロックを書く
サイト用の設定ファイルを作ります。
sudo nano /etc/nginx/sites-available/example.conf
server {
listen 80;
server_name example.com;
root /var/www/example;
index index.php index.html;
location / {
try_files $uri $uri/ =404;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php8.3-fpm.sock;
}
location ~ /\.ht {
deny all;
}
}
location ~ \.php$ が、.php で終わるリクエストを PHP-FPM へ渡す部分です。fastcgi_pass には手順2で確かめたソケットを書きます。
Ubuntu/Debian に入っている snippets/fastcgi-php.conf の中身は次のとおりです。
fastcgi_split_path_info ^(.+?\.php)(/.*)$;
try_files $fastcgi_script_name =404;
set $path_info $fastcgi_path_info;
fastcgi_param PATH_INFO $path_info;
fastcgi_index index.php;
include fastcgi.conf;
最後の fastcgi.conf に、PHP-FPM が実行するファイルを決める SCRIPT_FILENAME($document_root$fastcgi_script_name)が含まれています。そのため、このスニペットを読み込む場合、fastcgi_param SCRIPT_FILENAME や include fastcgi_params; を自分で書き足す必要はありません。
また、try_files $fastcgi_script_name =404; が「実在しない PHP ファイルは PHP-FPM へ渡さず 404 を返す」役割をしています。これにより、アップロードされた画像などに /x.php を付けたリクエストで PHP として実行させる、という古くから知られた手口も防げます。試したところ、/nope.php(存在しない)と /up.txt/x.php はどちらも 404 になりました。
location ~ /\.ht は、Apache 用の .htaccess などが残っていた場合に外から読まれないようにする設定です。
4. 有効にして反映する
sudo ln -s /etc/nginx/sites-available/example.conf /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
同じ 80 番で既定のサイト(/etc/nginx/sites-enabled/default)が動いている場合、server_name が一致しないアクセスは既定のサイトに届きます。不要なら sudo rm /etc/nginx/sites-enabled/default で無効にします。
PHP が動いているか確かめる
公開ディレクトリにテスト用のファイルを置きます。
sudo mkdir -p /var/www/example
echo '<?php echo "OK ", PHP_VERSION, " ", php_sapi_name();' | sudo tee /var/www/example/index.php
curl -H 'Host: example.com' http://127.0.0.1/
次のように表示されれば、PHP-FPM で実行されています(fpm-fcgi が PHP-FPM 経由で動いている印です)。
OK 8.3.6 fpm-fcgi
phpinfo() で詳しい設定を見ることもできますが、サーバーの情報を外部に見せてしまうので、確認が終わったらすぐ削除してください。
RHEL 系(AlmaLinux/Rocky Linux 9)での違い
RHEL 系では、php-fpm パッケージが Nginx 用の設定ファイルを一緒に置きます。
sudo dnf install nginx php-fpm
sudo systemctl enable --now php-fpm nginx
| 項目 | Ubuntu 24.04 | RHEL 系 9 |
|---|---|---|
| プール設定 | /etc/php/8.3/fpm/pool.d/www.conf |
/etc/php-fpm.d/www.conf |
| ソケット | /run/php/php8.3-fpm.sock |
/run/php-fpm/www.sock |
| 実行ユーザー | www-data |
apache |
| サービス名 | php8.3-fpm |
php-fpm |
| Nginx 用の設定 | 自分で書く(スニペットあり) | /etc/nginx/conf.d/php-fpm.conf と /etc/nginx/default.d/php.conf が入る |
/etc/nginx/conf.d/php-fpm.conf には upstream php-fpm として /run/php-fpm/www.sock が定義され、/etc/nginx/default.d/php.conf には .php を fastcgi_pass php-fpm; へ渡す location が書かれています。Nginx の標準の server ブロックは default.d/*.conf を読み込むので、追加の設定なしで PHP が動きます。自分で server ブロックを作る場合は、その中に include /etc/nginx/default.d/*.conf; を書くと同じ設定を使えます。
www.conf では listen.acl_users = apache,nginx によって nginx ユーザーもソケットに接続できるようになっています。SELinux が有効な環境で /var/www 以外を公開ディレクトリにする場合は、ファイルのラベルも合わせる必要があります。
PHP-FPM のプールを調整する
プール(www.conf)は、PHP を実行するプロセスの数や実行ユーザーを決めます。Ubuntu 24.04 の既定値は次のとおりです。
user = www-data
group = www-data
listen = /run/php/php8.3-fpm.sock
listen.owner = www-data
listen.group = www-data
pm = dynamic
pm.max_children = 5
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3
一番影響が大きいのは pm.max_children(同時に動かす PHP プロセスの上限)です。これを超える同時リクエストは待たされ、待ちが長いと Nginx がタイムアウトして 504 などを返します。逆に大きくしすぎると、メモリが足りなくなってサーバー全体が不安定になります。
目安は「PHP に使えるメモリ ÷ 1プロセスあたりのメモリ」です。1プロセスあたりのメモリは、実際に動かしている状態で確かめます。
ps -o rss= -C php-fpm8.3 | awk '{ s += $1; n++ } END { if (n) printf "%d procs, avg %.0f MB\n", n, s/n/1024 }'
たとえば PHP に 1GB 使えて、1プロセスが平均 60MB なら、pm.max_children は 15 前後が上限の目安になります。
設定を変えたら、構文を確かめてから再読み込みします。
sudo php-fpm8.3 -t
sudo systemctl reload php8.3-fpm
php.ini の設定(アップロードの上限など)は、PHP-FPM 用の /etc/php/8.3/fpm/php.ini を編集します。コマンドライン用の /etc/php/8.3/cli/php.ini を直しても Web には反映されません。
うまく動かないときの調べ方
まず Nginx のエラーログを見ます。
sudo tail -n 50 /var/log/nginx/error.log
sudo journalctl -u php8.3-fpm -n 50 --no-pager
| 症状 | ログの例 | 主な原因と対処 |
|---|---|---|
| 502 Bad Gateway | connect() to unix:/run/php/php8.3-fpm.sock failed (2: No such file or directory) |
PHP-FPM が止まっている、またはソケットのパスが違う。systemctl status と ls /run/php/ で確かめる |
| 502 Bad Gateway | connect() ... failed (13: Permission denied) |
ソケットの所有者と Nginx の実行ユーザーが合っていない。listen.owner/listen.group を確かめる |
| 「File not found.」と表示される(404) | Primary script unknown |
PHP-FPM に渡したファイルのパス(SCRIPT_FILENAME)が誤っている。スニペットを使わず独自に書いた設定で起きやすい。スニペットを使っていれば、root の誤りは Nginx 自身の 404 になる |
| PHP ファイルがダウンロードされる | なし | location ~ \.php$ が無い、または別の location が先に一致している |
| 504 Gateway Time-out | upstream timed out |
PHP の処理が長い、または pm.max_children が足りず待たされている |
試しに PHP-FPM を止めると、1行目の 502 とログが再現できます。原因の切り分けの練習にもなります。
502 の調べ方はNginxの502 Bad Gatewayを解決する方法、PHP-FPM 自体の設定はPHP-FPMのインストールと設定、WordPress を動かす場合の設定はNginxでWordPressを動かす設定でも扱っています。
まとめ
- Nginx は
.phpへのリクエストをfastcgi_passで PHP-FPM へ渡します - ソケットのパスは
ls /run/php/とwww.confのlistenで確かめ、古い記事のphp7.4-fpm.sockをそのまま使わないようにします - Ubuntu/Debian では
include snippets/fastcgi-php.conf;とfastcgi_passの2行で足り、SCRIPT_FILENAMEの追加は不要です - RHEL 系では php-fpm パッケージが Nginx 用の設定を置き、ソケットは
/run/php-fpm/www.sockです - 変更後は
nginx -tとphp-fpm8.3 -tで確かめてから再読み込みし、問題があればエラーログから原因を切り分けます