作成 2012.02.28
更新 2012.03.01
FreeBSD で nginx + PHP FPM + fcgiwrap
今さらながら FreeBSD 9.0 に nginx を入れた時のメモ
前回のやり方は FreeBSD 以外の環境で応用できないのでリベンジ。
さらに、perl CGI を動作させるために fcgiwrap を導入する。
目次
システム概要
インストール
nginx
PHP FPM
fcgiwrap
サーバー設定
PHP FPM
fcgiwrap
fcgiwrap の補足
nginx
fastcgi_params の補足
サービス管理
起動
停止
設定のリロード
その他
Apache mod_rewrite からの移行
Apache Alias からの移行
ログのローテーション
システム概要
nginx がフロントエンドの HTTP サーバーとして動作し、php が呼び出された場合は PHP FPM がバックエンドとして PHP を実行する。
同様に、cgi ファイルの場合は、fcgiwrap が実行ファイルを呼び出す。
クライアント ========> nginx ========> PHP FPM
          TCP/80/HTTP    TCP/9000/FastCGI(CGI/1.1)
                           ========> fcgiwrap ==> 実行ファイル
                         UNIX/FastCGI(CGI/1.1)
インストール
nginx
www/nginx を ports でインストール
# portmaster www/nginx
モジュールは以下を選択
IPV6
HTTP_MODULE
HTTP_ADDITION_MODULE
HTTP_CACHE_MODULE
HTTP_REALIP_MODULE
HTTP_REWRITE_MODULE
HTTP_SSL_MODULE
HTTP_SUB_MODULE
WWW
HEADERS_MORE_MODULE
HTTP_AUTH_PAM_MODULE
PHP FPM
PHP FPM は PHP のモジュールの一つとして存在する。そのため PHP をインストールする。
今回はは最新版の lang/php5 をインストール。
インストール済みの場合は、--force-config オプションを追加すればモジュールの再選択ができる。
# portmaster lang/php5
モジュールは以下を選択。
FPM を選択するのがキモ。
CLI
CGI
FPM
SUHOSIN
MULTIBYTE
IPV6
MAILHEAD
任意で追加インストール
# portmaster converters/php5-mbstring
# portmaster databases/php5-pdo_sqlite
fcgiwrap
fcgiwrap に選択肢はない。淡々とインストールする。
自動的に www/fcgi もインストールされる。
# portmaster www/fcgiwrap
サーバー設定
PHP FPM
設定は、php-fpm.conf で実施する。
設定ファイルに記述されているデフォルトでは、ユーザーは www で実行され、127.0.0.1:9000 で待ち受ける。
/usr/local/etc/php-fpm.conf
; (略)
起動設定は rc.conf で
/etc/rc.conf
php_fpm_enable="YES"
fcgiwrap
設定ファイルは存在しないが、rc.conf でパラメーターを設定できる。
fcgiwrap_user は nginx.conf の user ディレクティブと同じユーザーを指定する。
/etc/rc.conf
fcgiwrap_enable="YES"
fcgiwrap_user="www"
fcgiwrap の補足
nginx と fcgiwrap 間は UNIX ソケットを利用して通信する。
デフォルトは /var/run/fcgiwrap/fcgiwrap.sock であり、rc.conf で以下の要領で指定できる。
fcgiwrap_socket="unix:/var/run/fcgiwrap/fcgiwrap.sock"
なお、このソケットファイルは nginx から書き込める権限が必要だが、サービスを起動するたびに srw-r--r-- に戻ってしまうため、結果的に nginx と同じユーザーを指定しないと cgi が呼び出せなくなってしまう。
nginx
起動設定は rc.conf で
/etc/rc.conf
nginx_enable="YES"
各種設定は /usr/local/etc/nginx/nginx.conf を編集する。
マニュアルは公式サイトの英語ページに記載されているが、基本的な構成はすでに記述されているのでトリッキーなことをしない限り問題ないだろう。
FastCGI + PHP の設定に関しても nginx.conf にコメントアウトされた状態で以下のように記述されている。
/usr/local/etc/nginx/nginx.conf より抜粋
location / {
    root   /usr/local/www/nginx;
    index  index.html index.htm;
}

# proxy the PHP scripts to Apache listening on 127.0.0.1:80
#
#location ~ \.php$ {
#    proxy_pass   http://127.0.0.1;
#}

# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
#location ~ \.php$ {
#    root           html;
#    fastcgi_pass   127.0.0.1:9000;
#    fastcgi_index  index.php;
#    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
#    include        fastcgi_params;
#}

# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
#    deny  all;
#}
三段落目のコメントアウトを外すことで、FastCGIへの接続が有効になる。
スクリプトの実体を /scripts/ 配下に配置することで該当のスクリプトが実行される。
fastcgi_params の補足
ちなみに、include fastcgi_params は外部ファイルを読み込んでいる。実体は以下のとおり。
/usr/local/etc/nginx/fastcgi_params
fastcgi_param  QUERY_STRING       $query_string;
fastcgi_param  REQUEST_METHOD     $request_method;
fastcgi_param  CONTENT_TYPE       $content_type;
fastcgi_param  CONTENT_LENGTH     $content_length;

