php-fpmでVirtualHostごとにuid/gidを変える
概要
Apache+CGIの環境ではsuExecで、実行するCGIプログラムのユーザIDを指定することができる。同様にphp-fpmにおいても、設定ファイルでuser/groupを指定すれば、ユーザID、グループIDを指定できる。これをVirtualHostごとにphp-fpmのユーザIDを指定できるようにする。
前提条件
WebサーバーにはApacheを使用。php-fpmが動作する設定は完了済みとする。
OSはFedora28を使用した。
修正方針
php-fpmにはPoolというものがあり、Pool単位で設定を変更することができる。デフォルトではwwwプールが一つだけ定義されており、Fedoraでは/etc/php-fpm.d/www.confに設定ファイルがある。修正の方針としては、VirtualHostごとにプールを作成し、各プールでユーザIDを指定するようにする。
手順
まずは、新しいプールを作成する(User:tomitaで実行するのでtomitaプールとする)。wwwプールをベースに作成すると楽なので/etc/php-fpm.d/www.confをコピーして作成する。
cp /etc/php-fpm.d/www.conf /etc/php-fpm.d/tomita.conf
tomita.confの修正箇所は以下のとおり。
- プール名を修正(ファイル先頭の[www]を[tomita]に変更)
- user/group設定を変更
- listen用socketファイルの名前を変更
- ログファイルの名前を変更
- session等のwork directoryを変更
注意が必要なのは、phpの実行ユーザがapacheではなく、一般ユーザ(tomita)になるので、デフォルトのログディレクトリ(/var/log/php-fpm)やsessionディレクトリ(/var/lib/php/session)に対して書き込み権限がない。このため、ユーザのホームディレクトリにこれらのディレクトリを作成し、そこを使うように設定する。ディレクトリの作成例は以下のとおり。
homeディレクトリ以下に作成する作業用ディレクトリ
/home/tomita/
.php-fpm/
log/ <-- logrotationをするように別途設定する必要がある
wsdlcache/
session/
opcache/
tomita.confの修正の差分例は以下のようになる。
# diff www.conf tomita.conf 4c4 < [www] --- > [tomita] 24c24 < user = apache --- > user = tomita 26c26 < group = apache --- > group = tomita 38c38 < listen = /run/php-fpm/www.sock --- > listen = /run/php-fpm/tomita.sock 319c319 < slowlog = /var/log/php-fpm/www-slow.log --- > slowlog = /home/tomita/.php-fpm/slow.log 413c413,414 < php_admin_value[error_log] = /var/log/php-fpm/www-error.log --- > php_flag[display_errors] = on > php_admin_value[error_log] = /home/tomita/.php-fpm/log/error.log 426,428c427,429 < php_value[session.save_path] = /var/lib/php/session < php_value[soap.wsdl_cache_dir] = /var/lib/php/wsdlcache < ;php_value[opcache.file_cache] = /var/lib/php/opcache --- > php_value[session.save_path] = /home/tomita/.php-fpm/session > php_value[soap.wsdl_cache_dir] = /home/tomita/.php-fpm/wsdlcache > ;php_value[opcache.file_cache] = /home/tomita/.php-fpm/opcache
新しいプールの定義は完了したので、設定を読み込む。
# systemctl reload php-fpm
設定が正常に反映されていれば、以下のようにtomitaプールのphp-fpmが指定したユーザ(以下の例ではtomita)で実行されている。
#1ps aux | grep php-fpm root 108635 0.0 0.2 327988 19684 ? Ss 8月29 0:00 php-fpm: master process (/etc/php-fpm.conf) tomita 110097 0.0 0.1 342524 11652 ? S 00:12 0:00 php-fpm: pool tomita <略> apache 110102 0.0 0.1 342524 11672 ? S 00:12 0:00 php-fpm: pool www <略>
今度はVirtualHostからtomitaプールを使うようにapacheの設定を修正する。
apacheのVirtualHost設定例
<VirtualHost *:80> ServerAdmin xxxx@xxxxxx DocumentRoot /var/www/html.foo ServerName foo.xxxx ErrorLog logs/foo-error_log CustomLog logs/foo-access_log combined AddDefaultCharset Off # tomitaプールのsocketファイルを指定 <FilesMatch \.(php|phar)$> SetHandler "proxy:unix:/run/php-fpm/tomita.sock|fcgi://localhost" </FilesMatch> </VirtualHost>
上記設定で、foo.xxxx仮想ホストにアクセス時はtomitaプールのphp-fpmを使用するようになり、tomitaユーザでphpスクリプトが実行されることになる。
これをVirtualHost毎に設定すれば、各VirtualHostで異るUID/GIDでphpを実行できる。SetHandlerを指定していないVirtualHostではデフォルト設定のwwwプールが使用される。
最後にapacheの設定を再読み込みするのを忘れずに。
# systemctl reload httpd
注意点
プールごとに待機プロセスが作成されるため、プールをあまり増やしすぎるとメモリが少ないサーバーでは厳しくなるかもしれない。