work.log

元エンジニアの備忘録的ブログ

NginxでWordPressを使う時の設定をまとめてみた

投稿:2015-03-10 18:57  更新:

NginxWordPress を使う為の設定って結構色々な書き方が出来るのですが、ネット上の情報は断片的な気がしたのでちょっとまとめてみました。

マルチドメインでシンプルに設定を追加していきたいのと、WordPress 用にこれだけ書けば不自由はないよ!ってのを目的に設定してます。

環境

今回は「GMO クラウド VPS」を借りてまっさらな状態で色々と試しました。

何度か記事に設定について記事を書いていますが、間借りの環境でばっかり試していたものだから、設定のブレが大きいし微妙に環境依存している部分があったりしたのでこれじゃいかんという事で。

とりあえず、各種スペックはこんな感じです。

  • VPS: GMO クラウド VPS スモールプラン
  • OS: CentOS 6.6 (6.2 からアップグレード)
  • Nginx: 1.6.2
  • PHP (php-fpm): 5.5.21

PHP は remi リポジトリを使って yum でインストール。

Nginx は image filter モジュールを別で利用したかったのと、ディレクトリ構成等のパラメータを変えたかったのでソースからインストールしてみました。

2016-06-16 追記

現地点での最新安定版 Nginx 1.10 および PHP 7 を利用したい場合は下記インストール方法を参照。

Nginx 1.6 + PHP 5.5 で構築した環境より WordPress が速くなります。

WordPressをNginx 1.10とPHP 7の環境で動かしてみる

# ./configure \
--prefix=/etc/nginx \
--sbin-path=/usr/sbin/nginx \
--conf-path=/etc/nginx/nginx.conf \
--pid-path=/var/run/nginx.pid \
--lock-path=/var/run/nginx.lock \
--error-log-path=/var/log/nginx-error.log \
--user=www \
--group=www \
--http-client-body-temp-path=/home/www/tmp/client_body_temp \
--http-fastcgi-temp-path=/home/www/tmp/fastcgi_temp \
--http-proxy-temp-path=/home/www/tmp/proxy_temp \
--http-scgi-temp-path=/home/www/tmp/scgi_temp \
--http-uwsgi-temp-path=/home/www/tmp/uwsgi_temp \
--http-log-path=/var/log/nginx-access.log \
--add-module=/path/to/ngx_cache_purge-2.3 \
--with-http_gzip_static_module \
--with-http_image_filter_module \
--with-http_stub_status_module \
--with-http_sub_module \
--with-pcre \
--with-http_ssl_module

# make ; make install

image filter モジュールとか要らないと思ったら nginx のリポジトリを追加して yum でインストールするのが簡単。

# rpm -ivh http://nginx.org/packages/centos/6/noarch/RPMS/nginx-release-centos-6-0.el6.ngx.noarch.rpm
# yum -y install --enablerepo=nginx nginx

nginx.confの設定

全般的な設定を nginx.conf に書いて、それ以外は cond.d というディレクトリを作成しそこに作っていく構成にしてみました。

user	www www;
pid	/var/run/nginx.pid;

# worker_processes はVPSの CPU コア数に合わせて設定
worker_processes      4;
worker_rlimit_nofile  4096;

events {
	use epoll;
	multi_accept        on;
	worker_connections  1024;
}

