さくらのVPS借り直してCentOS 7でLEMP+HTTPS

お引っ越し

さくらのVPSに引っ越しました ::ハブろぐ を書いたのが2010年9月28日ということで、かれこれ4年も前のはなしです。東京リージョンのメモリ1GB HDD20GBで、プラン的にもまあまあ古い。当時、CentOS 5だったのも5.9までは上げたところで6系にアップグレードする勇気と手間を出せないまま、世間ではCentOS 7がリリースされました。

今回、メモリ2GB HDD200GBのプランを新しくレンタルしてセットアップすることにしました。標準ではCentOS 6でしたが、カスタムOSインストールでCentOS 7を選べたので、CentOS 7を入れて利用します。

CentOS 7|カスタムOSインストールガイド|さくらのVPS|さくらインターネット公式サポートサイト

LEMP Stack + HTTPS/SPDY

以前はnginxをフロントにして、後ろでapache+mod_phpを動かしてましたが、今回は純LEMP (Linux, Nginx, MySQL, PHP)としてセットアップすることにしました。なにげに初php-fpmでもあります。

あと、Google I/O 2014 - HTTPS Everywhereを聞いてきたのもあって、HTTPSSPDYに対応させたいなーという趣。(それをやろうとしたときに、そもそもCentOSが古くて辛かった)

基本的なセットアップ

基本的なとこの設定ログから。

いろいろ確認

cat /etc/redhat-release
CentOS Linux release 7.0.1406 (Core)

cat /proc/cpuinfo | grep processor
processor : 0
processor : 1
processor : 2

hdparm -t /dev/vda2
/dev/vda2:
 Timing buffered disk reads: 978 MB in  3.01 seconds = 325.27 MB/sec

うむ、グッドだ。ちょっとディスクアクセス速い気がするんだけど。

SELinux無効にしちゃう

しちゃう。

vi /etc/selinux/config

SELINUX=disabled

sshd_configを変更

ポート変更とか、ルートのリモートログイン禁止、鍵認証に限定とか、そういうの。

vi /etc/ssh/sshd_config
service sshd restart

firewall-cmd --permanent --remove-service=ssh
firewall-cmd --permanent --add-port=[sshの変更ポート]/tcp

ユーザー作成&公開鍵

あほむだよ ✧\\ ٩( 'ω' )و //✧

adduser ahomu
passwd ahomu
usermod -G wheel ahomu
su - ahomu
mkdir ~/.ssh
touch ~/.ssh/config
touch ~/.ssh/authorized_keys

chmod 700 ~/.ssh
chmod 600 ~/.ssh/config
chmod 600 ~/.ssh/authorized_keys

authourized_keys に手元の .pub 貼り付けてついでに reboot する。

yumフィーバー

以下 root で作業。

Epel

色々あるのでEpelいれとく。

wget http://download.fedoraproject.org/pub/epel/beta/7/x86_64/epel-release-7-0.2.noarch.rpm
yum install http://linux.mirrors.es.net/fedora-epel/beta/7/x86_64/epel-release-7-0.2.noarch.rpm

Nginx

/etc/init.d/nginx start とかじゃない!おしゃれ! systemctl start nginx とかにリダイレクトされてるっぽい。Fedoraい。

yum install nginx

service nginx start
systemctl enable nginx.service

Firewalld

CentOS 7ではiptablesがリストラされ、firewalldを使うらしい。iptablesの設定ファイル、いまいち分かりづらい気持ちだったので良い。

firewall-cmd --permanent --zone=public --add-service=http
firewall-cmd --permanent --zone=public --add-service=https
service firewalld restart

public (default, active)
  interfaces: eth0
  sources:
  services: dhcpv6-client http https
  ports: [sshの変更ポート]
  masquerade: no
  forward-ports:
  icmp-blocks:
  rich rules:

http://[ip address] でnginxのWelcomeページを確認する。

MariaDB

初★MariaDB、ブログのDB周りがMySQL4.xの残り香を伴った物体だったので、未知の不安があったけど問題なかった。

yum install mariadb mariadb-devel mariadb-libs mariadb-server

service mariadb start
systemctl enable mariadb.service
mysql_secure_installation

PHP (php-fpm)

インストールしたら恒例のtimezone設定を忘れずに。

yum install php-fpm php-common php-mbstring php-pecl-apcu php-gd php-mysql

service php-fpm start
systemctl enable php-fpm.service

アプリケーションの配備

PHP+MySQLなブログシステムを置いてます。

ディレクトリ

ディレクトリ類の準備。アプリ部分はGitHubからpullってる。

mkdir -p /var/log/nginx/havelog.ayumusato.com
mkdir -p /var/log/nginx/havelog.ayumusato.com/backend
chown -R nginx:nginx /var/log/nginx

cd /srv/www
git pull git@github.com:ahomu/havelog.ayumusato.com.git
chown -R nginx:nginx /srv/www/havelog.ayumusato.com/

ドメインの設定ファイル作成

mkdir /etc/nginx/sites-available
mkdir /etc/nginx/sites-enabled
touch /etc/nginx/sites-available/havelog.ayumusato.com.conf
cd /etc/nginx/sites-enabled/
ln -s /etc/nginx/sites-available/havelog.ayumusato.com.conf

nginx.conf をいじる

主要な追記ポイントの抜粋。proxy_set_header X-Forwarded-Proto $scheme; でリクエストされたときhttp/httpsのどちらだったかをバックエンドのアプリにちゃんと伝える必要がある。

# CPU3つ
worker_processes  3;

