WordpressをnginxとPHP-FPM(FastCGI)で運用するための環境構築-2

2011-12-09  /  PHPWordPress

nginxをインストール

サーバーの負荷軽減、パフォーマンス向上が期待されるということで、nginxとPHP-FPMでWordpressを運用することにしました。その構築手順です。 前回、PHP-FPMをインストールしたので、今回はnginxです。

環境

前回に引き続き、サーバーは、さくらインターネットのVPS512で、CentOS5を使用しています。Apache+PHP(モジュール)で運用中のサイトがあるので、それを活かしたままで稼働できるようにします。

yumのリポジトリ追加

nginxは、最新版のパッケージを配布している公式リポジトリがあります。CentOS標準のリポジトリにあるnginxはバージョンが古いので、公式リポジトリを利用します。 nginx: downloadのページ、「Pre-Build Package」にリンクがあるので、rpmをインストールします。

作業はrootで行っています。(URLは投稿時のものです。)

$ rpm -Uvh http://nginx.org/packages/centos/5/noarch/RPMS/nginx-release-centos-5-0.el5.ngx.noarch.rpm

インストールできると、/etc/yum.repos.dの中に、nginx.confがあるのが確認できます。

nginxのインストール

yumのリポジトリの追加を行ったので、インストールは簡単です。念のためパッケージの情報を確認してみます。最新の安定版は1.0.10です。
$ yum info nginx
Name       : nginx
Arch       : x86_64
Version    : 1.0.10

一部省略しています。Versionが最新になっていることが確認できましたので、インストールします。

$ yum install nginx

nginxのサービスの設定

yumからインストールしているので、サービスとして登録されています。常駐させるための設定を行います。
$ chkconfig nginx on
$ chkconfig --list nginx
nginx          	0:off	1:off	2:on	3:on	4:on	5:on	6:off

サービスとして利用できるようになっていますが、起動前にnginxの初期設定を行います。

nginxの初期設定

設定ファイルは/etc/nginx/nginx.confです。念のためnginx.conf.defaultとして複製しておきます。
cd /etc/nginx
cp nginx.conf nginx.conf.default

VirtualHost用のログ設定
mainというログフォーマットを修正して、vhostというログフォーマットの設定をします。先頭に $host を追加しています。
複数のドメインで運用する場合に、どのドメイン(ホスト名)にアクセスしてきたかを知るために、ホスト名をログに記録します。

log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                  '$status $body_bytes_sent "$http_referer" '
                  '"$http_user_agent" "$http_x_forwarded_for"';
# 追記
log_format  vhost '$host $remote_addr - $remote_user [$time_local] "$request" '
                  '$status $body_bytes_sent "$http_referer" '
                  '"$http_user_agent" "$http_x_forwarded_for"';
# main から vhost に変更
access_log  /var/log/nginx/access.log  vhost;

デフォルト設定
アクセス全般に対してのデフォルト設定です。

server_tokens off;    # versionをレスポンスヘッダーに表示しない
index index.html index.php;    # ディレクトリインデックス
charset utf-8;    # 文字コード
error_page 500 502 503 504 /50x.html;    # エラーページ
large_client_header_buffers 4 8k;    # 長いURLやクッキーのサイズが大きい場合に対応する

文字コード設定は、UTF8以外で制作しているページやCMSがあれば、設定しない方が良いと思います。(UTF8以外を採用しているページやCMSは少ないとは思いますが…)
large_client_header_buffersの設定については、これが最適値かどうかわかりませんが、小さいと400か414エラーになるということで、上記の設定を行っています。

nginx公式の説明
によると、

デフォルトでは、ひとつのバッファのサイズはページのサイズと同等で、プラットフォームによりますが、4K もしくは 8K です。ワーキングリクエストの終了時に接続が変わりキープアライブが提示された場合、これらのバッファは解放されます。
ということなので、設定の必要はないかもしれません。

デフォルトサーバーの設定
不正アクセスなのか、DNSの設定ミスなのかわかりませんが、管理外のドメインでのアクセスが、そこそこあります。そういったアクセスに対応する設定です。

# default server
server {
    listen 80 default_server;
    server_name _;
    access_log /var/log/nginx/default.log vhost;
    server_name_in_redirect off;
    root /var/www/dummy;
}

