phpfarm + fastcgi で vhost ごとに異なるバージョンの PHP を動かす on apache 2.2 + centos 5.7

さくらVPS の CentOS 5.7 に phpfarm を入れて Apache 2.2 + FastCGI を設定して名前ベースのバーチャルホスト上で phpinfo を表示するまで(環境作りブログではないはずなのに、なぜかこんなネタばかり)。基本的に参考サイトをなぞっただけですが。

手順概要

  1. phpfarm を git clone
  2. mod_fastcgi をソースからコンパイル
  3. apache の設定を書く

phpfarm のインストール

phpfarm を sf.net の Git リポジトリから clone し、リリースされたばかりの 5.3.10 を例としてコンパイル。

参考:Introducing phpfarm

$ su -
# cd /opt
# git clone git://git.code.sf.net/p/phpfarm/code phpfarm
# cd phpfarm/src
# ./compile 5.3.10

終わったらバージョン確認。

# cd ../inst/bin
# ./php-5.3.10 --version
PHP 5.3.10 (cli) (built: Feb 10 2012 22:51:30) (DEBUG)
Copyright (c) 1997-2012 The PHP Group
Zend Engine v2.3.0, Copyright (c) 1998-2012 Zend Technologies
# ./pyrus-5.3.10 --version
Pyrus version 2.0.0a3 SHA-1: BE7EA9D171AE3873F1BBAF692EEE9165BB14BD5D
Using PEAR installation found at /opt/phpfarm/inst/php-5.3.10/pear
php pyrus.phar version 2.0.0a3.

mod_fastcgi のコンパイル、インストール

mod_fastcgi をインストールする。 CentOS ではソースからコンパイルしないといけない。

参考:Red Hat / CentOS Apache 2 FastCGI PHP Configuration

# rpm -q libtool httpd-devel apr-devel apr  # 依存パッケージ
libtool-1.5.22-7.el5_4
httpd-devel-2.2.3-53.el5.centos.3
apr-devel-1.2.7-11.el5_6.5
apr-1.2.7-11.el5_6.5
# mkdir /root/tmp
# cd /root/tmp
# wget http://www.fastcgi.com/dist/mod_fastcgi-current.tar.gz
# tar xvf mod_fastcgi-current.tar.gz
# cd mod_fastcgi-2.4.6
# cp Makefile.AP2 Makefile

以下、 64bit なので /usr/lib64 を指定。 32bit の場合は /usr/lib にする。

# make top_dir=/usr/lib64/httpd
# make install top_dir=/usr/lib64/httpd
make[1]: Entering directory `/root/tmp/mod_fastcgi-2.4.6'
/usr/lib64/apr-1/build/libtool --silent --mode=install cp mod_fastcgi.la /usr/lib64/httpd/modules/
make[1]: Leaving directory `/root/tmp/mod_fastcgi-2.4.6'

apache の設定

モジュールをロードする設定ファイルを作成。このファイルが読み込まれたあとでバーチャルホストの設定が読み込まれなければいけないことに注意( /etc/httpd/conf.d/ 以下の設定ファイル名に気をつけるなど)。

# vi /etc/httpd/conf.d/fastcgi.conf
LoadModule fastcgi_module modules/mod_fastcgi.so

# php-cgi setup
# used for multiple php versions
# see: http://cweiske.de/tagebuch/Running%20Apache%20with%20a%20dozen%20PHP%20versions.htm

# phpfarm でバージョンを1つ追加したらそれに対応する行を以下に追加し
# さらに /var/www/cgi-bin/php-cgi-$version を作成する
#FastCgiServer /var/www/cgi-bin/php-cgi-5.x.x
FastCgiServer /var/www/cgi-bin/php-cgi-5.3.6

ScriptAlias /cgi-bin-php/ /var/www/cgi-bin/

php-cgi-$version を実行するシェルスクリプト

# vi /var/www/cgi-bin/php-5.3.10
#!/bin/sh
# See also /etc/httpd/conf.d/fastcgi.conf

PHPRC="/etc/php5/cgi/5.3.10/"
export PHPRC

PHP_FCGI_CHILDREN=3
export PHP_FCGI_CHILDREN

PHP_FCGI_MAX_REQUESTS=5000
export PHP_FCGI_MAX_REQUESTS