fastcgi_param  SCRIPT_NAME        $fastcgi_script_name;
fastcgi_param  REQUEST_URI        $request_uri;
fastcgi_param  DOCUMENT_URI       $document_uri;
fastcgi_param  DOCUMENT_ROOT      $document_root;
fastcgi_param  SERVER_PROTOCOL    $server_protocol;

fastcgi_param  GATEWAY_INTERFACE  CGI/1.1;
fastcgi_param  SERVER_SOFTWARE    nginx/$nginx_version;

fastcgi_param  REMOTE_ADDR        $remote_addr;
fastcgi_param  REMOTE_PORT        $remote_port;
fastcgi_param  SERVER_ADDR        $server_addr;
fastcgi_param  SERVER_PORT        $server_port;
fastcgi_param  SERVER_NAME        $server_name;

# PHP only, required if PHP was built with --enable-force-cgi-redirect
fastcgi_param  REDIRECT_STATUS    200;
fcgiwrap を呼び出す記述を追加する。基本的に php と同様の指定内容。
/usr/local/etc/nginx/nginx.conf の server ディレクティブ内に追加
location ~ \.cgi$ {
    fastcgi_pass   unix:/var/run/fcgiwrap/fcgiwrap.sock;
    fastcgi_param  SCRIPT_FILENAME  /cgi_scripts$fastcgi_script_name;
    include        fastcgi_params;
}
サービス管理
起動
起動順序は順不同で構わないが、システムの依存関係を考慮すると、バックエンドから先に起動する方がセオリー。
# service php-fpm start
Starting php_fpm.
# service fcgiwrap start
Starting fcgiwrap.
# service nginx start
Performing sanity check on nginx configuration:
nginx: the configuration file /usr/local/etc/nginx/nginx.conf syntax is ok
nginx: configuration file /usr/local/etc/nginx/nginx.conf test is successful
Starting nginx.
停止
起動と逆の順で。
# service nginx stop
# service fcgiwrap start
# service php-fpm start
設定のリロード
location ディレクティブの変更程度なら、設定変更を無停止で反映できる。
# service nginx reload
その他
Apache mod_rewrite からの移行
このページも mod_rewrite を使用してページを表示していた。現在は nginx へ移行済み。
公式ドキュメントにもそれなりに記載されているが用途が若干違うので記載しておく。
httpd.conf mod_rewrite の記述
RewriteEngine on
RewriteRule ^/kb/$ "/kb/main.php" [L]
RewriteRule ^/kb/(.*)\.html$ "/kb/main.php?op=$1" [L]
RewriteRule ^/kb/tag/(.*)$ "/kb/main.php?tag=$1" [L]
RewriteRule ^/kb/([0-9]*)$ "/kb/main.php?id=$1" [L]
nginx.conf rewrite の記述
location ~ \.php$ {
    fastcgi_pass   127.0.0.1:9000;
    fastcgi_index  index.php;
    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
    include        fastcgi_params;
}
location = /kb/ {
    rewrite ^ /kb/main.php;
}
location ~ /kb/\d+$ {
    rewrite kb/(\d+)$ /kb/main.php?id=$1;
}
location ~ /kb/tag/.+$ {
    rewrite kb/tag/(.+)$ /kb/main.php?tag=$1;
}
location ~ /kb/.+\.html$ {
    rewrite kb/(.+)\.html /kb/main.php?op=$1;
}
= マークは完全一致、~ マークは正規表現でマッチすることを意味する。
location が複数の項目にマッチすると、マークなしよりマークありが優先される。また、複数のマークなしにマッチするとより長いほうが適用され、複数のマークありにマッチすると上に記述したものが適用される。要するに、=~ が付いている方が優先となる。
なお、rewrite されると location が再評価されるため、無限ループに注意。また、rewrite と auth は location 内で共存できないためちょっと苦労した。
Apache Alias からの移行
httpd.conf Alias の記述
Alias /sub/ /data/
nginx.conf location の記述
location /sub/ {
    alias   /data/;
}
alias の代わりに root でも一応可能。
その場合は、http://hostname/sub/test.html へアクセスすると、/data/sub/test.html のファイルが参照される。
alias の先に php がある場合は、location をネストして記述することで対応可能。ただ、auth を使用しない場合に限り、alias 上の実行ファイルを他の実行ファイルと同じディレクトリに移動させたほうが、よりシンプルになる。
ログのローテーション
とりあえず、5世代分 1MB に達したらローテーションするようにした。
/etc/newsyslog.conf
# logfilename             [owner:group] mode count size when  flags [/pid_file] [sig_num]
/var/log/php-fpm.log      root:wheel    640  5     1000 *     JC    /var/run/php-fpm.pid
/var/log/nginx-access.log root:wheel    640  5     1000 *     JC    /var/run/nginx.pid
/var/log/nginx-error.log  root:wheel    640  5     1000 *     JC    /var/run/nginx.pid
タグ: FreeBSD PHP Perl

©2004-2017 UPKEN IPv4