管理外のドメインに対してのアクセスログを、運用しているドメインと同じログに混在させたくないので、アクセスログは別で保存するようにしています。rootも念のため切り分けています。

変更後の設定ファイルのdiffです。

$ diff nginx.conf.default nginx.conf
20a21,23
>     log_format  vhost '$host $remote_addr - $remote_user [$time_local] "$request" '
>                       '$status $body_bytes_sent "$http_referer" '
>                       '"$http_user_agent" "$http_x_forwarded_for"';
22c25
<     access_log  /var/log/nginx/access.log  main;
---
>     access_log  /var/log/nginx/access.log  vhost;
30a34,48
>     server_tokens off;
>     index index.html index.php;
>     charset utf-8;
>     error_page 500 502 503 504 /50x.html;
>     large_client_header_buffers 4 8k;
> 
>     # default server 
>     server {
>         listen 80 default_server;
>         server_name _;
>         access_log /var/log/nginx/default.log vhost;
>         server_name_in_redirect off;
>         root /var/www/dummy;
>     }

PHP-FPMと連携する設定

次にWordpressと連携するための設定を行います。/etc/nginx/conf.d配下のconfファイルをincludeする設定になっていますので、/etc/nginx/conf.d/wordpress.confというファイルで設定を行います。 もともとあるdefault.confを複製して使います。
cd /etc/nginx/conf.d
cp default.conf wordpress.conf

前提として、/var/www/vhosts以下にホスト名でディレクトリを作り、その中にlog、public_htmlなど必要なディレクトリを作成するという方針にしています。
例えば、lab.cazooro.jpであれば、

/var/www/vhosts/lab.cazooro.jp/log
/var/www/vhosts/lab.cazooro.jp/public_html

という感じです。

修正を行ったwordpress.confです。nginxは$hostという変数でホスト名が使用できますので、$hostを設定内では使用しています。

server {
    listen 80; 
    server_name ホスト名;
    # $host が server_name で設定したホスト名になります
    access_log /var/www/vhosts/$host/log/access.log;

    location / {
        # public_html以下のファイルを公開
        root /var/www/vhosts/$host/public_html;
        # index.php を index.html より優先して表示
        index index.php index.html;
        # リクエストされたファイルが存在しない場合、index.php を表示
        if (!-e $request_filename) {
            rewrite ^(.+)$ /index.php?q=$1 last;
            break;
        }   
    }   
    
    # エラーが起きた場合のファイルはnginx配下のファイルを使用
    location = /50x.html {
        root   /usr/share/nginx/html;
    }   
    
    # PHPファイルへのアクセスはFastCGI(PHP-FPM)へ処理を任せます
    location ~ \.php$ {
        fastcgi_pass 127.0.0.1:9000;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME /var/www/vhosts/$host/public_html$fastcgi_script_name;
        # FastCGIで起きたエラーをそのまま表示するかどうか
        # Wordpressの設定中などエラーの内容を表示したい場合には off(デフォルト)
        # 運用中などエラーの内容を表示したくない場合には on
        #fastcgi_intercept_errors on; 
        include fastcgi_params;
    }   
    
    # .htaccessや.htpasswordなどのファイルアクセスを禁止
    location ~ /\.ht {
        deny  all;
    }   
}

基本的にはdefault.confの内容が使えます。画像やCSS、JSはnginxがそのまま処理して、他はPHP-FPMでWordpressが実行されます。Wordpress自体に404エラーを処理する仕組みがあるので、404のエラーページは特に設定していません。

Wordpressの設定

Apacheからnginxに完全に乗り換える場合、すでに起動中のApacheを停止して、nginxを代わりに起動します。
$ service apache stop
$ service nginx start

設定に問題が無ければ、今までと同じようにWordpressのサイトが表示できます。

自分の場合は、トップページは問題なく表示できたのですが、それ以下の、個別の記事やアーカイブのページが表示されませんでした。

もともとWordpressはapache + mod_rewriteでの運用が前提になっていて、mod_rewriteが使えない場合は、

http://lab.cazooro.jp/index.php/aaa/bbb

というindex.phpを含んだURLでアクセスすることができるようになっています。しかし、nginxの方でmod_rewriteに相当する処理を行っていますので、index.phpの部分は必要ありません。

Wordpressの管理画面側は問題なくアクセスできますので、管理画面にログインし、「設定」->「パーマリンク設定」を確認してください。
パーマリンク設定
このように設定中に index.php が含まれてしまうので、「カスタム構造」を利用してindex.phpが必要ないパーマリンクを設定し直します。