http {

	include  mime.types;

	default_type  text/plain;
	server_names_hash_bucket_size  64;
	client_body_buffer_size  64k;

	# gzip 圧縮を有効化
	gzip              on;
	gzip_http_version 1.0;
	gzip_types        text/plain
			  text/xml
			  text/css
			  text/javascript
			  application/xml
			  application/xhtml+xml
			  application/rss+xml
			  application/atom_xml
			  application/javascript
			  application/x-javascript
			  application/x-httpd-php;
	gzip_disable      "MSIE [1-6]\.";
	gzip_disable      "Mozilla/4";
	gzip_comp_level   1;
	gzip_buffers      4 8k;
	gzip_min_length   1100;

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

	sendfile          on;
	tcp_nopush        on;
	server_tokens     off;

	# 画像も捌くので keepalive は on
	keepalive_requests 100;
	keepalive_timeout  2;

	fastcgi_buffers 8 64k;
	fastcgi_buffer_size 64k;
	fastcgi_connect_timeout 60;
	fastcgi_read_timeout    60;
	fastcgi_send_timeout    60;

	# リバースプロキシも使うかもしれないので一応設定
	proxy_connect_timeout  60;
	proxy_send_timeout     60;
	proxy_read_timeout     60;
	proxy_set_header       Host               $host;
	proxy_set_header       X-Real-IP          $remote_addr;
	proxy_set_header       X-Forwarded-Host   $host;
	proxy_set_header       X-Forwarded-Server $host;
	proxy_set_header       X-Forwarded-For    $proxy_add_x_forwarded_for;
	proxy_temp_path        /home/www/tmp;

	# ドメイン名毎のキャッシュの設定は別ファイルに書く
	include                conf.d/cache_path.conf;

# デフォルトのサーバ
server {

	listen  *:80 default_server;
	root    /home/www/htdocs;

	access_log  /var/log/nginx-access.log main;
	error_log   /var/log/nginx-error.log warn;

	index  index.html;
	include  conf.d/global.conf;

}

	# バーチャルドメイン用の設定ファイルをインクルード
	include  conf.d/virtual.conf;

}

Nginxでインクルードする各種設定

次に nginx.conf からインクルードする各種設定を。

/etc/nginx/conf.d という感じにディレクトリを作成し、そこに 4 つの設定ファイルを配置します。

全般的な設定

WordPress 以外でも汎用的に使うんじゃないかなと思う設定はここに書くことに。少ないけど中身はこんな感じです。

location ~ /\. {
	return 404;
}

location ~ /favicon.ico {
	allow  all;
	log_not_found  off;
	access_log  off;
	error_log   /dev/null crit;
}

location ~ /robots.txt {
	allow  all;
	log_not_found  off;
	access_log  off;
	error_log   /dev/null crit;
}

キャッシュキーの設定

キャッシュキーはドメイン名毎に分けたいのでこんな感じに書いています。

ディレクトリパスは環境依存している設定値を記述しているので注意。

fastcgi_cache_path  /home/www/cache/default levels=1:2 keys_zone=default:18m inactive=1d max_size=10g;
fastcgi_cache_path  /home/www/cache/worklog.be levels=1:2 keys_zone=worklog:18m inactive=1d max_size=10g;
fastcgi_cache_path  /home/www/cache/example.com levels=1:2 keys_zone=example:18m inactive=1d max_size=10g;

keys_zone に設定しているパラメータは下記を参考に必要な分を設定してみました。リンクは FreeBSD の場合についてだけど、この設定ファイルは CentOS と FreeBSD 混在の環境で共有したいので、良くわからないがこれでよしとしてます^^;

WordPressの共通設定

ほぼ、要の設定です。色々な情報を選別して汎用的に使えるように試していったらこうなりました。

index  index.php;
error_page  404 /index.php?error=404;

set $is_mobile '';

# キャッシュを作成する場合のスマートフォンの判定処理
if ($http_user_agent ~* '(iPhone|iPod|Android.*Mobile|Windows.*Phone|dream|CUPCAKE|blackberry9500|blackberry9530|blackberry9520|blackberry9550|blackberry9800|webOS|incognito|webmate|Googlebot-Mobile)') {
	set $is_mobile 'mobile.';
}

# GET メソッド以外はキャッシュを作成しない
if ($request_method != GET) {
	set $do_not_cache 1;
}

# キャッシュされたらまずそうな物を適当に除外 (念の為に書いているのもある)
if ($request_uri ~* '/(wp-admin/|wp-login.php|wp-cron.php|xmlrpc.php|\??feed|sitemap.xml)') {
	set $do_not_cache 1;
}

# Cookie を持っていたらキャッシュを渡さない
if ($http_cookie ~* 'comment_author|wordpress_[a-f0-9]+|wp-postpass|wordpress_no_cache|wordpress_logged_in') {
	set $do_not_cache 1;
}

# アクセスされたら嫌なファイルを WordPress 内に置くときに
location ~ \.(txt|dat)$ {
	return 404;
}

