CentOS 7.0 + HTTP2 (h2o) + PHP7 + MariaDB で Wordpress を動かす

# 前置き

PHP 7 がリリースされたし (作業時点で PHP 7.0.2 が最新) 世の中は HTTP2 が当たり前になるだろうし Wordpress がどれくらい速くなるか体験したかったのでやってみたことの作業録。

当初は nginx を想定していたけど、 H2O の存在を知ったので、切替。

# 作業内容

## サーバーを調達

**さくらVPS 2G** を契約、カスタムOSインストールで `CentOS 7 x86_64` を選択

http://vps.sakura.ad.jp/

また、HTTP2 は SSL通信を用いるので、格安SSL証明書を購入する

なお、メールサーバーは Google Apps があるのでそれを使う

## CentOS 初期設定

### インストール作業

* 既存のパーティションを削除してインストール
* パッケージ選択はデフォルトのまま、変更なし
* root ユーザーと一般ユーザーの設定

**以後の作業はすべてSSH経由で行う**

インストールされたバージョン
```
$ cat /etc/redhat-release
CentOS Linux release 7.2.1511 (Core)
```

### ファイヤウォール

初期状態の確認

```
# firewall-cmd --list-all
public (default, active)
  interfaces: eth0
  sources:
  services: dhcpv6-client ssh
  ports:
  masquerade: no
  forward-ports:
  icmp-blocks:
  rich rules:
```

SSH はすでに開いているので、HTTPS (443) を開放する

```
# firewall-cmd --add-service=https --zone=public --permanent
success
# firewall-cmd --reload
success
# firewall-cmd --list-all
public (default, active)
  interfaces: eth0
  sources:
  services: dhcpv6-client https ssh
  ports:
  masquerade: no
  forward-ports:
  icmp-blocks:
  rich rules:
```

> 本来は nginx を立ち上げてから HTTPS を開放したほうが
> セキュリティ的には正解だと思う

### SSH ログインの設定

#### root ユーザーの SSHログイン不許可

```
# vi /etc/ssh/sshd_config
```

```
PermitRootLogin no
```

変更後、設定の再読込

```
systemctl reload sshd
```

#### 一般ユーザーを鍵認証のみ許可

一般ユーザーでログインし `~/.ssh/authorized_keys` にクライアントのSSH公開鍵を追記する
その後、クライアントから **パスワードなし で SSHログイン** できるか確認する

確認できたら、パスワード認証によるSSHログインを禁止する

```
# vi /etc/ssh/sshd_config
```

```
PasswordAuthentication no
```
変更後、設定の再読込

```
systemctl reload sshd
```

## SELinux を Permissive に

```
# setenforce Permissive
```

## MariaDB

> CentOS 7 から 標準のパッケージ群には MySQL はなくなり、
> MariaDB に置き換わっていた

### インストール

```
# yum install mariadb mariadb-server
```

### サービス起動

```
# systemctl enable mariadb.service
# systemctl start mariadb.service
```

### 初期セットアップ

```
# mysql_secure_installation
```

## PHP 7

### 必要なパッケージをインストール

```
# rpm -ihv ftp://195.220.108.108/linux/centos/7.2.1511/extras/x86_64/Packages/epel-release-7-5.noarch.rpm
# yum install libxml2-devel openssl-devel libpng-devel libjpeg-devel bzip2-devel libcurl-devel freetype-devel libmcrypt-devel libxslt-devel wget
```

### ソースを取得

```
# git clone --depth=1 -b php-7.0.2 https://github.com/php/php-src.git
```

### ビルド

```
# cd php-src/
# ./buildconf --force
# ./configure \
--with-zlib-dir \
--with-freetype-dir \
--enable-mbstring \
--with-libxml-dir=\
--enable-soap \
--enable-calendar \
--with-curl \
--with-mcrypt \
--with-zlib \
--with-gd \
--disable-rpath \
--enable-inline-optimization \
--with-bz2 \
--with-zlib \
--enable-sockets \
--enable-sysvsem \
--enable-sysvshm \
--enable-pcntl \
--enable-mbregex \
--enable-exif \
--enable-bcmath \
--with-mhash \
--enable-zip \
--with-pcre-regex \
--with-pdo-mysql \
--with-mysqli \
--with-mysql-sock=/var/run/mysqld/mysqld.sock \
--with-jpeg-dir=/usr \
--with-png-dir=/usr \
--enable-gd-native-ttf \
--with-openssl \
--with-fpm-user=USER \
--with-fpm-group=USER \
--with-libdir \
--enable-ftp \
--with-kerberos \
--with-gettext \
--with-xmlrpc \
--with-xsl \
--enable-opcache \
--enable-fpm
# make && make install
```

インストール結果

```
Installing shared extensions:     /usr/local/lib/php/extensions/no-debug-non-zts-20151012/
Installing PHP CLI binary:        /usr/local/bin/
Installing PHP CLI man page:      /usr/local/php/man/man1/
Installing PHP FPM binary:        /usr/local/sbin/
Installing PHP FPM config:        /usr/local/etc/
Installing PHP FPM man page:      /usr/local/php/man/man8/
Installing PHP FPM status page:      /usr/local/php/php/fpm/
Installing phpdbg binary:         /usr/local/bin/
Installing phpdbg man page:       /usr/local/php/man/man1/
Installing PHP CGI binary:        /usr/local/bin/
Installing PHP CGI man page:      /usr/local/php/man/man1/
Installing build environment:     /usr/local/lib/php/build/
Installing header files:          /usr/local/include/php/
Installing helper programs:       /usr/local/bin/
  program: phpize
  program: php-config
Installing man pages:             /usr/local/php/man/man1/
  page: phpize.1
  page: php-config.1
Installing PEAR environment:      /usr/local/lib/php/
--2016-01-16 19:21:01--  https://pear.php.net/install-pear-nozlib.phar
Resolving pear.php.net (pear.php.net)... 109.203.101.62
Connecting to pear.php.net (pear.php.net)|109.203.101.62|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 3579275 (3.4M) [text/plain]
Saving to: ‘pear/install-pear-nozlib.phar’

100%[===============================================>] 3,579,275    233KB/s   in 17s

2016-01-16 19:21:19 (207 KB/s) - ‘pear/install-pear-nozlib.phar’ saved [3579275/3579275]

[PEAR] Archive_Tar    - installed: 1.4.0
[PEAR] Console_Getopt - installed: 1.4.1
[PEAR] Structures_Graph- installed: 1.1.1
[PEAR] XML_Util       - installed: 1.3.0
[PEAR] PEAR           - installed: 1.10.1
Wrote PEAR system config file at: /usr/local/etc/pear.conf
You may want to add: /usr/local/lib/php to your php.ini include_path
/root/php-src/build/shtool install -c ext/phar/phar.phar /usr/local/bin
ln -s -f phar.phar /usr/local/bin/phar
Installing PDO headers:          /usr/local/include/php/ext/pdo/
```

## H2O

### 必要なパッケージのインストール

```
# yum install cmake
```

### ソースの取得

```
# cd ~/
# git clone --depth=1 https://github.com/h2o/h2o.git
# cd h2o
```

### ビルド＆インストール

```
# cmake -DWITH_BUNDLED_SSL=off .
# make && make install
```

### systemd で起動するために設定ファイル用意

```
vi /usr/lib/systemd/system/h2o.service
```

```
[Unit]
Description=H2O optimized HTTP server

[Service]
Type=forking
PIDFile=/var/run/h2o/h2o.pid
ExecStartPre=-/usr/bin/mkdir -p /var/run/h2o /var/log/h2o
ExecStartPre=-/usr/bin/chown USERNAME:USERNAME /var/run/h2o /var/log/h2o
ExecStart=/usr/local/bin/h2o -c /etc/h2o/h2o.conf -m daemon
ExecReload=/usr/bin/kill -HUP $MAINPID
LimitNOFILE=infinity

[Install]
WantedBy=multi-user.target
```

ちなみに、`php-fpm` は H2O が呼び出す

### H2O 設定ファイル

```
# mkdir /etc/h2o
# vi /etc/h2o.conf
```

```
user: USERNAME
pid-file: /var/run/h2o/h2o.pid
access-log: /var/log/h2o/access.log
error-log: /var/log/h2o/error.log
http2-reprioritize-blocking-assets: ON
max-connections: 1024
num-threads: 2

listen:
  port: 443
  ssl:
    certificate-file: /path/to/certificate/file.pem
    key-file: /path/to/private/key.pem

file.custom-handler:
  extension: .php
  fastcgi.spawn: "PHP_FCGI_CHILDREN=10 exec /usr/local/bin/php-cgi"
hosts:
  "DOMAIN_NAME:443":
    paths:
      /:
        file.dir: /home/USERNAME/wordpress/
        file.dirlisting: OFF
        redirect:
          url: /index.php/
          internal: YES
          status: 307
```

### SSL 証明書の用意

nginx の場合と同じように証明書を用意する

### サービスの起動

```
# systemctl start h2o.service
# systemctl enable h2o.service
```

### Wordpress の設置

省略。H2O 設定 `file.dir` に書いたように、一般ユーザーのホームディレクトリ以下に置いた `/home/USERNAME/wordpress`

## HTTP2 の確認

[HTTP/2 and SPDY indicator](https://chrome.google.com/webstore/detail/http2-and-spdy-indicator/mpbpobfflnpcgagjijhmgnchggcjblin?hl=ja) など を使用して HTTP2 で通信されていることを確認

# 終わってみて

だいぶ速い。体感で2倍〜10倍くらい？記事は空っぽの状態なので、今後 運用してみてどうなるか？

ベンチマークは取ってない。他にいくらでも出てくるので。

PHP をmakeするなんて久しぶりにやった。めんどくさいので今後は yum で入れる。パッケージを提供してるリポジトリはあった (動作は未確認) → [PHP 7 on CentOS/RHEL 6.7 and 7.1 via Yum](https://webtatic.com/packages/php70/)

## 言い訳

Wordpress のパーミッションが面倒だからって理由で 一般ユーザーで H2O を起動してしまってるけど良くないと思う。でも自分一人しか使わないサーバーだし。

## 関連しそうなサイト

[H2O - the optimized HTTP/2 server](https://h2o.examp1e.net/)
[H2OでPHP（がちょっとだけ動くまで）](http://uzulla.hateblo.jp/entry/2015/06/18/150942)

## 不明点

wp-config.php の生成ができなかった。手動で作った。で、今試しに wp-config.php を消してみたら今度は出来た。もやもやする。