# Gzipまわり
gzip              on;
gzip_http_version 1.1;
gzip_vary         on;
gzip_comp_level   6;
gzip_buffers      16 8k;
gzip_types        text/plain text/xml text/css text/javascript
                    application/xhtml+xml application/xml
                    application/rss+xml application/atom_xml
                    application/javascript application/x-javascript
                    application/x-httpd-php;
gzip_disable      "MSIE [1-6]\.";

# プロキシーキャッシュ
proxy_cache_path  /var/cache/nginx levels=1:2
                  keys_zone=one:10m max_size=50m inactive=120m;
proxy_temp_path   /var/tmp/nginx;
proxy_cache_key   $scheme://$host$request_uri;
proxy_set_header  Host               $host;
proxy_set_header  X-Real-IP          $remote_addr;
proxy_set_header  X-Forwarded-Proto  $scheme;
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_set_header  Accept-Encoding    "";
proxy_connect_timeout 5;
proxy_send_timeout 10;
proxy_read_timeout 120;
proxy_hide_header X-Pingback;
proxy_hide_header X-Powered-By;
proxy_hide_header Etag;
proxy_hide_header Vary;
proxy_cache_use_stale timeout invalid_header http_500 http_502 http_503 http_504;
proxy_cache_lock on;
proxy_cache_lock_timeout 5s;

# 設定ファイルロード
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*.conf;

havelog.ayumusato.com.conf をつくる

書くのめんどうになってきたのでコピペ。コメントアウト部はHTTPS完全移行への迷い。yumから適当に入れたもので普通にSPDYも対応できてます。

upstream backend {
    server unix:/var/run/nginx-backend.sock;
}

upstream phpfpm {
    server unix:/var/run/php-fpm.sock;
}

#server {
#       listen         80;
#       server_name    havelog.ayumusato.com;
#       rewrite        ^ https://$http_host$request_uri? permanent;
#}

server {
    listen       80;
    listen       443 ssl spdy;

#    ssl                  on
    ssl_certificate      /etc/pki/tls/certs/startssl.crt;
    ssl_certificate_key  /etc/pki/tls/certs/startssl.key;
    ssl_dhparam          /etc/nginx/ssl/dhparam.pem;
    ssl_session_timeout  5m;
    ssl_protocols        SSLv3 TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers          'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128:AES256:AES:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK';
    ssl_prefer_server_ciphers on;
    ssl_session_cache shared:SSL:50m;

    server_name aho.mu havelog.ayumusato.com;
    access_log /var/log/nginx/havelog.ayumusato.com/access.log;
    error_log /var/log/nginx/havelog.ayumusato.com/error.log;
    root /srv/www/havelog.ayumusato.com;

    location ~ (^|/)\. {
        return 403;
    }

    location ~ (/private|/themes.*\.(html|htm)$) {
        return 403;
    }

    location / {
        index index.php index.html index.htm;

        set $do_not_cache 0;
        if ($http_cookie ~* sid ) {
            set $do_not_cache 1;
        }
        if ($request_method != GET) {
            set $do_not_cache 1;
        }
 
        proxy_no_cache     $do_not_cache;
        proxy_cache_bypass $do_not_cache;
 
        proxy_redirect     off;
        proxy_cache        one;
        proxy_cache_key    $scheme$host$uri$args;
        proxy_cache_valid  200 5m;
        proxy_cache_valid  any 1m;
        proxy_pass         http://backend;
#        proxy_redirect     http:// https://;
    }
}

server {
    listen unix:/var/run/nginx-backend.sock;
    server_name  _;
    root        /srv/www/havelog.ayumusato.com;
    access_log  /var/log/nginx/havelog.ayumusato.com/backend/access.log;
    error_log   /var/log/nginx/havelog.ayumusato.com/backend/error.log;
 
    gzip              off;
    gzip_vary         off;
 
    location / {
        index  index.php index.html index.htm;
        if (-e $request_filename) {
            expires 7d;
            break;
        }
        rewrite (.*(^|/)[^\./]+)$ $1/ permanent;
        rewrite ((\.(html|htm|php|xml|txt|js|json|css|yaml|csv))|/)$ /index.php last;
    }
 
    location ~ \.php$ {
        fastcgi_pass   phpfpm;
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
        include /etc/nginx/fastcgi_params;
        fastcgi_param  REMOTE_ADDR      $http_x_real_ip;
    }
}

SSL周り捕捉

サーバー証明書は、StartSSLつかって後述の参考サイト通りの手順に導入しています。

あと、HTTPS Everywhere でTLSの設定は先人の知恵に従えって書いてあったのでSecurity/Server Side TLS - MozillaWikiを参考に設定しています。openssl dhparam 2048は、/etc/nginx/ssl/dhparam.pem として保存しました。

一通り設定ができたら、Qualys SSL Labs - Projects / SSL Server Testでチェックして、良い感じになっているか確認にしておくと良いでしょう。うちのブログの結果はこんな感じになっています。件のOpenSSLの件とかもチェックしてくれるし、割と神ツール。

おしまい

LEMPでHTTPS+SPDYに対応した環境が用意できました。これでまた次の3年放置できる気がします( ˘ω˘) あとパフォーマンスチューニングみたなのやっておかないと...。

参考

LEMPのインストールまわり

nginxの設定まわり

a-blog cmsまわり

SSLまわり

どっかんどっかん

いろいろ検討しましたがDockerは結局使うのやめました。どうせブログは常設で中身いじることはないので。実験アプリつくるときはDockerにすればいいかなーと思いつつ、世間のPaaS使えばいいじゃん感。