# wp-config.php へはアクセスさせない
# ただ、Web からここへアクセスする必要がある時は設定しない方が良いと思う
location ~ /wp-config.php$ {
	return 404;
}

# リクエストは index.php に投げる
location / {
	try_files  $uri $uri/ /index.php?$args;
}

# 画像等はブラウザキャッシュを効かせる (6 ヵ月)
location ~ \.(jpe?g|png|gif|ico|css|js)$ {
	access_log  off;
	expires  6M;
}

# PHP は php-fpm で処理する。php-fpm へはソケットで渡すようにしてみた
# 各キャッシュの有効期限はこんな感じに
location ~ \.php {

	try_files  $uri /index.php;

	include  fastcgi_params;
	fastcgi_pass   unix:/var/run/php-fpm/php-fpm.sock;
	fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;

	fastcgi_no_cache      $do_not_cache;
	fastcgi_cache_bypass  $do_not_cache;
	fastcgi_cache_key     $is_mobile$scheme://$host$request_uri;
	fastcgi_cache_valid   200 2h;
	fastcgi_cache_valid   301 302 1h;
	fastcgi_cache_valid   404 1m;
	fastcgi_cache_valid   500 1s;
	fastcgi_cache_valid   any 5m;

}

バーチャルドメインの設定

最後はバーチャルドメインの設定です。

上記で散々細々書いたのでここはこんな感じにシンプルに書けます。

server {

	listen       80;
	server_name  worklog.be;
	root         /home/blog/worklog.be/htdocs;

	access_log  /home/blog/worklog.be/log/nginx-access.log combined;
	error_log   /home/blog/worklog.be/log/nginx-error.log warn;

	# キャッシュ on -> 0, off -> 1
	set $do_not_cache 0;

	# 利用するキャッシュキー
	fastcgi_cache  worklog;

	include  conf.d/global.conf;
	include  conf.d/wordpress.conf;

}

ドメイン名は 10 とか 20 とか詰め込みたいので、頻繁に触るファイルはなるべく可読性が良くなるように考慮したという感じです。

とりあえず、今回の本題は以上であとは駄文です。

WordPressの運用はNginxとApacheどちらが良いか

Nginx と Apache でそれぞれ複数の WordPress を運用しているのですが、実際にやってみてどちらが良いかっての書こうと思います。

これまでメインで利用していたという事もありますが、設定の簡単さやサクッと使いたい場合 Apache かなと思います。

ただし、そこそこのアクセスを捌かなければならないとなるとやっぱり Nginx かなという所です。

PHP だけを処理するというのであれば Apache の方が良いと思うのですが、WordPress は PHP 以外にも画像や CSS, JS 等の複数の静的ファイルを使うのでその場合は Nginx の方が良い結果になりました。特に、メモリ消費量は一目瞭然でした。

VPSはメモリが小さいのでここで節約できたメモリを他に回せるのが凄く大きなポイントです。

また、個人的に複数の WordPress を同時に効率よく運営するにはみたいなテーマがあったので、Nginx のキャッシュ機能も大変便利だと感じました。

これまでは WP Super Chache をメインに使って来ましたが、各ドメイン名毎に煩わしい設定をしなくてはならなかったのでこれから開放されたのはデカいです。

Nginxで作成されるキャッシュの削除方法の考察

Nginx で作成されたキャッシュは、特に何もしなければ有効期限が切れるまで削除されないのでそのままだとちょっと不便です。

「Nginx Cache Controller」という WordPress のプラグインを利用すると任意のタイミングで削除できるようになるようですが、設定が悪いのか上手く動作しなかったのと、ローカルだけではなくリバースプロキシとして別立てしている Nginx のキャッシュも同時に削除したいと思ったのでちょっと別の仕組みを用意してみました。

仕組み的には、各 Nginx にキャッシュを削除する CGI を設置して、WordPress を更新したら JSON を投げて該当するドメイン名のキャッシュを全て削除するという単純なもの。

WordPress の更新タイミングに関するフックについて少しハマりましたが、暫く動かして問題なさそうなので気が向いたらまた書こうと思います。