LAMP環境（Debian 9 + PHP 7.1 + Apache 2.4 + MariaDB 10.1）を作る

ある日突然GCEインスタンスがうんともすんとも言わなくなってしまい、原因究明より新しく作り直した方が早そうなのでそうしました。
jessieのサポートも切れた事ですし。

原因究明はおいおい別記事でやるつもりなので、今回はGCEでWordPressが動く環境を作るまでの手順を書きます。
以前ブログに書いていた内容の最新版という感じです。[^1]

[^1]: インスタンスにログインできないのでこのままブラックボックス化しそう。しかも当のブログは別のCMSなのでまだ復旧できていない…。

※この記事では独り言などを脚注に押し込めているので、基本的に脚注は読まなくて良いです。

# GCEインスタンスへのSSH接続

作業マシンがWindowsなので、まずPuTTYでできるようにした。[^2]

[^2]: 起動ディスクを新しくしても、何故か最初からLinuxのユーザー（Googleアカウント名とは違うユーザー名で接続したい）も認証情報も存在していた。同じプロジェクト内だと別インスタンスでも共有されるのか？　と思ったけどスナップショットに存在する別ユーザーは居なかったりして謎。

- [PuTTYで公開鍵認証方式でのSSH接続を行う手順まとめ](https://qiita.com/sugar_15678/items/55cb79d427b9ec21bac2)

## ポート番号の変更

- 簡単に管理できるufwを使う
    - [ufwを使って簡単にファイアウォールを設定する](https://qiita.com/yoh-nak/items/46935af3c5c4036e93b3)
    - [UbuntuでSSHとSSHに関するファイアウォールの設定をする](https://yoshinorin.net/2016/10/17/ubuntu-ssh/)
- **まず他のポートを開けて、接続できる事を確認してから22番を閉じる**
    - セッション閉じずに複数セッションで確認するとより安全
- - ファイアウォールだけでなく**SSHの設定も変更する**
- 80番、443番も開ける
- *GCEの場合はWebの管理画面からも[ファイアウォール ルール](https://console.cloud.google.com/networking/firewalls/list)の変更が必要*なので注意
    - RDPなど使わない物は閉じてOK

```
sudo apt install ufw
sudo ufw allow 22/tcp <- 後で消す
sudo ufw allow XXX/tcp <- 変更したいポート番号
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo vi /etc/ssh/sshd_config <- ポート番号を書き換える
sudo service sshd restart
```

# swap領域作成

チューニングは後でも良いが、swap作成は（f1-microの場合）PHPのコンパイルに必要なので先に作っておく。
f1-microであれば2GBくらいあれば良い筈。

```
sudo dd if=/dev/zero of=/swapfile bs=1M count=2048
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
sudo vi /etc/fstab
```

```/etc/fstab
/swapfile none swap sw 0 0
```

# 事前に入れておくと良いパッケージ

```
sudo apt install git
sudo apt install unzip
sudo apt install xsel
```

その他お好みで。[^3] [^4]

[^3]: gitに関してはGCPのリポジトリにpushできなくなっており、自分でビルドしなおす必要があるかも。オレオレ証明書とか使ってないのにな…。

[^4]: ↑とか思いながら他の作業を進めていたらpush出来るようになっていたので、一時的な問題だったらしい。

# MariaDBのインストール

- [Google Compute Engine で MySQL をセットアップする方法](
https://cloud.google.com/solutions/setup-mysql)

`sudo mysql_secure_installation` を忘れずに。基本的に全てyesで良い筈。
rootの初期パスワードは空。

## バックアップしてあったSQLを読み込ませる

MariaDBになってから `sudo` を付けないとログインできない模様。

```
sudo mysql -u root -p
```
```sql
create database wordpress;
exit
```
```
sudo mysql -u root -p wordpress < filename.sql
```

## WordPress用ユーザー作成

```sql
create user username@localhost identified by 'password';
grant all on wordpress.* to username@localhost;
select Host, User, Password from mysql.user; # 確認
```

# Apacheのインストール

- [基本的な Apache ウェブサーバーの実行](https://cloud.google.com/compute/docs/tutorials/basic-webserver-apache)

```
sudo apt update && sudo apt install apache2 -y
sudo apt install apache2-dev # PHP動かすのに必要（と思う）
```

## 必要なモジュールの有効化

WordPressではmod_rewriteが必須。

```
sudo a2enmod rewrite
sudo a2enmod expires
sudo a2enmod headers
```

## SSLの設定

```
sudo a2enmod ssl
```

詳細は[Google Cloud Platformでの独自ドメイン関連まとめ](https://qiita.com/yukari-n/items/5facc46317246ded4c05#google-compute-engine)を参照。

SSLを使う場合は**設定ファイルに証明書の指定が必要**なので注意。
Apacheの設定ファイルのシンタックスチェックは `sudo apachectl configtest` で行える。

終わったら[SSL Server Test](https://www.ssllabs.com/ssltest/)でチェック。

Chromeでサイトを確認する際、強制的にhttpsにリダイレクトされて困る場合はHSTSの設定を削除する。

- [Chromeでhttpからhttpsへ強制リダイレクトされる場合の対処法
](https://i-think-it.net/chrome-http-https-force-redirect-approache/)

# PHPのインストール

## MPM eventを使用しない場合

これを入れれば良い。
https://packages.debian.org/sid/php7.1

ソースリストに、サーバーの場所に近いミラーを追加。

```/etc/apt/sources.list
deb http://ftp.us.debian.org/debian sid main
```

```
sudo apt install php7.1
sudo apt install php7.1-mysql php7.1-xml php7.1-curl # 必要なものは適宜
```

## MPM eventを使用する場合

ThreadsafeなPHPを自分でコンパイルする必要がある。

- [PHP7.1を関連ライブラリと共にインストール（ソースからコンパイル）for Apache2.4+CentOS7.4](https://qiita.com/shadowhat/items/a9ec289b44af9a8e8ad3)

f1-microなどメモリが少ない場合や高速化を図る場合はMPM Eventは必須かと。

以前の環境をチェックできる場合は `php -i | grep configure` や `php -m` で調べておく。

### 必要なライブラリを入れておく

```
sudo apt install libbz2-dev
sudo apt install libxml2-dev
sudo apt install libc-client-dev
sudo apt install libcurl4-openssl-dev
sudo apt install libjpeg-dev
sudo apt install libpng-dev
sudo apt install libfreetype6-dev
sudo apt install libxpm-dev
sudo apt install libgd-dev #GD
sudo apt install libkrb5-dev # Kerberos
sudo apt install libmcrypt-dev
sudo apt install libgmp-dev
sudo apt install libpspell-dev
sudo apt install libreadline-dev
```

### コンパイルとインストール

```
wget --trust-server-names http://jp2.php.net/get/php-7.1.16.tar.gz/from/this/mirror
tar xvzf php-7.1.16.tar.gz
cd php-7.1.16

./configure --disable-dba --disable-rpath --enable-calendar --enable-cgi --enable-exif --enable-ftp --enable-gd-native-ttf --enable-gd-jis-conv --enable-huge-code-pages --enable-maintainer-zts --enable-debug --enable-mbstring --enable-mbregex --enable-fpm --enable-bcmath --enable-opcache --enable-pcntl --enable-inline-optimization --enable-shmop --enable-soap --enable-sockets --enable-sysvsem --enable-sysvshm --enable-sysvmsg --enable-wddx --enable-zip --with-apxs2=/usr/bin/apxs2 --with-bz2 --with-curl=/usr/local --with-gmp --with-mhash --with-pcre-regex --with-fpm-user=www-data --with-fpm-group=www-data --with-gd=/usr/include --with-freetype-dir=/usr/local/src/phpmodule/freetype-2.7 --with-jpeg-dir=/usr/local/lib --with-png-dir=/usr/local --with-iconv-dir=/usr/local --with-libxml-dir=/usr/local --with-mcrypt=/usr/local --with-tsrm-pthreads --with-openssl --with-pspell --with-readline --with-xpm-dir=/usr --with-gettext --with-pdo-mysql --with-mysqli --with-mysql-sock=/var/run/mysqld/mysqld.sock --with-kerberos --with-zlib --with-zlib-dir=/usr --without-pear

sudo make
sudo make install
```

apxs2の場所は `whereis apxs2` で探す。
他のライブラリも同様。

make中に `[Makefile:297: sapi/cli/php] Error 1` などが出たら `sudo make clean` してからやり直す。

最後に php.ini を /usr/local/lib に作る。

```
sudo cp php.ini-production /usr/local/lib/php.ini
```

### ApacheにPHPを設定

このままだと設定ファイルが不足しており、サーバー上でPHPが動かない。
パッケージとしてインストールできるPHP7.1の設定ファイルをコピー（またはリネーム）し、

```
sudo a2dismod php7
sudo a2enmod php7
```

で読み込ませる。

```/etc/apache2/mods-available/php7.conf
<FilesMatch ".+\.ph(ar|p|tml)$">
    SetHandler application/x-httpd-php
</FilesMatch>
<FilesMatch ".+\.phps$">
    SetHandler application/x-httpd-php-source
    Require all denied
</FilesMatch>
<FilesMatch "^\.ph(ar|p|ps|tml)$">
    Require all denied
</FilesMatch>
<IfModule mod_userdir.c>
    <Directory /home/*/public_html>
        php_admin_flag engine Off
    </Directory>
</IfModule>
```

## mbstringの設定

自分でビルドしなかった場合は入れる。

```
sudo apt install php7.1-mbstring
```

いずれの場合も、php.iniにmbstringの設定が必要。

- [日本語環境の設定 - mbstring](https://webkaru.net/php/mbstring-php-ini/)

# チューニング

## MySQLのチューニング

現状 MyISAM が多いのでバッファサイズを上げる。
キャッシュなども必要に応じて。

```sql
set global key_buffer_size = 256 * 1024 * 1024;
set global read_buffer_size = 1 * 1024 * 1024;
set global query_cache_limit = 16 * 1024 * 1024;
```

クエリキャッシュはMySQL 8だと使えないらしい。

## PHPのメモリ上限変更など

```php.ini
memory_limit = 256M
realpath_cache_size = 8192k
realpath_cache_ttl = 300
```

```wp-config.php
define('WP_MEMORY_LIMIT', '128M');
define('WP_MAX_MEMORY_LIMIT', '256M');
```

## PHP-FPMとFastCGI

※私の環境だとFPMを有効化すると

> お使いのサーバーの PHP では WordPress に必要な MySQL 拡張を利用できないようです。

というWordPressのエラーが出てしまうので、とりあえずFastCGIのみ（CGI/FastCGI）で動かしています。

---

- [FastCGI PHP の設定方法 と mod_php とのパフォーマンスの比較（Apache httpd）](https://blog.apar.jp/linux/8208/)

mod_fcgidをインストール。

```
sudo apt install libapache2-mod-fcgid
```

スクリプトを作成。

```
sudo vi /usr/local/bin/php-wrapper
```

```/usr/local/bin/php-wrapper
#!/bin/sh
export PHP_FCGI_MAX_REQUESTS=5000
export PHP_FCGI_CHILDREN=0
exec /usr/local/bin/php-cgi
```

パーミッション変更。

```
sudo chown www-data /usr/local/bin/php-wrapper
sudo chmod u+x /usr/local/bin/php-wrapper
```

モジュール版を無効化。

```
sudo a2dismod php7
```

Apacheの設定ファイルを編集。

- `Options` に `ExecCGI` を追加
- `AddHandler` を指定
- `FcgidWrapper` を指定
- `FcgidMaxRequestsPerProcess` を指定

詳細は参考リンクを見てください。

PHP-FPMをインストールして有効化。

```
sudo apt install php7.1-fpm
sudo a2enmod proxy_fcgi setenvif
sudo a2enconf php7.1-fpm
```

`phpinfo()` で Server API が FPM/FastCGI となっていればOK。

## MPM Event

色々悩んでたけど自分で記事書いてた（すっかり忘れていた…）。

- [GCEにWordPress乗っけたらメモリが足りなかった件（解決済み）](https://qiita.com/yukari-n/items/ba760e013f5d69a4114c#追記)

```mpm_event.conf
<IfModule mpm_event_module>
        StartServers             1
        ServerLimit              8
        ThreadLimit              4
        ThreadsPerChild          4
        MinSpareThreads          4
        MaxSpareThreads          16
        MaxRequestWorkers        32
        MaxConnectionsPerChild   0
</IfModule>
```

## OPcache

- [OPcache導入してみた！（速さ検証もあるよ！）]( https://qiita.com/morimorim/items/fb39ae7d673a8b88f413)

opcache.so を読み込まないと有効化されません。
何故最初からファイルに書いておいてくれないのか。

```php.ini
zend_extension=opcache.so
```

GUIでチェックするツールは[opcache-gui](https://github.com/amnuts/opcache-gui)が好きです。

## Memcached

設定途中。

- [PHPでmemcachedを使うときのモジュールパフォーマンス比較](http://masayuki14.hatenablog.com/entry/20120710/1341877792)

```
sudo apt install memcached
sudo service memcached start
sudo apt install php-memcached
```

```php.ini
ession.save_handler = memcache
```

# WordPressの設定

- WPのフォルダの所有権をApacheに変えておく
    - wp-config.phpなどはアクセス権もチェックする 
- Googleなどのログイン認証はやり直しになる
    - 自動バックアップ等の設定は要見直し