概要
タイトル通り。Webサーバー上で PHP-FPM で動的サイトを構築したかったので。
環境
- Ubuntu 24.04
- nginx/1.28.0
- php8.1-fpm (ondrej/php)
# nginx/1.28.0
nginx -v
nginx version: nginx/1.28.0
# php8.1-fpm がインストールされている
sudo dpkg -l php*-fpm | grep '^ii'
ii php8.1-fpm 8.1.33-1+ubuntu24.04.1+deb.sury.org+1 amd64 server-side, HTML-embedded scripting language (FPM-CGI binary)
前提
Nginx のインストールは以下の筆者別記事にて実施済み:
( 公式の手順に沿って、バイナリをインストール )
方法
前提
-
PHPのマニュアル に Nginx 1.4.x の方法が書いてある。1.28.0 に読み替える必要がある。
-
また、上記マニュアルではすべてのバイナリと設定は
/usr/local/nginxにあると想定されている。が、以下の点を読み替える。-
実際確認するとバイナリは
/usr/sbin/nginxにあった。 -
設定 (
nginx.conf) は/etc/nginx/nginx.conf。.bash# nginx ( バイナリインストール ) の場所を検索 which nginx /usr/sbin/nginx # 設定ファイルの場所を検索 sudo find / -path *nginx.conf* [sudo] password for xxx: find: ‘/proc/117753/task/117753/net’: Invalid argument find: ‘/proc/117753/net’: Invalid argument /etc/nginx/nginx.conf # <-- Here find: ‘/run/user/1000/gvfs’: Permission denied find: ‘/run/user/1000/doc’: Permission denied /var/lib/dpkg/info/nginx.conffiles
-
What added since Nginx 1.5.x so far
今回は CHANGELOG を見て、"HTTP", " port " などで検索し、関係ありそうな変更点は、その点をマニュアルで読み替える。変更の詳細は、GitHub を確認する。
"HTTP" でヒットした変更点
- 1.9.4 の sub_filter ディレクティブ のバグが 1.9.5 で修正。→PHPのマニュアル で言及なし
- postpone_output ディレクティブ の変更 ( 1.7.8 ) → 同じく、言及なし
" port " でヒットした変更点
-
mail proxy ( Eメールのプロキシ ), ngx_http_realip_module, proxy_bind, fastcgi_bind, memcached_bind, scgi_bind , and uwsgi_bind ディレクティブの機能追加 ( 1.27.3 など) → 同じく、言及なし
-
listen ディレクティブ の機能追加 :
Changes with nginx 1.5.10
Feature: port ranges in the "listen" directive.→ ポート範囲を指定する場合 は、注意が必要 ( ただし PHPのマニュアル で言及なし)
→ 下記、注意が必要。
Changes with nginx 1.23.4
Bugfix: port ranges in the "listen" directive did not work; the bug
had appeared in 1.23.3.
Thanks to Valentin Bartenev.
設定手順
公式の手順に沿って進めていきます。
事前準備
設定ファイルを取得し、正しい場所に移動します。
php.ini:
# php.ini 設定ファイルのパスを検索
sudo find / -path *php.ini-*
[sudo] password for xxx:
/usr/lib/php/8.1/php.ini-production.cli
/usr/lib/php/8.1/php.ini-production
/usr/lib/php/8.1/php.ini-development # <-- Here
.....
# php.ini 設定ファイルをコピー
sudo cp /usr/lib/php/8.1/php.ini-development /usr/local/php/php.ini
コピーした php.ini の以下の設定を追加。
ファイルが存在しなかったときは、Nginx が PHP-FPM バックエンドに、 リクエストを渡さないようにし、任意のスクリプトの挿入を防げるようにする
; cgi.fix_pathinfo provides *real* PATH_INFO/PATH_TRANSLATED support for CGI.
cgi.fix_pathinfo=0
【任意】「コピー先のディレクトリがない」と、怒られる場合。
sudo cp /usr/lib/php/8.1/php.ini-development /usr/local/php/php.ini
cp: cannot create regular file '/usr/local/php/php.ini': No such file or directory
# 【任意】コピー先のディレクトリを作成
sudo mkdir -p /usr/local/php
php-fpm の設定ファイル
ppa の php8.1-fpm を使用しているためか、設定ファイルのパスが違いました:
# php-fpm 設定ファイルのパスを検索
sudo find / -path *fpm*conf*
/usr/lib/tmpfiles.d/php8.1-fpm.conf
find: ‘/proc/117753/task/117753/net’: Invalid argument
find: ‘/proc/117753/net’: Invalid argument
/etc/apache2/conf-available/php8.1-fpm.conf
/etc/php/8.1/fpm/pool.d/www.conf # <-- Here
/etc/php/8.1/fpm/conf.d
/etc/php/8.1/fpm/conf.d/20-readline.ini
.....
...
/etc/php/8.1/fpm/conf.d/20-sysvmsg.ini
/etc/php/8.1/fpm/conf.d/20-ftp.ini
/etc/php/8.1/fpm/php-fpm.conf
find: ‘/run/user/1000/gvfs’: Permission denied
find: ‘/run/user/1000/doc’: Permission denied
/var/lib/dpkg/info/php8.1-fpm.conffiles
今回のように、ondrej/php から php8.1-fpm をインストールした場合、 /etc/php/8.1/fpm/pool.d/www.conf だと思われます。
PHPのマニュアルは古いせいか、www.conf.default をコピー元として www.conf というファイルを作っています。が、手元の私の環境では、www.conf がすでにあるので、逆にその www.conf を元に www.conf.default を作成することにします。
www.conf.default の存在理由は不明ですが。
# www.conf.default ファイルを作成 ( www.conf をコピー )
sudo cp /etc/php/8.1/fpm/pool.d/www.conf /etc/php/8.1/fpm/pool.d/www.conf.default
php-fpm の設定
まず www.conf の設定。
サービスを開始する前に、php-fpm が www-data ユーザーと www-data グループで 必ず実行されるように (中略)
sudo vim /etc/php/8.1/fpm/pool.d/www.conf
以下の部分を探し、修正します:
[www]
; Unix user/group of the child processes. This can be used only if the master
; process running user is root. It is set after the child process is created.
; The user and group can be specified either by their name or by their numeric
; IDs.
; Note: If the user is root, the executable needs to be started with
; --allow-to-run-as-root option to work.
; Default Values: The user is set to master process running user by default.
; If the group is not set, the user's group is used.
user = nginx
group = nginx
; Set permissions for unix socket, if one is used. In Linux, read/write
; permissions must be set in order to allow connections from a web server. Many
; BSD-derived systems allow connections regardless of permissions. The owner
; and group can be specified either by name or by their numeric IDs.
; Default Values: Owner is set to the master process running user. If the group
; is not set, the owner's group is used. Mode is set to 0660.
listen = /run/php/php8.1-fpm.sock
listen.owner = nginx
listen.group = nginx
+ listen.mode = 0660
;listen.allowed_clients = 127.0.0.1
+ slowlog = /var/log/php-fpm.log.slow
+ php_flag[display_errors] = off
+ php_admin_value[error_log] = /var/log/php-fpm.www-error.log
+ php_admin_flag[log_errors] = on
; The timeout for serving a single request after which a PHP backtrace will be
; dumped to the 'slowlog' file. A value of '0s' means 'off'.
; Available units: s(econds)(default), m(inutes), h(ours), or d(ays)
; Default Value: 0
;request_slowlog_timeout = 0
+ request_slowlog_timeout = 5s
# www-dataユーザー、 www-data グループが所有者になっている
ls -ld /run/php/php8.1-fpm.sock
srw-rw---- 1 nginx nginx 0 Oct 13 15:14 /run/php/php8.1-fpm.sock
| ディレクティブ | 説明 | 設定値 | 備考 |
|---|---|---|---|
user, group
|
Unix ユーザー/グループ (子プロセス) | nginx |
|
listen |
FastCGI へのリクエストを受け付けるアドレス |
listen = <unixsocket> で Unix ソケットのパスを指定。 |
|
listen.owner, listen.group
|
読み取り、および書き込み権限 を持つ Unix ソケットファイルの所有者とグループ | nginx |
|
listen.mode |
Unix ソケットの読み取り・書き込み権限を Webサーバーへの接続に対して許可する | 0660 |
|
listen.allowed_clients |
接続が許可されている FastCGI クライアントの IPv4 or IPv6 アドレス のリスト | default: any | TCP ソケットの場合のみ有効 |
slowlog |
スローリクエストのログファイルパス | /var/log/php-fpm.log.slow |
|
request_slowlog_timeout |
リクエストを処理する際のタイムアウト。この時間を過ぎると PHP のバックトレースが 'slowlog' ファイルに出力される | 5s |
Default Value: 0 ( = 'off' ) |
php_admin_value[error_log] |
PHP エラーログファイルパス | /var/log/php-fpm.www-error.log |
|
php_admin_flag[log_errors] |
PHP エラーログを有効にする | on |
www.conf のディレクティブは以下を参考.
ログファイルの権限:
# スローリクエストのログファイル
ls -ld /var/log/php-fpm.log.slow
-rwxrwxr-x 1 nginx nginx 0 Oct 11 11:35 /var/log/php-fpm.log.slow
# PHP エラーログファイル
ls -ld /var/log/php-fpm.www-error.log
-rwxrwxr-x 1 nginx nginx 0 Oct 11 11:36 /var/log/php-fpm.www-error.log
次に php-fpm.conf の設定。以下は初期値のまま:
include=/etc/php/8.1/fpm/pool.d/*.conf
[global]
; Pid file
; Note: the default prefix is /var
; Default Value: none
; Warning: if you change the value here, you need to modify systemd
; service PIDFile= setting to match the value here.
pid = /run/php/php8.1-fpm.pid
-
pid:PID ファイルのパス
/etc/php-fpm.d/*.conf の概要
このディレクトリには、PHP-FPM の設定を分割して管理するための設定ファイルが「プール」単位で格納されています。デフォルトでは、www.confというプール設定ファイルが生成されています。
参考:
PHP-FPMの「プール」機能
- プール単位でプロセス管理が可能。
- アプリケーションごとにプールを分けて資源を最適化。
- 主な構成要素:
- マスター・プロセス:設定読み込みと管理
- ワーカープロセス:PHPスクリプトの実行
- リスナー(ソケット):Webサーバーとの通信
php-fpm サービスを起動:
ここまで来れば、php-fpm サービスを開始できます:
/usr/local/bin/php-fpm
実際は、PHPマニュアルとは 違いますので注意。
ondrej/php から php-fpm をインストールしていれば、単にそれが動いていれば OK
# 起動状態を確認。
sudo systemctl status php8.1-fpm
● php8.1-fpm.service - The PHP 8.1 FastCGI Process Manager
Loaded: loaded (/usr/lib/systemd/system/php8.1-fpm.service; enabled; preset: enabled)
Active: active (running) since Thu 2025-10-09 19:39:52 JST; 24h ago
# 起動していなければ.
sudo systemctl start php8.1-fpm
php-fpm のバイナリのコピー・実行は不要
# php-fpm のバイナリのパスを検索。
which php-fpm8.1
/usr/sbin/php-fpm8.1
# 上記のファイルをコピー
sudo cp /usr/sbin/php-fpm8.1 /usr/local/bin/php-fpm
このように、もし間違えて、PHP マニュアル通りに php-fpm サービスを呼び出すと、エラーになります:
sudo /usr/local/bin/php-fpm
[10-Oct-2025 20:13:51] ERROR: Another FPM instance seems to already listen on /run/php/php8.1-fpm.sock
[10-Oct-2025 20:13:51] ERROR: FPM initialization failed
nginx の設定
Nginx が PHP アプリケーションの実行をサポートするように設定しなければなりません。
下のnginx.conf で追加した要素についてはあとで説明します。とりあえず全行 :
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log debug;
pid /run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
#gzip on;
include /etc/nginx/conf.d/*.conf;
server {
listen 80;
root /usr/share/nginx/html;
server_name localhost;
location / {
index index.php index.html index.htm;
try_files $uri $uri/ /index.php;
}
location ~* \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+?\.php)(/.+)?$;
# NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini
fastcgi_index index.php;
fastcgi_pass unix:/run/php/php8.1-fpm.sock;
# fastcgi_pass localhost:9000;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME /usr/share/nginx/html$fastcgi_script_name;
fastcgi_param SCRIPT_NAME $fastcgi_script_name;
}
}
}
# nginx を再起動
sudo /usr/sbin/nginx -s stop
sudo systemctl start nginx
# テスト用 PHP ファイル を作成。
echo "<?php phpinfo(); ?>" | sudo tee /usr/share/nginx/html/index.php > /dev/null
# index.html を削除
sudo rm /usr/share/nginx/html/index.html
ドキュメントルートの所有者(nginx) と権限 ( ディレクトリは 755, ファイルは 644 )
# 所有者とグループを nginx に。
sudo chown -R nginx:nginx /usr/share/nginx/html
# ドキュメントルートのディレクトリは 755に、
sudo find /usr/share/nginx/html -type d -exec chmod 755 {} +
# ファイルは 644 に設定する
sudo find /usr/share/nginx/html -type f -exec chmod 644 {} +
# 権限・所有者・グループ確認 (ディレクトリ)
ls -ld /usr/share/nginx/html
drwxr-xr-x 2 nginx nginx 4096 Oct 11 21:12 /usr/share/nginx/html
# 同 (ファイル)
ls -al /usr/share/nginx/html
total 16
drwxr-xr-x 2 nginx nginx 4096 Oct 11 21:12 .
drwxr-xr-x 3 root root 4096 Oct 9 17:04 ..
-rw-r--r-- 1 nginx nginx 497 Apr 23 20:48 50x.html
-rw-r--r-- 1 nginx nginx 20 Oct 11 08:53 index.php
default.conf の設定と server_name が被るので、デフォルトの設定ファイルを無効化しておく。
# デフォルトの設定ファイルを無効化
sudo mv /etc/nginx/conf.d/default.conf /etc/nginx/conf.d/default._conf
# 設定ファイルのテスト
sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
# 設定ファイルの再読み込み
sudo nginx -s reload
# nginx と php-fpm を再起動
sudo systemctl restart nginx && sudo systemctl restart php8.1-fpm
トラブルシューティング (nginxの設定)
-
ドキュメントルートの
index.phpの URI にWebブラウザでアクセスすると、index.php ファイルがダウンロードされる場合:nginx.conflocation ~* \.php$ { + try_files $uri =404; + fastcgi_split_path_info ^(.+?\.php)(/.+)?$; # NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini設定内容はあまり理解できていないが、とりあえずリンクを貼っておく:
-
nginx -tすると、nginx: [warn] conflicting server name "localhost" on 0.0.0.0:80, ignoredになる場合:上にも書いたが、以下を実行。
.bash# デフォルトの設定ファイルを無効化 sudo mv /etc/nginx/conf.d/default.conf /etc/nginx/conf.d/default._conf
参考
nginx.conf の説明
実際に追加したのは、以下の要素 ( server ディレクティブのコンテキスト) :
| コンテキスト | 説明 | 設定値 |
|---|---|---|
| listen | 80 | |
| root | サイトのルートディレクトリ | /usr/share/nginx/html |
| location の index | ブラウザ等からlocalhost などに "/" だけを付けた URI にアクセスした場合、root のディレクトリに指定したファイルが存在するかを調べる。そしてマッチしたファイルにリダイレクトする。 |
index.php index.html index.htm |
| location の try_files |
$uri あるいは $uri/ を探す。なければ /index.php を探す |
$uri $uri/ /index.php |
2つ目のlocation の fastcgi_index, fastcgi_param SCRIPT_FILENAME
|
/の URI にアクセスしたときに返すファイル |
index.php, /usr/share/nginx/html$fastcgi_script_name
|
fastcgi_param SCRIPT_NAME |
同上 | $fastcgi_script_name |
fastcgi_pass |
php-fpm のUnix ソケットのパス | unix:/run/php/php8.1-fpm.sock |
ログの設定
- ログレベルを
debugに変更:
| ディレクティブ | 説明 | 設定値 |
|---|---|---|
| error_log | エラーログのパスとログのレベル | /var/log/nginx/error.log debug |
参考: A simple PHP site configuration の例
Fast CGI パラメータの読み込み
-
include fastcgi_paramsで/etc/nginx/fastcgi_paramsを読み込む。 - その下の行で、
fastcgi_param SCRIPT_FILENAMEなど、上記のfastcgi_paramsファイルを上書きしたい値を設定する。(逆にすると、nginx.conf が上書きされてしまい、効果がなくなるので注意)
設定にてこずってQiitaは後から書いたので、listen とかは追加したかもとからあったか、うろおぼえですが。あと、バックアップしてなかったので。
なお、セミコロン (";" ) が文末に必要なので注意。
注意
/usr/share/nginx/html/index.html は削除してください。location の index コンテキストに影響します。
sudo rm /usr/share/nginx/html/index.html
上記のように設定した index コンテキストだと、リクエストされた root のディレクトリのファイルに対して、index.html がなかった場合に、index.php にマッチング します。
つまり、PHP の動的サイトを作る場合は、index.html を削除し、index.php だけを作成 する、という事になります。
http://localhost/index.php にアクセスします:
