ConoHa VPS（CentOS7）, nginx, PHP7, MariaDB10 で、Wordpress5 環境を構築する

## はじめに

久しぶりに VPS を触りたくなったのと、ずっと放置していた VPS と WordPress を新しく立て直したかったので、この辺の作業を記事にしました。
Dockerを使って爆速で…といったモダンなものではないので、これと言って真新しい内容ではありませんので、ご注意ください。

## 全体の流れ

1. ドメインの取得、VPS の用意
2. nginx のインストール
3. Firewall の設定
4. SSL証明書の取得と、nginx の設定
5. PHP7 のインストール
6. MariaDB のインストール
7. WordPress のインストール
8. セキュリティチェック

## ドメインの取得

[お名前.com]() や [Google Domains]() でドメインを取得してください。
この記事では、仮に**example.com**というドメインを取得したものとして解説します。

## VPS の用意

[ConoHa](https://www.conoha.jp/conoha/?btn_id=header_vps) で VPS を用意します。
今回用意したVPSのスペックは以下です。

|        |       512MBプラン |
|:-----------------|------------------|
| メモリ             |              512MB |
| CPU             |              1コア |
| SSD             |              20GB |
| イメージタイプ             |              CentOS 7 |

## VPS にドメインを設定する

ConoHa にログインしたら、左メニューの「DNS」を選択して、ドメイン設定画面に移動します。

右上の「+ドメイン」ボタンをクリックして、ドメインとDNSレコードを追加します。

|        |       DNSレコード |
|:-----------------|------------------|
| タイプ             |              A（通常） |
| 名称             |              @ |
| TTL             |              3600 |
| 値             |              ＜VPSのIPアドレス＞ |

サブドメインを用意して、blog.example.com のようなアクセスも許可したい場合は、
名称を blog にしたレコードも追加します。

## VPS 接続許可ポート設定

外部からVPSに接続できるポートを制限します。

左メニューの「サーバー」を選択して、設定を行うVPSのネームタグをクリックします。
「ネットワーク情報」の「接続許可ポート」で、SSH と Web のみチェックを入れます。

## コマンド集

以下の説明では省きますが、パッケージのインストール前後の状態確認や設定ファイルのバックアップなどを行いながら進めています。
その際、使ったコマンドや役に立ったコマンドをまとめておきます。

<details><summary>コマンド集</summary><div>

| コマンド | 説明 | 例 |
|---------|------|----|
| cp <コピー元ファイル名> <コピー先ファイル名> | ファイルをコピー | cp sshd_config sshd_config_backup |
| mv <元のファイル・ディレクトリ名> <新しいファイル・ディレクトリ名> | ファイル・ディレクトリの名前を変更 | mv wordpress myblog |
| mv <移動するファイル・ディレクトリ名> <既存のディレクトリ名> | ファイル・ディレクトリを既存のディレクトリの下へ移動 | mv myblog blogs |
| yum info <パッケージ名> | パッケージの配信元などを確認 | yum info nginx |
| yum list available &#124; grep <キーワード> | 利用可能なパッケージを、キーワードでフィルタリングして表示 | yum list available &#124; php |
| yum list installed &#124; grep <キーワード> | インストール済みのパッケージを、キーワードでフィルタリングして表示 | yum list installed &#124; php |
| systemctl status <サービス名> | サービスの状態を表示 | systemctl status nginx |
| systemctl start <サービス名> | サービスを開始 | systemctl start nginx |
| systemctl enable <サービス名> | サーバー再起動時に、自動的にサービスが立ち上がるようにする | systemctl enable nginx |
| firewall-cmd --get-default-zone | ファイヤーウォールのデフォルトゾーンを表示 |  |
| firewall-cmd --list-service --zone=<ゾーン名> | ファイヤーウォールのゾーンに設定されているサービスを表示 | firewall-cmd --list-service --zone=public |
| firewall-cmd --add-service=http --zone=<ゾーン名> --permanent | ファイヤーウォールのゾーンにサービスを設定。再起動後も有効 | firewall-cmd --add-service=https --zone=public --permanent |
| firewall-cmd --reload | ファイヤーウォール設定の再読み込み |  |
| nginx -t | nginx の設定が正しいかテスト |  |

</div></details>

## ユーザーの作成と、rootログイン禁止

`useradd`コマンドで、ユーザーを作成します。ユーザー sample を作るとしたら以下のようになります。

```
# useradd sample
```

新しいユーザーにはパスワードが設定されていないので、`passwd`コマンドでパスワードを設定します。
ユーザー sample のパスワードを設定するとしたら、以下のようになります。

```
# passwd sample
```

次に、root でのログインを禁止します。
root ログインに関する設定は、`/etc/ssh/sshd_config`ファイルにあります。
sshd_config ファイル内の、`PermitRootLogin`を`no`にすると、root ログインを禁止できます。

変更する前に、念のためsshd_config ファイルをコピーしておくと良いです。

```
# cp /etc/ssh/sshd_config sshd_config_backup
# vi /etc/ssh/sshd_config
```

```:sshd_config
PermitRootLogin no
```

## 前準備

nginx や PHP7、Certbot をインストールする際、いくつかのリポジトリを有効にする必要があります。
直接設定ファイルを編集してもよいのですが、今回は yum-config-manager を使うので、
事前にインストールしておきます。

```
# yum install yum-utils
```

次に、epel リポジトリとremi リポジトリを有効化します。
remi リポジトリは PHP7 のインストールに必要です。
また、epel は、remi リポジトリや Certbot のインストールで必要になります。

インストールの前に、remi リポジトリがインストールされているかどうか確認します。

```
# yum repolist
```

インストールされていない場合は、以下のコマンドでインストールします。

```
# yum install https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
# yum install http://rpms.remirepo.net/enterprise/remi-release-7.rpm
# yum-config-manager --enable remi-php73
```

**補足**
環境に合わせた PHP のインストール手順は、以下のサイトから確認することができます。
OS や インストールしたい PHP バージョンを選ぶと、ガイドが表示されます。

[Remi's RPM repository - Configuration wizard](https://rpms.remirepo.net/wizard/)

## nginx のインストールと設定

nginx を yum でインストールするために、以下の内容で、/etc/yum.repos.d/nginx.repo ファイル作成します。

[公式：nginxのリポジトリ設定](http://nginx.org/en/linux_packages.html#instructions)

```:/etc/yum.repos.d/nginx.repo
[nginx-stable]
name=nginx stable repo
baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key

[nginx-mainline]
name=nginx mainline repo
baseurl=http://nginx.org/packages/mainline/centos/$releasever/$basearch/
gpgcheck=1
enabled=0
gpgkey=https://nginx.org/keys/nginx_signing.key
```

今回は、新機能やバグフィックスが積極的に行われているmainlineをインストールします。
yum-config-manager で nginx-mainline リポジトリ を有効にしてインストールします。

```
# yum-config-manager --enable nginx-mainline
# yum info nginx
# yum install nginx
```

インストールが完了したら、起動、確認をします。
問題なかったら、自動起動設定をします。

```
# systemctl start nginx
# systemctl status nginx
# systemctl enable nginx
```

このままだと nginx のバージョンが表示されてしまうので、表示されないようにします。
/etc/nginx/nginx.conf の http ディレクティブに server_tokens off; を追加します。

```:/etc/nginx/nginx.conf
http {
  省略
  server_tokens off;
  省略
}
```

追加したら、設定が正しいかテストして、nginx を再起動します。

```
# nginx -t
# systemctl restart nginx
```

ついでに、ブログ用の設定ファイルも作成しておきます。
PHP や SSL の設定を書いていきます。
ここでは、/etc/nginx/conf.d/ に example.com.conf という名前で作成します。

## ポートの開放

http と https での接続を通すように、ポートを設定します。

まずは、デフォルトゾーンの確認します。

```
firewall-cmd --get-default-zone
```

私の環境では public でした。
次に、public ゾーンでのサービスを確認します。

```
firewall-cmd --list-service --zone=public
```

http と https サービスが入っていなかったので、追加します。
`--permanent` をつけて、再起動後も設定が保持されるようにしています。

```
firewall-cmd --add-service=http --zone=public --permanent
firewall-cmd --add-service=https --zone=public --permanent
firewall-cmd --reload
```

正しくポートが解放されたかどうか、以下のサイトでチェックしてみるのも良いかと思います。
[CMAN - Portチェックテスト【外部からのPort開放確認】](https://www.cman.jp/network/support/port.html)

## SSL 証明書の取得

Certbot を使って、Let's Encrypt の SSL 証明書を取得します。
証明書を取得するには、80番ポート（http）と443番ポート（https）が開いている必要があります。
開いていない場合、またはよくわからない場合は、firewall設定を参考に確認してください。

yum で Certbot をインストールします。
epel リポジトリから提供されているので、有効になっていない場合は、前準備を参考に epel を有効にしてください。

```
# yum install certbot python2-certbot-nginx
```

インストールが完了したら、以下のコマンドで証明書のインストールと nginx の設定を行います。
nginx の設定も自動で行いたい場合は、`certonly` オプションを付けずに実行していください。

```
# certbot --nginx certonly
```

Let's Encryp の証明書は90日で期限が切れるので、期限が切れる前に更新する必要があります。
手動で更新していると忘れそうなので、自動更新の設定を行います。

先ずは、以下のコマンドで、自動更新がうまく行くかどうかテストします。
`--dry-run` を付けて実行すると、ファイルに影響を与えません。

```
# certbot renew --dry-run
```

特にエラーもなく、正しく動作することが確認出来たら、cron で自動更新の設定を行います。
エラーが出た場合は、nginxの設定に日本語が含まれていないか確認してみてください。

今回は、『毎日２回、証明書の期限を確認して、期限が切れそうだったら更新する』というタスクを設定しいます。
`-u` はタスクを実行するユーザー、`-e` はタスクを設定するためのコマンドです。

ちなみに、`-r` は **すべてのタスクの削除** なので、タイプミスしてこれを指定してないか注意してください。
cron の設定方法は、特定のフォルダにファイルを作るなど、いくつかあるので、他の方法が良い人は調べてみると良いと思います。

```
# crontab -u root -e
0 0,12 * * * python -c 'import random; import time; time.sleep(random.random() * 3600)' && certbot renew 
```

設定が終わったら、正しく設定できているか確認します。

```
# crontab -l
```

実際の設定は、`/var/spool/cron/root` に記録されます。

ところで、毎日2回も走らせて大丈夫なの？と思う方もいるかもしれませんが、
`certbot renew` は期限が30日以上ある場合は何もしないので、大丈夫です。

各環境に合わせた取得、設定方法はCertbot公式サイトから確認できます。

[公式：Certbot設定方法](https://certbot.eff.org/)

証明書が取得できたので、SSL 接続できるように nginx の設定を行います。

ここでは、WordPress を /usr/share/nginx/blog/ の下に、example という名前で置くことを想定しています。

`ssl_prefer_server_ciphers on;` で、クライアントとサーバー間の通信で使う暗号化スイートに、サーバー側の設定を使うようにしています。

`ssl_protocols` はデフォルトで `ssl_protocols TLSv1 TLSv1.1 TLSv1.2` となるので、設定していません。
[公式：nginxのデフォルト設定](http://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_protocols)

また、80番ポートに来たアクセスは、443番ポートにリダイレクトするようにしました。

```:/etc/nginx/conf.d/example.com.conf
server {
  listen 443 ssl;
  server_name example.com;
  root /usr/share/nginx/blog/example;
  index  index.php;

  ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

  ssl_prefer_server_ciphers on;
}

server {
  listen 80;
  server_name example.com;

  return 301 https://$host$request_uri;
}
```

設定を保存したら、`nginx -t` で設定が正しいかテストし、問題なければ `systemctl restart nginx` で nginx を再起動してください。

## PHP7.3 のインストール

PHP の提供元が remi リポジトリになっているかどうか確認します。
なっていない場合は、[前準備]() 参考にして、remi リポジトリを有効にしてください。

以下のコマンドで、パッケージの情報を確認できます。

```
# yum info php
```

PHP7.3 といくつかのパッケージをインストールします。

```
# yum install php php-devel php-mbstring php-fpm php-mysql
```

次に、 php-fpm のユーザー設定を nginx に変更します。
user と group の項目を、以下のように変更してください。

```:/etc/php-fpm.d/www.conf
user = nginx
group = nginx
```

nginx から PHP のスクリプトを実行するための設定を行います。

```:/etc/nginx/conf.d/example.com.conf
server {
  listen 443 ssl;
  ＜省略＞
  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 -t` で設定が正しいかテストし、問題なければ `systemctl restart nginx` で nginx を再起動してください。

## MariaDB のインストールと設定

DB として、MariaDB をインストールします。
yum でインストールできるように、リポジトリを追加します。

/etc/yum.repos.d/ に MariaDB.repo を作成し、以下の設定で保存してください。
ここでは、10.3 のリポジトリを追加しています。

```:/etc/yum.repos.d/MariaDB.repo
# MariaDB 10.3 CentOS repository list - created 2019-03-31 11:50 UTC
# http://downloads.mariadb.org/mariadb/repositories/
[mariadb]
name = MariaDB
baseurl = http://yum.mariadb.org/10.3/centos7-amd64
gpgkey=https://yum.mariadb.org/RPM-GPG-KEY-MariaDB
gpgcheck=1
```

環境に合わせtリポジトリ設定は、以下のサイトから確認できます。

[公式：MariaDB Foundation - Downloads](https://downloads.mariadb.org/mariadb/repositories/#mirror=yamagata-university)

以下のコマンで、MariaDB をインストールします。

```
# yum install MariaDB-server MariaDB-client
# systemctl start mariadb
# systemctl status mariadb
# systemctl enable mariadb
```

インストールが完了したら、以下のコマンドを実行して、初期設定を行います。

```
# mysql_secure_installation
```

次に、日本語が扱えるように設定を行います。
/etc/my.cnf.d/ 以下に、client.cfn を作成して、以下のクライアント側の設定を行い保存してください。

```:/etc/my.cnf.d/client.cnf 
[client-mariadb]
default-character-set=utf8mb4

[tk@133-130-112-150 ~]$ cat /etc/my.cnf.d/server.cnf | grep utf8
character-set-server=utf8mb
```

サーバー側の設定は /etc/my.cnf.d/server.cnf の、`character-set-server`を
`utf8mb` に変更して保存してください。

```:/etc/my.cnf.d/server.cnf
character-set-server=utf8mb
```

上記の設定を行ったら、MariaDB を再起動してください。

```
# systemctl restart mariadb
```

## WordPress 用データベースの作成

WordPress で利用するデータベースと、作成したデータベースにアクセスできるユーザーを作成します。

以下の例では、データベース名は `wordpress`、ユーザー名は `wpuser`、パスワードは `Password` という設定で作成していますが、実際の環境では強度の高いパスワードを設定してください。

```
# mysql
> create database wordpress;
> grant all privileges on wordpress.* to "wpuser"@"localhost" identified by "Password";
> flush privileges;
```

## WordPress のインストール

/usr/share/nginx の下に blog ディレクトリを作成して、WordPress をダウンロード、解凍します。

[公式：WordPressダウンロード](https://ja.wordpress.org/download/)

```
# cd /usr/share/nginx/blog
# curl https://ja.wordpress.org/latest-ja.tar.gz -o wordpress.tar.gz
# tar xzfv wordpress.tar.gz
```

次に、wordpress ディレクトリの所有者とグループを nginx に変更します。
`-R` は設定を再帰的に反映させるオプションです。

ディレクトリの名前も example に変更しています。
変更は任意ですが、nginx の root 設定と整合性を取るようにしてください。

```
# chown -R nginx:nginx wordpress
# mv wordpress example
```

次に、WordPress のための nginx 設定を行います。
wp-config.php へのアクセス禁止と、パーマリンク設定を変更されても正しくルーティングできるようにする設定を行っています。

```:/etc/nginx/conf.d/example.com.conf
server {
  listen 443 ssl;
  ＜省略＞

# Deny access to wp-config.php
  location ~* /wp-config.php {
    deny all;    
  }

# Wordpress permanent link settings
  try_files $uri $uri/ /index.php?$args;
}
```

設定を保存したら、`nginx -t` で設定が正しいかテストし、問題なければ `systemctl restart nginx` で nginx を再起動してください。

nginx を再起動したら、ブラウザからサイトにアクセスしてください。
初回アクセス時に、使用するデータベース名、パスワードを聞かれるので、DB作成時に設定したものを入力してください。

## セキュリティチェック

最後に、セキュリティのチェックを行い、SSL や nginx の設定が正しく行われているか確認します。
以下のサイトからチェックできます。

以上の設定を行うと「A」評価でしたが、更にセキュリティを高めたいかたは、「サイト セキュリティ チェック A+」といったキーワードで検索すると参考になる記事が出てくると思うので、調べてみてください。

[Qualys SSL Labs](https://www.ssllabs.com/ssltest/index.html)

## おまけ

WordPress のバージョン情報も隠したかったので、「Meta Generator and Version Info Remover」という WordPress プラグインをインストールしました。

[WordPress プラグインページ：Meta Generator and Version Info Remover](https://ja.wordpress.org/plugins/meta-generator-and-version-info-remover/)

どのプラグインを使っても良いと思いますが、何れにせよWordPress のバージョン情報も隠した方が良いと思います。