NOTES : 2011-08-03 : WEB

Nginx + WordPress

以前にVPSにnginxをインストールしてWordpress用のバーチャルホストを設定する記事を書きましたが、改めてWordpress用のnginxの設定をまとめておきたいと思います。
インストール方法等は飛ばしますので、必要な方は以前の記事もご覧ください。

PHPを稼働させる

まず、PHPを使えるようにします。

index index.php;

location ~ .*\.php$ {
    fastcgi_pass   127.0.0.1:9000;
    fastcgi_index  index.php;
    fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
    include        fastcgi_params;
}

nginxのインストール環境によっては、fastcgiのスクリプトを自分で作成する必要があります。
動かない場合はそのへんを確認するといいかもしれません。

パーマリンク設定

パーマリンク設定でURL書き換えを行っている場合は下記が必要です。

location / {
    try_files $uri $uri/ /index.php?q=$uri&$args;
}

# マルチサイトにしている場合は以下も必要
rewrite ^.*/files/(.*) /wp-includes/ms-files.php?file=$1;

.htaccess対策

WordPressやプラグインは、Apacheをベースに考えているので、サーバーがNginxでも勝手に .htaccess を生成する事があります。
当然その内容はNginx用に変換する必要があるのですが、不用意に生成された場合に、Nginxでは.htaccessが丸見えになってしまいますので、その対策をします。

location ~ /\.ht { deny all; }

gzip圧縮転送設定

htmlやcss、js等のテキストファイルをgzip圧縮転送させる設定です。対象ファイルをMIMEタイプで指定します。ここでは多めに設定してみてるので、環境に合わせて変更してください。
[参考: HttpGzipModule]

gzip                on;
gzip_http_version   1.0;
gzip_min_length     1000;
gzip_comp_level     1;
gzip_proxied        expired no-cache no-store private auth;
gzip_vary           on;
gzip_types          text/plain 
                    text/xml 
                    text/css 
                    text/javascript 
                    image/x-icon 
                    application/xml 
                    application/rss+xml 
                    application/json 
                    application/x-javascript;
gzip_disable        "MSIE [1-6]\.";
gzip_disable        "Mozilla/4";

古いブラウザ相手にgzip圧縮転送すると不安定な事があるらしいので、条件付けて gzip_disable させてます。
また、うちのサーバは省メモリのVPSなのと、Wordpressを使う場合、サーバ負荷の原因の多くは転送量よりもCPU負荷かと思うので、gzip_comp_level は1にしてます。

ブラウザキャッシュを有効にする

ファイルの送信ヘッダに有効期限をつけることで、ブラウザ側でのキャッシュを期待できます。
ここでは、ファイル自体が存在する静的ファイルすべてに有効期限を設定します。
[参考: HttpHeadersModule]

location / {
    if (-f $request_filename) {
        expires 30d;
        add_header Pragma "public";
        add_header Cache-Control "public, must-revalidate, proxy-revalidate";
    }
}
location ~* .*\.(jpe?g|gif|png|css|js|inc|ico|gz|zip|pdf|mp3|m4a|mp4|swf|wmv|flv|svgz?) { expires 14d; add_header Pragma “public”; add_header Cache-Control “public, must-revalidate, proxy-revalidate”;}

proxy cacheを有効にする

nginxをリバースプロキシサーバとして設定します。
[参考: HttpProxyModule]

proxy_cache_path    /var/cache/nginx levels=1:2 keys_zone=czone:10m max_size=200m inactive=1d;
proxy_temp_path     /var/tmp/nginx;
proxy_cache_valid       200 302 10m;
proxy_cache_valid       301 1h;
proxy_cache_valid       any 1m;

proxy_set_header Host            $http_host;
proxy_set_header X-Remote-Addr   $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

upstream www_domain_com {
    ip_hash;
    server 127.0.0.1:8080;
}

