Nginx で実用的な WordPress サーバを構築するメモ
こんにちは。野又でございます。久々にブログをしたためることができそうなお仕事をさせてもらいました。
今回は、ずいぶん枯れてきているらしい LEMP(Linux, Nginx, MySQL, PHP-FPM) 構成の WordPress サーバをもっとラクに作れないか考えました。
CentOS 7.1 を Minimal Install (最小インストール)した状態から全てメモしました。各パッケージのバージョンを yum の base/epel リポジトリのみで管理して良い場合にはオススメできます。
Nginx の設定で行ったこと
- URL パーマリンク対応
- WPtouch プラグイン向けの設定
- WP Super Cache プラグイン向けの設定(未検証)
- phpMyAdmin を設置し、データベースのメンテナンスを Web 経由で出来るようにする
- phpMyAdmin へのクラックを抑制するため、サービスポート変更 かつ BASIC 認証を付加
- WordPress 管理機能(ダッシュボード)へのクラックを抑制するため BASIC 認証を付加
その他、行った事
構築メモ
▼ パッケージの更新
インストール直後なので必ず実施します。通信確認も兼ねています。
yum -y update
▼ SELinux の無効化
※作業の簡略化のために sed による修正を多用しますが、今後のバージョン次第で問題になる可能性があります。
setenforce 0
sed -i -e 's/^SELINUX=.*/SELINUX=disabled/' /etc/sysconfig/selinux
▼ EPEL (Extra Packages for Enterprise Linux) のインストール
Nginx をインストールするために epel リポジトリを有効にします。
yum -y install epel-release yum clean all
▼ Nginx のインストール
epel リポジトリからインストールします。
細かい設定ファイルは本稿の後半で行います。
yum -y install nginx mkdir -p /var/cache/nginx/cache chown -R nginx:nginx /var/cache/nginx chown -R nginx:nginx /usr/share/nginx systemctl start nginx.service systemctl enable nginx.service
▼ PHP FastCGI Process Manager (PHP-FPM) のインストール
起動ユーザを nginx に統一し UNIX ドメインソケット経由での接続のみ受けられるようにします。
yum -y install php php-fpm httpd-tools
sed -i -e 's/^;*user *=.*$/user = nginx/' /etc/php-fpm.d/www.conf
sed -i -e 's/^;*group *=.*$/group = nginx/' /etc/php-fpm.d/www.conf
sed -i -e 's:^;*listen *=.*$:listen = /run/php-fpm/php-fpm.sock:' /etc/php-fpm.d/www.conf
sed -i -e 's/^;*listen\.owner *=.*$/listen.owner = nginx/' /etc/php-fpm.d/www.conf
sed -i -e 's/^;*listen\.group *=.*$/listen.group = nginx/' /etc/php-fpm.d/www.conf
sed -i -e 's/^;*listen\.mode *=.*$/listen.mode = 0660/' /etc/php-fpm.d/www.conf
chown -R nginx:nginx /var/lib/php/session/
systemctl start php-fpm.service
systemctl enable php-fpm.service
なお yum における依存関係のせいで Apache がこのタイミングで入ってしまいます。うっかり起動しないように mask しておきます。
systemctl mask httpd.service
▼ phpMyAdmin のインストール
phpMyAdmin は base リポジトリからのインストールになります。このインストールで php 関連モジュールがさらに追加されるため PHP-FPM を再起動しておきます。
yum -y install phpmyadmin chown -R nginx:nginx /usr/share/phpMyAdmin systemctl restart php-fpm.service
▼ MySQL(MariaDB) のインストール
MySQL を使うため MariaDB をインストールします。
本稿では my.cnf 関連のチューニングは行いませんので必要に応じて修正して下さい。
yum -y install mariadb mariadb-server systemctl start mariadb.service systemctl enable mariadb.service
▼ MySQL(MariaDB) の初期設定
MySQL を起動してから実行します。
mysql_secure_installation
root パスを決めたらあとは [Y] か [Enter] で進めます。
Enter current password for root (enter for none): [Enter]
Set root password? [Y/n] Y
New password: ********
Re-enter new password: ********
Remove anonymous users? [Y/n] Y
Disallow root login remotely? [Y/n] Y
Remove test database and access to it? [Y/n] Y
Reload privilege tables now? [Y/n] Y
▼ WordPress 用 DB と phpMyAdmin 用 DB を作成
wordpress のデータベース名を wordpress にしていますが、もっと別な名前が望ましいです。
また、接続用ユーザーの名称は admin 以外が望ましいです。
mysql -uroot -Dmysql -p******** -e "INSERT INTO user SET user='admin', password=password('@@@@@@@@'), host='localhost';"
mysql -uroot -Dmysql -p******** -e "CREATE DATABASE wordpress DEFAULT CHARACTER SET utf8;"
mysql -uroot -Dmysql -p******** -e "GRANT ALL ON wordpress.* to admin;"
mysql -uroot -Dmysql -p******** -e "source /usr/share/phpMyAdmin/sql/create_tables.sql"
mysql -uroot -Dmysql -p******** -e "GRANT ALL ON phpmyadmin.* to admin;"
mysql -uroot -Dmysql -p******** -e "FLUSH PRIVILEGES;"
▼ FTP サーバのインストール
セキュリティ的には宜しくないのですが、本稿ではログインユーザ名を nginx にして作業を簡略化しています。
yum -y install vsftpd
echo "nginx" > /etc/vsftpd/chroot_list
echo "nginx" > /etc/vsftpd/user_list
mkdir -p /etc/vsftpd/user_conf
echo "local_root=/var/www" > /etc/vsftpd/user_conf/nginx
sed -i -e 's/^#*anonymous_enable=.*/anonymous_enable=NO/' /etc/vsftpd/vsftpd.conf
sed -i -e 's/^#*chown_uploads=.*/chown_uploads=YES/' /etc/vsftpd/vsftpd.conf
sed -i -e 's/^#*chown_username=.*/chown_username=nginx/' /etc/vsftpd/vsftpd.conf
sed -i -e 's/^#*chroot_local_user=.*/chroot_local_user=NO/' /etc/vsftpd/vsftpd.conf
sed -i -e 's/^#*chroot_list_enable=.*/chroot_list_enable=YES/' /etc/vsftpd/vsftpd.conf
sed -i -e 's:^#*chroot_list_file=.*:chroot_list_file=/etc/vsftpd/chroot_list:' /etc/vsftpd/vsftpd.conf
echo "userlist_deny=NO" >> /etc/vsftpd/vsftpd.conf
echo "user_config_dir=/etc/vsftpd/user_conf" >> /etc/vsftpd/vsftpd.conf
systemctl start vsftpd.service
systemctl enable vsftpd.service
パスワードを与えれば FTP クライアントからログインできるようになります。
passwd nginx
New password: ********
Retype new password: ********
▼ WordPress のダウンロードと展開
epel にあるからと yum で入れると英語版が入ってしまうらしいです。 WordPress 自身がアップデート機能を持っているため yum で管理する必要は特にありません。よって本家から日本語版をダウンロードして展開することにします。
wget http://ja.wordpress.org/latest-ja.tar.gz -P /var/www tar xvzf /var/www/latest-ja.tar.gz -C /var/www chown -R nginx:nginx /var/www/wordpress mkdir -p /var/www/logs chown nginx:nginx /var/www/logs mkdir -p /var/www/fastcgi_cache chown nginx:nginx /var/www/fastcgi_cache
▼ /etc/nginx/nginx.conf の編集
今回は以下のような設定にしてみました。極端なパラメータがあるかもしれません。
vi /etc/nginx/nginx.conf
修正した部分を示します。
# For more information on configuration, see:
# * Official English Documentation: http://nginx.org/en/docs/
# * Official Russian Documentation: http://nginx.org/ru/docs/
user nginx nginx;
worker_processes auto;
worker_rlimit_nofile 131072;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
events {
worker_connections 2048;
use epoll;
multi_accept on;
}
http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for" $request_time';
access_log /var/log/nginx/access.log main;
server_tokens off;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 20;
client_header_timeout 20;
client_body_timeout 20;
reset_timedout_connection on;
types_hash_max_size 2048;
server_names_hash_bucket_size 128;
include /etc/nginx/mime.types;
default_type application/octet-stream;
#upstream
upstream php-fpm {
server unix:/run/php-fpm/php-fpm.sock;
}
#buffers
client_body_buffer_size 10K;
client_header_buffer_size 1k;
client_max_body_size 8m;
large_client_header_buffers 2 1k;
#gzip
gzip_static on;
gzip on;
gzip_http_version 1.0;
gzip_vary on;
gzip_comp_level 1;
gzip_types text/plain
text/css
text/xml
text/javascript
application/json
application/javascript
application/x-javascript
application/xml
application/xml+rss;
gzip_disable "MSIE [1-6]\.";
gzip_disable "Mozilla/4";
gzip_buffers 4 32k;
gzip_min_length 1100;
gzip_proxied off;
#open_file_cache
open_file_cache max=1000 inactive=20s;
open_file_cache_valid 30s;
open_file_cache_min_uses 2;
open_file_cache_errors on;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
if_modified_since before;
fastcgi_cache_path /var/www/fastcgi_cache levels=1:2 keys_zone=whole:64m max_size=1g inactive=1d;
# Load modular configuration files from the /etc/nginx/conf.d directory.
# See http://nginx.org/en/docs/ngx_core_module.html#include
# for more information.
include /etc/nginx/conf.d/*.conf;
# server {
# listen 80 default_server;
# listen [::]:80 default_server;
# server_name _;
# root /usr/share/nginx/html;
#
# # Load configuration files for the default server block.
# include /etc/nginx/default.d/*.conf;
#
# location / {
# }
#
# error_page 404 /404.html;
# location = /40x.html {
# }
#
# error_page 500 502 503 504 /50x.html;
# location = /50x.html {
# }
# }
}
▼ /etc/nginx/conf.d/phpMyAdmin.conf の新規作成
phpMyAdmin を任意のポート(本稿では 53306 番ポート)で動作させるようにします。
touch /etc/nginx/conf.d/phpMyAdmin.conf vi /etc/nginx/conf.d/phpMyAdmin.conf
追加した内容。
server {
root /usr/share/phpMyAdmin;
listen 53306;
server_name _;
access_log /var/log/nginx/phpMyAdmin.access.log;
error_log /var/log/nginx/phpMyAdmin.error.log;
location / {
index index.php;
}
location ~ \.php$ {
auth_basic "Authentication";
auth_basic_user_file /var/www/.htpasswd;
include fastcgi_params;
fastcgi_index index.php;
fastcgi_pass php-fpm;
fastcgi_cache_bypass 1;
fastcgi_no_cache 1;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_script_name;
}
}
▼ /etc/nginx/conf.d/WordPress.conf の新規作成
wordpress を 80 番ポートで使用します。本稿ではドメイン直下にインストールしています。
touch /etc/nginx/conf.d/WordPress.conf vi /etc/nginx/conf.d/WordPress.conf
追加した内容。
server {
listen 80;
server_name _;
root /var/www/wordpress;
access_log /var/www/logs/WordPress.access.log main;
error_log /var/www/logs/WordPress.error.log warn;
rewrite /wp-admin$ $scheme://$host$uri/ permanent;
location / {
index index.php;
try_files $uri $uri/ /index.php?q=$uri&$args;
port_in_redirect off;
if (-f $request_filename) { break; }
set $supercache_dir /wp-content/cache/supercache/;
set $supercache_file $document_root$supercache_dir${http_host}${uri}/index.html;
set $supercache_uri '';
set $do_not_cache '';
if (-f $supercache_file) {
set $supercache_uri $supercache_dir${http_host}${uri}/index.html;
}
if ($query_string ~ .*=.*) {
set $supercache_uri '';
}
if ($request_method != "GET") {
set $supercache_uri '';
set $do_not_cache 1;
}
if ($http_cookie ~* "comment_author_|wordpress_(?!test_cookie)|wp-postpass_" ) {
set $supercache_uri '';
set $do_not_cache 1;
}
if ($http_x_wap_profile ~ ^[a-z0-9\"]+) {
set $supercache_uri '';
set $do_not_cache 1;
}
if ($http_profile ~ ^[a-z0-9\"]+) {
set $supercache_uri '';
set $do_not_cache 1;
}
set $mobile '@p';
if ($http_user_agent ~* '(Android|iPad|Kindle|Silk)') {
set $supercache_uri '';
set $mobile "@t";
}
if ($http_user_agent ~* '(iPhone|iPod|incognito|webmate|Android.*Mobile|dream|CUPCAKE|froyo|BlackBerry|webOS|s8000|bada|IEMobile|Googlebot\-Mobile|AdsBot\-Google)') {
set $supercache_uri '';
set $mobile "@s";
}
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|-mobile-converter|PSP)') {
set $supercache_uri '';
set $mobile "@k";
}
}
location = /favicon.ico {
log_not_found off;
access_log off;
}
location = /robots.txt {
log_not_found off;
access_log off;
}
location ~* /\. {
deny all;
}
location = /wp-config.php {
deny all;
}
location = /wp-admin/admin-ajax.php {
include fastcgi_params;
fastcgi_pass php-fpm;
fastcgi_cache_bypass 1;
fastcgi_no_cache 1;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_script_name;
}
location ~ /(wp-login|install|setup-config|wp-admin/.*)\.php$ {
auth_basic "Authentication";
auth_basic_user_file /var/www/.htpasswd;
client_max_body_size 1024M;
include fastcgi_params;
fastcgi_pass php-fpm;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_cache_bypass 1;
fastcgi_no_cache 1;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_script_name;
fastcgi_param PHP_VALUE "upload_max_filesize=1000M";
fastcgi_param PHP_VALUE "post_max_size=1G";
}
location ~* \.(jpg|jpeg|png|gif|swf|bmp|ico)$ {
log_not_found off;
access_log off;
expires max;
break;
}
location ~* \.(txt|html|html|css|js)$ {
log_not_found off;
access_log off;
expires 1d;
break;
}
location ~* \.php {
try_files $uri =404;
include fastcgi_params;
fastcgi_pass php-fpm;
fastcgi_cache whole;
fastcgi_cache_key "$scheme://$host$request_uri$mobile";
fastcgi_cache_valid 200 30m;
fastcgi_cache_valid any 1m;
fastcgi_ignore_headers Cache-Control Expires;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_cache_bypass $do_not_cache;
fastcgi_no_cache $do_not_cache;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_script_name;
}
}
▼ BASIC 認証用 ID/PASS の作成
※ここでは ID に guest を用いますが、もちろん guest じゃないほうがいいです。
touch /var/www/.htpasswd
chown nginx:nginx /var/www/.htpasswd
htpasswd /var/www/.htpasswd guest
New password: ********
Re-type new password: ********
▼ Nginx の記述確認と再起動
確認コマンドを実行します。問題なければ syntax is ok が出力されます。
nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
サービスを再起動します。
systemctl restart nginx.service systemctl restart php-fpm.service
▼ firewalld を使わず iptables にする
各自のポリシー次第ですが、自分は iptables を使うようにしました。
yum -y install iptables-services
▼ 各種ポートの開放 (iptables)
FTP(20, 21) SSH(22) Web(80) phpMyAdmin(53306) を開けます。
固定 IP からの管理環境であれば 80/tcp 以外はできるだけ IP アドレスを用いて厳しく制限したいです。
vi /etc/sysconfig/iptables
その内容。
*filter :INPUT ACCEPT [0:0] :FORWARD ACCEPT [0:0] :OUTPUT ACCEPT [0:0] -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT -A INPUT -p icmp -j ACCEPT -A INPUT -i lo -j ACCEPT -A INPUT -p tcp -m state --state NEW -m tcp --dport 20 -j ACCEPT -A INPUT -p tcp -m state --state NEW -m tcp --dport 21 -j ACCEPT -A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT -A INPUT -p tcp -m state --state NEW -m tcp --dport 80 -j ACCEPT -A INPUT -p tcp -m state --state NEW -m tcp --dport 53306 -j ACCEPT -A INPUT -j DROP -A FORWARD -j DROP COMMIT
起動します。
systemctl stop firewalld.service systemctl mask firewalld.service systemctl start iptables.service systemctl enable iptables.service
▼ ログローテーション設定の追記 (logrotate)
ログの保存場所を追加したので、ログローテーションの設定も追記する必要があります。
vi /etc/logrotate.d/nginx
その内容。
/var/log/nginx/*log {
create 0644 nginx nginx
daily
rotate 10
missingok
notifempty
compress
sharedscripts
postrotate
/bin/kill -USR1 `cat /run/nginx.pid 2>/dev/null` 2>/dev/null || true
endscript
}
/var/www/logs/*log {
create 0644 nginx nginx
daily
rotate 10
missingok
notifempty
compress
sharedscripts
postrotate
/bin/kill -USR1 `cat /run/nginx.pid 2>/dev/null` 2>/dev/null || true
endscript
}
▼ MySQL データベースの定時バックアップ (mysqldump)
シェルスクリプトを作成し crontab 依存で定期的に dump をとります。
touch /etc/cron.daily/mysql_backup.cron chmod 755 /etc/cron.daily/mysql_backup.cron vi /etc/cron.daily/mysql_backup.cron
その内容。
#!/bin/sh
mysql_dump_dir=/var/www/mysql_backup/
mysql_dump_file=`date +%Y%m%d%H%M%S`.sql.gz
mkdir -p ${mysql_dump_dir}
/usr/bin/mysqldump -uroot -p******** -x --all-databases --lock-all-tables --hex-blob | gzip > ${mysql_dump_dir}${mysql_dump_file}
chmod 660 ${mysql_dump_dir}${mysql_dump_file}
chown nginx:nginx ${mysql_dump_dir}${mysql_dump_file}
find ${mysql_dump_dir} -mtime +15 -name "*.sql.gz" | xargs rm -f
いちど手動でキックしてみて、指定したディレクトリにダンプファイルが生成されているか確認します。
/etc/cron.daily/mysql_backup.cron
動作確認
ブラウザから以下にアクセスします(サーバの IP アドレスが ip.add.re.ss だとします)。
BASIC 認証が必要になっているはずです。
- http://ip.add.re.ss:53306/
- http://ip.add.re.ss/wp-admin/setup-config.php
以上となります。
参考サイト
- Recommended Nginx Configuration for WordPress
- Nginxを使ったもう一歩進んだWordPressチューニング | cloudrop
- [WordPress] nginxでモバイルとPCでテーマを分ける方法 | エバーセンス開発ブログ
- Nginx+PHP-FPMでUNIXドメインソケットを使っていてハマる | 設定やツールねた
- WordPressをnginxで利用するための設定例 - ぞえ の戯れ言
- WordPressを100倍速くする! MySQLの調整やnginx proxy cache | KRAY Inc
- Nginxのパフォーマンスを極限にするための考察 - Qiita