長年PHPと付き合ってきて動作モードが3つあることは知ってたが、なんとなくだったので自分用にまとめてみた。以下のサンプルでのOSはCentOS系。
モジュール版
一番簡単な方法。Apacheのconfで LoadModule php7_module modules/libphp7.so
として読み込む方法。一番最初にPHP使った時はローカル環境でApache立ててモジュール版PHPを動かしていたような気がする。
メリット
- 動作が早い。Apacheと同じプロセスなので
デメリット
今、これ動かすなら普通に apt-get php
とかすればいいのかな?簡単なので、起動方法は省略。
PHP-FPM(FastCGI Process Manager )版
CGIなんだけど、一般的なmod_cgiのようにリクエストごとにプロセスを増やすのではなくCGIサーバとして1つのプロセスを常駐させておいてApacheはそのプロセスに橋渡しをする。
メリット
デメリット
- DAEMONを2つ用意しないといけない。
意外とデメリットがそれほどでもないので、開発者用にPHP提供するならPHP-FPMが一番よさげ。
設定
インストール
PHPの違うバージョンはremiリポジトリを使う。remiリポジトリの導入は省略。
# yum install -y php74-php-fpm
これをDEAMONとして起動&自動起動する。
# systemctl enable php74-php-fpm # systemctl start php74-php-fpm
設定
PHP-FPM
プロセスの設定ディレクトリは以下になる。PHP7.4の場合
/etc/opt/remi/php74/php-fpm.d/
ここに起動させたいプロセス分だけ設定ファイルを ****.conf
とかで設置する。 /etc/opt/remi/php74/php-fpm.d/t-ito.conf
とか。
基本的には、そこに www.confがあるのでそれをコピーして以下の項目を変更する。
# なんとなく設定セグメント [t-ito] # プロセスに接続するソケットファイル、Apacheの設定で使う。 listen = /var/opt/remi/php74/run/php-fpm/t-ito.sock # プロセスを実行するユーザ user = t-ito # プロセスを実行するグループ group = wheel
設定したら、PHP-FPM再起動
# systemctl restart php74-php-fpm
Apache
PHP拡張子はPHP-FPMのソケットにつなぎに行くようにする。
<Directory "/var/www/demo/htdocs"> <FilesMatch \.(php|phar)$> SetHandler "proxy:unix:/var/opt/remi/php74/run/php-fpm/t-ito.sock|fcgi://localhost" </FilesMatch> </Directory>
CGI + suExec (SuexecUserGroupの場合 )
普通にPerlとかのCGIと同じように動かす。ただし、なんやしらんけど、行頭の #!/usr/bin/php
みたいなのは要らない。
で、それだとApache権限で動作するんだけど、それだけでなく、suExecでプログラムの実行ユーザも変更してくれる。
UserDir 方式だと、ファイルオーナーの権限で動作し、SuexecUserGroup方式だとSuexecUserGroupオプションで指定されているユーザ・グループの権限で動作する。
メリット
- ユーザーごとの権限で動作するので、ほかのディレクトリに侵入できない(レンタルサーバーとかの共有サーバーで優位)
- ディレクトリパーミションを777にしなくてもどんどん<?php mkdir() ; ?> とかできる。
デメリット
設定
環境
/usr/sbin/suexec -V
コマンドを実行すると以下のように出る。この値はsuexecコマンドをコンパイルした時点で決まるので、後から変更できない(らしい)。
-D AP_DOC_ROOT="/var/www" -D AP_GID_MIN=1000 -D AP_HTTPD_USER="apache" -D AP_LOG_SYSLOG -D AP_SAFE_PATH="/usr/local/bin:/usr/bin:/bin" -D AP_UID_MIN=1000 -D AP_USERDIR_SUFFIX="public_html"
設定
ということで設定。
インストール
CGIプログラム /opt/remi/php74/root/bin/php-cgi
が欲しいからこれが入るようなパッケージを導入。php-fpmあたりに入ってるのかな?
#yum install -y php74-php-fpm
PHPのCGI実行プログラム
これをDocumentRoot内にコピーする。remiリポジトリでPHPを入れると /opt/remi/php74/root/bin/php-cgi
とかにあるので、
# cp /opt/remi/php74/root/bin/php-cgi /var/www/demo/php74-cgi # chown t-ito:wheel /var/www/demo/php74-cgi
とかにコピーしてオーナーチェンジする。
ApacheのCGI設定
ScriptAlias /php-cgi /var/www/demo/php74-cgi
で、/php-cgi にアクセスした場合に/var/www/demo/php74-cgiを実行するようにする。 *1-
Options ExecCGI
でCGIが実行できるようにする。 -
AddHandler php-cgi .php
でphp拡張子のファイルに対してphp-cgiというactionを関連付ける。 -
Action php-cgi /php-cgi
でphp-cgiというActionに対して/php-cgiというスクリプトを関連付ける。 SuexecUserGroup
でCGI実行ユーザー・グループ権限を設定SuexecUserGroup ユーザー名 グループ名
(( UserDirを使う場合は、各ユーザーのWebRootディレクトリをAP_USERDIR_SUFFIXに合わす。t-itoユーザーなら/home/t-ito/public_html
以下。…らしい ))
で、これらをサーバ設定ファイルとバーチャルホスト /etc/httpd/conf.d/demo.conf
で設定する。
<VirtualHost *:80> ServerName demo.example.ne.jp DocumentRoot "/var/www/demo/htdocs-suexec" ScriptAlias /php-cgi /var/www/demo/php74-cgi SuexecUserGroup t-ito wheel <Directory "/var/www/demo/htdocs-suexec"> Options FollowSymLinks ExecCGI AllowOverride All AddHandler php-cgi .php Action php-cgi /php-cgi </Directory> ErrorLog /var/www/demo/logs/xxx_error_log CustomLog /var/www/demo/logs/xxx_access_log combined </VirtualHost>
PHPファイルを設置
で、/var/www/demo/htdocs-suexec/phpinfo.php
に <?php phpinfo
とだけ書いたファイルを設置。はい、Internal Server Error…
エラー対策
SuexecUserGroup で指定するユーザー&グループは suexec -V
の AP_GID_MIN と AP_UID_MIN の番号以上にしなければならない
suexec -V が -D AP_LOG_SYSLOG
なので、 # journalctl -f
でエラーを見る。
Sep 09 14:37:06 devel05 suexec[904624]: uid: (1031/t-ito) gid: (10/wheel) cmd: php74-cgi Sep 09 14:37:06 devel05 suexec[904624]: cannot run as forbidden gid (10/php74-cgi)
ははぁ、 cannot run as forbidden gid
で10番のグループIDで動いてるのがダメっぽい。
# getent group wheel wheel:x:10:,t-ito
たしかに10番であるが、suexec -Vでは、 -D AP_GID_MIN=1000
とグループIDが1000番未満ではダメだよと。
自ユーザー独自グループなら問題ないだろうとやり直す。
# getent group t-ito t-ito:x:1031:
当然ながら、1000番以上になっている。
# chown t-ito:t-ito /var/www/demo/php74-cgi # chown -R t-ito:t-ito /var/www/demo/htdocs-suexec
<VirtualHost *:80> ServerName demo.example.ne.jp DocumentRoot "/var/www/demo/htdocs-suexec" ScriptAlias /php-cgi /var/www/demo/php74-cgi SuexecUserGroup t-ito t-ito <Directory "/var/www/demo/htdocs-suexec"> Options FollowSymLinks ExecCGI AllowOverride All AddHandler php-cgi .php Action php-cgi /php-cgi </Directory> ErrorLog /var/www/demo/logs/xxx_error_log CustomLog /var/www/demo/logs/xxx_access_log combined </VirtualHost>
で、Apache再起動
ディレクトリは他のユーザーが書き込み出来てはいけない。
はい、またInternal Server Error… で、#journalctl -f
すると。
Sep 09 14:43:34 devel05 suexec[905245]: uid: (1031/t-ito) gid: (1031/t-ito) cmd: php74-cgi Sep 09 14:43:34 devel05 suexec[905245]: directory is writable by others: (/var/www/demo)
ls -l
すると
drwxrwsr-x 5 t-ito wheel 4096 Sep 9 14:20 demo
なるほど…
# chown t-ito:t-ito demo # chmod 755 demo
これでいけた。なかなか厳しい。