以上でWordpressをnginxとPHP-FPMで運用するための設定は終了です。PHP-FPMのソースからのインストールの際に、依存ライブラリの不足によるコンパイルエラーで手間取りました。それ以外はスムーズにできた印象です。

完全に移行する場合には必要ありませんが、既存のApache環境を活かすための設定を引き続き行います。


コマンドまとめ

nginxのインストールと設定
$ rpm -Uvh http://nginx.org/packages/centos/5/noarch/RPMS/nginx-release-centos-5-0.el5.ngx.noarch.rpm

$ yum info nginx
Name       : nginx
Arch       : x86_64
Version    : 1.0.10

$ yum install nginx

$ chkconfig nginx on
$ chkconfig --list nginx
nginx          	0:off	1:off	2:on	3:on	4:on	5:on	6:off

cd /etc/nginx
cp nginx.conf nginx.conf.default

log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                  '$status $body_bytes_sent "$http_referer" '
                  '"$http_user_agent" "$http_x_forwarded_for"';
# 追記
log_format  vhost '$host $remote_addr - $remote_user [$time_local] "$request" '
                  '$status $body_bytes_sent "$http_referer" '
                  '"$http_user_agent" "$http_x_forwarded_for"';
# main から vhost に変更
access_log  /var/log/nginx/access.log  vhost;

server_tokens off;    # versionをレスポンスヘッダーに表示しない
index index.html index.php;    # ディレクトリインデックス
charset utf-8;    # 文字コード
error_page 500 502 503 504 /50x.html;    # エラーページ
large_client_header_buffers 4 8k;    # 長いURLやクッキーのサイズが大きい場合に対応する

# default server
server {
    listen 80 default_server;
    server_name _;
    access_log /var/log/nginx/default.log vhost;
    server_name_in_redirect off;
    root /var/www/dummy;
}

$ diff nginx.conf.default nginx.conf
20a21,23
>     log_format  vhost '$host $remote_addr - $remote_user [$time_local] "$request" '
>                       '$status $body_bytes_sent "$http_referer" '
>                       '"$http_user_agent" "$http_x_forwarded_for"';
22c25
<     access_log  /var/log/nginx/access.log  main;
---
>     access_log  /var/log/nginx/access.log  vhost;
30a34,48
>     server_tokens off;
>     index index.html index.php;
>     charset utf-8;
>     error_page 500 502 503 504 /50x.html;
>     large_client_header_buffers 4 8k;
> 
>     # default server 
>     server {
>         listen 80 default_server;
>         server_name _;
>         access_log /var/log/nginx/default.log vhost;
>         server_name_in_redirect off;
>         root /var/www/dummy;
>     }

cd /etc/nginx/conf.d
cp default.conf wordpress.conf

wordpress.conf
server {
listen 80;
server_name ホスト名;
# $host が server_name で設定したホスト名になります
access_log /var/www/vhosts/$host/log/access.log;

    location / {
        # public_html以下のファイルを公開
        root /var/www/vhosts/$host/public_html;
        # index.php を index.html より優先して表示
        index index.php index.html;
        # リクエストされたファイルが存在しない場合、index.php を表示
        if (!-e $request_filename) {
            rewrite ^(.+)$ /index.php?q=$1 last;
            break;
        }   
    }   
    
    # エラーが起きた場合のファイルはnginx配下のファイルを使用
    location = /50x.html {
        root   /usr/share/nginx/html;
    }   
    
    # PHPファイルへのアクセスはFastCGI(PHP-FPM)へ処理を任せます
    location ~ \.php$ {
        fastcgi_pass 127.0.0.1:9000;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME /var/www/vhosts/$host/public_html$fastcgi_script_name;
        # FastCGIで起きたエラーをそのまま表示するかどうか
        # Wordpressの設定中などエラーの内容を表示したい場合には off(デフォルト)
        # 運用中などエラーの内容を表示したくない場合には on
        #fastcgi_intercept_errors on; 
        include fastcgi_params;
    }   
    
    # .htaccessや.htpasswordなどのファイルアクセスを禁止
    location ~ /\.ht {
        deny  all;
    }   
}

Apacheからnginxに完全に乗り換える場合
$ service apache stop
$ service nginx start