Ansible と wp-cli で WordPress の構築を自動化してみた話

1日遅れてしまいましたが Ansible と wp-cli で WordPress の構築を自動化してみた話を書きます。

WordPress って良くも悪くも気軽に管理画面で設定を変えたりプラグインをインストールできてしまいます。簡単なのでついつい管理画面でオペレーションが完結していまいがちですが、誰が作ったプラグインかわからないものを気軽に本番環境に入れるのは怖いです。特にサイトのデータがぶっ壊れたときに売上に影響するようなものだと。

本当に求めているプラグインなのかどうか使ってみないとわからないこともあるし、じゃあテスト環境みたいなのと本番環境みたいなのを作ってテスト環境で動作検証してから本番環境で使おうという発想になってくるわけですが、

- そもそもテスト環境を作らず本番だけで運用している人って多いのでは？
- 作ってても本番環境と入っているプラグインに差異があり、プラグイン間の相性などの検証ができずテスト環境の意味が半減しているのでは？
- 複数 WordPress のサイトを持っている人は、インストール、設定、いつも決まったプラグインを入れて……と同じことを繰り返しているのでは？

など運用改善の余地がありそうです。そこで以前の Advent Calendar でもちょっと名前が出てましたが wp-cli と Ansible を組み合わせて使って構築を試してみました。

私は WordPress 初心者なので、一般的にどんな感じで構築しているのかよくわかっていなくてオレオレな感じですが、たとえばさくらのレンタルサーバにテスト環境と本番環境を構築する想定で Ansible Playbook を書いてみました。 SSH 接続で入れることが必須なので、スタンダードプラン以上で使えます。

たとえば下記のように定義しておきます。

```yaml:host_vars/username.sakura.ne.jp.yml
---
envs:
  staging:
    wp_cli_dir: ~/www/bin
    wordpress_dir: ~/www/staging
    mysql_dbname: '{{ ansible_ssh_user }}_wp_staging'
    mysql_dbuser: '{{ ansible_ssh_user }}'
    mysql_dbpass: dbpassword
    mysql_dbhost: mysqlXXX.db.sakura.ne.jp
    url: http://example.com/
    title: WordPress 練習サイト
    admin_user: youcune
    admin_password: adminpassword
    admin_email: admin@example.com
  production:
    wp_cli_dir: ~/www/bin
    wordpress_dir: ~/www/production
    mysql_dbname: '{{ ansible_ssh_user }}_wp_production'
    mysql_dbuser: '{{ ansible_ssh_user }}'
    mysql_dbpass: dbpassword
    mysql_dbhost: mysqlXXX.db.sakura.ne.jp
    url: http://stg.example.com/
    title: WordPress 練習サイト
    admin_user: youcune
    admin_password: adminpassword
    admin_email: admin@example.com
```

```yaml:roles/install/tasks/main.yml
---
- file: path={{ envs[env].wp_cli_dir }} state=directory
- get_url: url=https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar
    dest={{ envs[env].wp_cli_dir }}/wp validate_certs=no mode=0755
- file: path={{ envs[env].wordpress_dir }} state=directory
- shell: '{{ envs[env].wp_cli_dir }}/wp core download --locale=ja'
    chdir={{ envs[env].wordpress_dir }} creates={{ envs[env].wordpress_dir }}/index.php
- shell: '{{ envs[env].wp_cli_dir }}/wp core config --dbname={{ envs[env].mysql_dbname }} --dbuser={{ envs[env].mysql_dbuser }} --dbpass={{ envs[env].mysql_dbpass }} --dbhost={{ envs[env].mysql_dbhost }}'
    chdir={{ envs[env].wordpress_dir }} creates={{ envs[env].wordpress_dir }}/wp-config.php
- shell: '{{ envs[env].wp_cli_dir }}/wp core install --url={{ envs[env].url }} --title="{{ envs[env].title }}" --admin_user={{ envs[env].admin_user }} --admin_password={{ envs[env].admin_password }} --admin_email={{ envs[env].admin_email }}'
    chdir={{ envs[env].wordpress_dir }}
```

そして、テスト環境を構築するときは、

```bash
$ ansible-playbook -i hosts sites.yml --extra-vars env=staging --ask-vault-pass
```

本番環境を構築するときは、

```bash
$ ansible-playbook -i hosts sites.yml --extra-vars env=production --ask-vault-pass
```

のように指定します。プラグインなど追加したいときは `roles/install/tasks/main.yml` に書き、まずテスト環境での動作を確認してから env を切り替えて同様の内容を本番環境に乗せるという運用にしてみようと思います（wp-cli は `wp-cli plugin install` したときにプラグインがすでにインストールされている場合も終了コード 0 になるようなので、 Ansible 上でエラーハンドリングを考慮しなくても良さそうです）。 Ansible Playbook の全文は [GitHub](https://github.com/youcune/wordpress-ansible-sakura) にあげました。

いつもこう運用してるとか、もっといいアイデアがあったら是非コメントで教えてください。