exec /opt/phpfarm/inst/bin/php-cgi-5.3.10
# chmod +x /var/www/cgi-bin/php-5.3.10

名前ベースバーチャルホストの設定を書く。

# vi /etc/httpd/conf.d/vhost.example.jp.conf
<VirtualHost *:80>
  ServerName example.jp
  DocumentRoot /home/cu39/vhosts/example.jp/html
  ErrorLog logs/example.jp-error_log
  CustomLog logs/example.jp-access_log common
  ServerAdmin webmaster@example.jp

  <Directory "/home/cu39/vhosts/example.jp/html">
    AddHandler php-cgi .php
    # 別のバージョンを試したいときはここを変更
    Action php-cgi /cgi-bin-php/php-cgi-5.3.10
    <FilesMatch "\.php$">
      SetHandler php-cgi
    </FilesMatch>
  </Directory>
</VirtualHost>
# chmod +x /var/log/httpd
# /etc/init.d/httpd configtest
# /etc/init.d/httpd restart

とかすると phpinfo() は表示される。

ログに吐かれるエラー

……が /var/log/httpd/error_log に以下のようなエラーが吐かれる。 /var/log/httpd を 755 にしても消えない。

[Sat Feb 11 03:53:51 2012] [notice] suEXEC mechanism enabled (wrapper: /usr/sbin/suexec)
[Sat Feb 11 03:53:51 2012] [error] FastCGI: access for server (uid 4294967295, gid 4294967295) failed: read not allowed
[Sat Feb 11 03:53:51 2012] [error] FastCGI: can't create dynamic directory "/etc/httpd/logs/fastcgi/dynamic": access for server (uid 4294967295, gid 4294967295) failed: read not allowed

/etc/httpd/logs から /var/log/httpd へと張られているシンボリックリンクに絡む問題?

参考:ruby-talk 83308: Re: fastcgi permission error

上掲サイトで提案されている解決策は、シンボリックリンクを削除して /etc/httpd/logs を実際のディレクトリにし、 /var/log/httpd のファイルをそこへ移せというもの。 /var/log/httpd 側をシンボリックリンクにすればいいの……? でも 2003 年から放置されたままなら理由がありそう。

ていうか /var/log/httpd/fastcgi 以下にソケットが作られたりするのもなんだかなぁと思ったりして FastCgiIpcDir してみるが、該当ディレクトリを 777 にしても configtest で write not allowed と言われる。

FastCGI on AWS « That's Geeky を参考に設定を改めてみるが……

# fastcgi.conf に追加した行
FastCgiSuexec /usr/sbin/suexec
# vhost.example.jp.conf に追加した行
SuexecUserGroup 500 100
# chmod 4755 /usr/sbin/suexec
# /etc/init.d/httpd configtest
Syntax error on line 13 of /etc/httpd/conf.d/fastcgi.conf:
FastCgiServer /var/www/cgi-bin/php-cgi-5.3.6: invalid user or group: getpwuid() couldn't determine the username for uid '4294967295', you probably need to modify the User directive: Success

getpwuid() が -1 を返してるから 4294967295 てことですか……ドキュメントを読んでもよくわからないし今は手に負えなさそうなので、エラーが吐かれながらも最初の設定のまま保留。

追記(20:40): mod_fastcgi のソース読んでみたら fcgi_config.c の中で geteuid() と getegid() を呼んでる箇所の直前に以下のコメントが。

/*******************************************************************************
 * Set/Reset the uid/gid that Apache and the PM will run as.  This is ap_user_id
 * and ap_group_id if we're started as root, and euid/egid otherwise.  Also try
 * to check that the config files don't set the User/Group after a FastCGI
 * directive is used that depends on it.
 */

Also try to check that the config files don't set the User/Group after a FastCGI directive is used that depends on it.

また設定ファイル内で FastCGI ディレクティブが使われたあとに User/Group が設定されていないかどうかチェックを試みる。

いやな予感がして httpd.conf をチェックしたらビンゴ。

Include conf.d/*.conf
...
User apache
Group apache

となっていたので

User apache
Group apache
...
Include conf.d/*.conf

としたらエラーを吐かなくなった。

他の何かに影響が出ないかどうかちょっと不安だけど、これで様子を見る。 Ubuntu の apache2.conf を見ると mods-enabled は User/Group のあとから読み込んでるようだし、大丈夫かも。