server {
    listen          80;
    server_name     www.domain.com;
    access_log /var/log/access.log;
    error_log /var/log/error.log;

    location /wp-admin { proxy_pass http://www_domain_com; }
    location ~ .*\.php { proxy_pass http://www_domain_com; }
    location / {
        if ($http_user_agent ~* '(DoCoMo|J-PHONE|Vodafone|MOT-|UP\.Browser|DDIPOCKET|ASTEL|PDXGW|Palmscape|Xiino|sharp pda browser|Windows CE|L-mode|WILLCOM|SoftBank|Semulator|Vemulator|J-EMULATOR|emobile|mixi-mobile-converter)') {
            set $mobile 1;
        }
        if ($http_user_agent ~* '(iPhone|iPod|Opera Mini|Android.*Mobile|NetFront|PSP|BlackBerry)') {
            set $mobile 2;
        }
        if ($http_cookie ~* "comment_author_[^=]*=([^%]+)%7C|wordpress_logged_in_[^=]*=([^%]+)%7C") {
            set $do_not_cache 1;
        }
        proxy_no_cache     $do_not_cache;
        proxy_cache_bypass $do_not_cache;
        proxy_cache czone;
        proxy_cache_key "$scheme://$host$request_uri$is_args$args$mobile";
        proxy_pass http://www_domain_com;
    }
}

上記の記述で以下のような動作になります。

  • 10M〜200Mまでのキャッシュを1日保存。
  • コンテンツ取得は10分間、移転は1時間、エラーは1分間、再チェックなし
  • 管理画面へのアクセスはキャッシュサーバー素通り
  • 携帯電話とスマートフォンとPCで別々のキャッシュを作成
  • Cookieはキャッシュ対象外

次に元のWordpressをインストールしてあるサーバ設定の、listen と server_name を変更して、アクセスログの設定を削除します。

server {
    listen       8080;
    server_name  _;

    … その他の設定
}

proxy cacheのクリア

ngx_cache_purge モジュールが Nginx にインストールされている場合は、強制キャッシュクリアが使えます。
普段はキャッシュの再チェック時間(上記だと10分間)で更新されるので、手動でキャッシュクリアする必要はあまりありませんが、非常時用に強制的にキャッシュクリアする手段だけ作っておくと安心です。

location ~ /purge(/.*) {
    proxy_cache_purge czone "$scheme://$host$1$is_args$args$mobile";
}

この場合、$mobile変数を利用するので、前に記載したコードを、一つ上の階層のserverディレクティブに移す必要があります。

server {
    ...
    if ($http_user_agent ~* '(DoCoMo|J-PHONE|Vodafone|MOT-|UP\.Browser|DDIPOCKET|ASTEL|PDXGW|Palmscape|Xiino|sharp pda browser|Windows CE|L-mode|WILLCOM|SoftBank|Semulator|Vemulator|J-EMULATOR|emobile|mixi-mobile-converter)') {
        set $mobile 1;
    }
    if ($http_user_agent ~* '(iPhone|iPod|Opera Mini|Android.*Mobile|NetFront|PSP|BlackBerry)') {
        set $mobile 2;
    }
    ...
}

モジュールが無い場合は、キャッシュディレクトリを全部削除するしか方法がありません。

# sudo rm -f -R /var/cache/nginx/*

nginx.conf 設定例

これまでの内容を入れた、nginx.conf の設定例です。
それぞれを合わせたので、前記とは異なる記述になっている箇所もあります。

user                apache;
worker_processes    2;
error_log           /var/log/nginx/error.log;
pid                 /var/run/nginx.pid;

events {
    worker_connections  1024;
}
http {
    include             mime.types;
    default_type        application/octet-stream;

    log_format  main    '$remote_addr - $remote_user [$time_local] $request '
                        '"$status" $body_bytes_sent "$http_referer" '
                        '"$http_user_agent" "$http_x_forwarded_for"';

    access_log          /var/log/nginx/access.log   main;

    sendfile            on;
    tcp_nodelay         on;
    keepalive_timeout   45;
    server_tokens       off;

    # gzip
    gzip                on;
    gzip_http_version   1.0;
    gzip_min_length     1000;
    gzip_comp_level     1;
    gzip_proxied        expired no-cache no-store private auth;
    gzip_vary           on;
    gzip_types          text/plain 
                        text/xml 
                        text/css 
                        text/javascript 
                        image/x-icon 
                        application/xml 
                        application/rss+xml 
                        application/json 
                        application/x-javascript;
    gzip_disable        "MSIE [1-6]\.";
    gzip_disable        "Mozilla/4";


    # Proxy Cahe
    proxy_cache_path    /var/cache/nginx levels=1:2 keys_zone=czone:15m max_size=100m inactive=120m;
    proxy_temp_path     /var/tmp/nginx;
    proxy_cache_valid       200 302 10m;
    proxy_cache_valid       301 1h;
    proxy_cache_valid       any 1m;

    # set header
    proxy_set_header Host            $http_host;
    proxy_set_header X-Remote-Addr   $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

    upstream www_domain_com {
        ip_hash;
        server 127.0.0.1:8080;
    }

    server {
        listen    80;
        server_name  www.domain.com;
        access_log /var/log/access.log;
        error_log /var/log/error.log;

        if ($http_user_agent ~* '(DoCoMo|J-PHONE|Vodafone|MOT-|UP\.Browser|DDIPOCKET|ASTEL|PDXGW|Palmscape|Xiino|sharp pda browser|Windows CE|L-mode|WILLCOM|SoftBank|Semulator|Vemulator|J-EMULATOR|emobile|mixi-mobile-converter)') {
            set $mobile 1;
        }
        if ($http_user_agent ~* '(iPhone|iPod|Opera Mini|Android.*Mobile|NetFront|PSP|BlackBerry)') {
            set $mobile 2;
        }
        location /wp-admin { proxy_pass http://www_domain_com; }
        location ~ .*\.php { proxy_pass http://www_domain_com; }
        location / {
            if ($http_cookie ~* "comment_author_[^=]*=([^%]+)%7C|wordpress_logged_in_[^=]*=([^%]+)%7C") {
                set $do_not_cache 1;
            }
            proxy_no_cache   $do_not_cache;
            proxy_cache_bypass $do_not_cache;
            proxy_cache czone;
            proxy_cache_key "$scheme://$host$request_uri$is_args$args$mobile";
            proxy_pass http://www_domain_com;
        }
        location ~ /purge(/.*) {
            proxy_cache_purge czone "$scheme://$host$1$is_args$args$mobile";
        }
    }

    server {
            listen 8080;
            server_name _;

            root /var/www;
            index index.html index.php;
            charset utf-8;

            location / {
                    if (-f $request_filename) {
                        expires 30d;
                        add_header Pragma "public";
                        add_header Cache-Control "public, must-revalidate, proxy-revalidate";
                    }
                    try_files $uri $uri/ /index.php?q=$uri&$args;
            }
            rewrite ^.*/files/(.*) /wp-includes/ms-files.php?file=$1;

            location ~ .*\.php$ {
                    fastcgi_pass    127.0.0.1:9000;
                    fastcgi_index   index.php;
                    fastcgi_param   SCRIPT_FILENAME $document_root$fastcgi_script_name;
                    include     fastcgi_params;
            }
            location ~ /\.ht { deny all; }
    }
}

追記

  • 2011.08.19 設定パラメータの一部を調整しました。
  • 2011.11.01 purgeの設定を見直しました。

コメント (0件) - 表示・投稿 ▼

関連記事

No related posts.