Digital OceanのDropletでWordpressブログを立ち上げてCloudFrontでアクセスできるようにするまで(前編)

お仕事で使っていたWordpressのブログを刷新というか、整理したので、作業分をメモとして残しておきます。大体、半年後くらいになんかいじろうとして全てを忘れているといういつものオチが待っているのをふせぐために。

Digital Oceanで構築

Digital OceanはKVMベースのいわゆるVPSで、RAM 512MB/1 CPU/20GB SSD DISK/1TB TRANSFERというスペックで月あたり$5という安さが魅力だなーということで選択(使ってみた感じ、CPUも充分早いと思っています)。さくらVPSなんかと比較すると日本に設置されていないので、ネットワークのレイテンシ的なところはあまりよくないんですが、今回の場合、管理画面は日本から直接アクセスするものの、サイト自体はCloudFrontのカスタムオリジンとなるだけでネットワークの性能や転送速度は重視しないところもポイントです。

というわけで、適当にDropletを起動します。RegionはSanFrancisco1を選び、Linux DistributionはUbuntu 12.04 x64にしました。特に意味はないんですが、一番慣れているので。Digital OceanではWordpress構築済みのUbuntuも提供されているのですが、その構成を把握する手間考えると、自分で構築でよいかなーということで、素のUbuntu 12.04を選択しました。

起動時はホスト名を設定するのですが、ちゃんとDNSを設定していると、逆引きもそれに合わせて設定してくれるようです。なので、正しいホスト名を入れた上で、設定しておきましょう。逆引きもできるに超したことはないですよね。あとは、ログイン用にSSHの公開鍵を設定しておくほうがよいです。rootのパスワードも一応提供されるんですが、鍵認証のほうがいいよね、ということで。そこまで選択して、Create Dropletをクリックすると、1分ほどで起動してきます。

UbuntuとWordpressのセットアップ

起動すると、メールも来ますし、Digital Oceanの管理画面で、Dropletsを選べばIPアドレスが分かるはずです。これを元にとりあえずDNS設定しておきましょう。その上で、SSHでログインします。公開鍵を登録しておけば、rootにパスワードなしで入れるので、とりあえずそれで入ります。その上で、とりあえず、一般ユーザを適当に作り、rootでのSSHログインを無効にします。んで、作った一般ユーザがsudoできるように設定します。できれば、SSHの待ち受けポートも変えておいたほうがいいかもしれないですね。

と、ここまでが、とりあえずログイン後の最低限の設定かと思います。この後は、Wordpressの構築です。といっても手間的にはそれほどのもんでもありません。

とりあえず、以下のような手順で構築します。

  1. パッケージをとりあえず最新に。
  2. MySQLのインストール
  3. MySQLのデータベースとユーザ作成
  4. Apacheのインストール
  5. PHPのインストール
  6. ApacheのVirtualHost関係を設定
  7. ApacheとMySQLのメモリ使用量を削減
  8. Wordpressのインストール
  9. DNSをVirtualHostの設定に合わせて行う

一応、コマンドもメモりながら、ざっと流れを追います。

1. パッケージアップデート

特になにも入ってないし、怖いものもないので、ゴリッと全部アップデートしておきます。

# apt-get update && apt-get dist-upgrade

2. MySQLのインストール

# apt-get install mysql-server
rootのパスワードを聞かれるので、適当に設定します。

3. MySQLのデータベースとユーザを作成

$ mysql -u root -p
mysql> create database `wp_test-blog`;
Query OK, 1 row affected (0.00 sec)
mysql> grant create,select,insert,update,delete,drop on `wp_test-blog`.* to 'wpadmin'@'localhost' identified by 'hogehogehoge';
Query OK, 0 rows affected (0.00 sec)
mysql> flush privileges;
Query OK, 0 rows affected (0.01 sec)

4. Apacheのインストール

.htaceessの自動更新などもあったりで、Wordpressは性能を気にしないのであれば、Apacheで動かす方がいいのかなぁと勝手に思い込んでいますが、実際のところはどうなんですかね。

# apt-get install apache2-mpm-prefork
特に性能に必要性もないので、preforkのMPMを入れます。

5. PHP関係のインストール

Wordpressに必要なPHPのExtensionも一緒に入れます。
# apt-get install php5 php5-mysql php5-curl

6. ApacheのVirtualHostでWordpressが動作するように設定

まずは、最終的に、rewite,expires,headersあたりのモジュールを使うので、それもロードするように以下のコマンドを実行して設定しておきます。

# cd /etc/apache2/mods-enabled
# ln -s ../mods-available/rewrite.load .
# ln -s ../mods-available/expires.load .
# ln -s ../mods-available/headers.load .

各種ファイルは/srv/apache/に置く方向で、後からStaticpressでの静的HTMLの生成もあるので、Wordpressの実体を置くディレクトリとDocumentRootはAliasを使って分離します。こうすると、DocumentRootに置かれるのは静的なHTMLファイルのみなので、なんかあったら、まとめて削除→再生成や運用によっては、CloudFrontではなく、S3にこのディレクトリ以下のファイルをまとめて転送するようにすればよいので、こうしています。

# cat > /etc/apache2/sites-enabled/010-test-blog
<VirtualHost *:80>
      ServerName origin.test-blog.qweasd.net
      DocumentRoot /srv/apache/htdocs/test-blog.qweasd.net
      ErrorLog /srv/apache/logs/test-blog.qweasd.net-error_log
      CustomLog /srv/apache/logs/test-blog.qweasd.net-access_log combined

      Alias /_wp/ /srv/apache/htdocs/wordpress/test-blog/
      <Directory "/srv/apache/htdocs/wordpress/test-blog">
              AllowOverride All
              Options FollowSymLinks
              Order allow,deny
              Allow from all

              ExpiresActive On
              ExpiresDefault "now"
              Header set Cache-Control "no-cache, no-store, must-revalidate, max-age=0, proxy-revalidate, no-transform"
              Header set Pragma "no-cache"
      </Directory>

      <Directory "/srv/apache/htdocs/test-blog.qweasd.net/">
              AllowOverride All
              Options FollowSymLinks
              Order allow,deny
              Allow from all
      </Directory>
</VirtualHost>

実際には、これにキャッシュ制御のExpiresやRewriteのルールを追加していくわけですが、とりあえず、Wordpressを動かすのが目的なので最低限の設定だけをまずは書きます。

7. ApacheとMySQLのメモリ使用量を削減

とりあえず、このDropletsは512MBしかメモリを積んでいませんし、Wordpressの管理画面は記事編集する人がたまにアクセスする程度で実際のアクセスはCloudFront経由しかありません。というわけで、同時アクセスの性能は全くと言ってよいほど必要ありません、それよりも、なにかの拍子にOOM Killerが発動してApacheとかMySQLが落ちるほうがよっぽど不幸です。というわけで、メモリを極力使わないように設定を調整しておきます。(実際、作業してるといきなりmysqlがいなくなって焦りました。)

Apacheは起動するプロセス数を削減しておきます。/etc/apache2/apache2.confのMPMの設定を調整します。
  StartServers          1
  MinSpareServers       1
  MaxSpareServers       3
  MaxClients           15
  MaxRequestsPerChild   0

MySQLはInnoDB関係に割くメモリを削減しておきます。(割と目に見えて性能が落ちたので、普通はオススメしませんが...まあ、今回は用途が用途なので)
/etc/mysql/my.cnfに以下を追記しました。
innodb_buffer_pool_size = 32M
innodb_log_buffer_size = 8M
innodb_additional_mem_pool_size = 8M
query_cache_size = 50
thread_cache_size = 15

というくらいで、とりあえず、メモリ使用量はぐっと減ります。それに加えて小ネタですが、ttyが6つもあってで絶対つかわないので、2つに削減しておきます。

・/etc/default/console-setupのACTIVE_CONSOLES="/dev/tty[1-2]"に変更
・ttyの設定を錯誤
# rm /etc/init/tty[3-6].conf

8. Wordpressのファイルを展開

$ cd /srv/apache/htdocs/wordpress
$ tar zxpvf wordpress-3.6.1-ja.tar.gz
$ mv wordpress-3.6.1 test-blog

と、Wordpressのサイトからアーカイブを落としてきて展開します。 そして、wp-config.phpだけ調整します。

$ cp wp-config-sample.php wp-config.php

wp-config.phpは、DB_NAMEをwp_test-blogに、DB_USERはwpadminにします。DB_PASSWORDは上記サンプルでは、hogehogehogeですが、まあ適当に。あとは、認証ユニークキーを任意に設定しておきましょう。一応、Wordpress.orgで生成サービスも提供しているみたいですが、まあそこは適当に手でつくるのがいいんじゃないですかね。

9. DNSを設定

VirtualHostでは、origin.test-blog.qweasd.netとして設定しているので、それにあわせて、DNS側もそのホスト名が起動しているDropletsのIPを指すように設定をおこないます。実際には複数のWordpressを動かす気満々なので、Dropletsにはwp-origin.qweasd.netみないなAレコードを作った上で、orogin.test-blog.qweasd.netはwp-origin.qweasd.netへのCNAMEになるように設定をおこなっています。ちなみに、このへんは全部、Route53です。楽で良いですよ。

と、ここまでやれば、 http://origin.test-blog.qweasd.net/_wp/install.php にアクセスすればきっとちゃんと設定画面がでるはずです。それで、amdinの設定をすれば、とりあえず、http://origin.test-blog.qweasd.net/_wp/ でWordpressが動いているはず。

後編に続く

これで、とりあえず、Wordpressを動かすところまでは終了ですが、お仕事の場合、TV放映なども散発的にあって、アクセスの負荷が予想できなかったりするため、CloudFront経由でのアクセスで実際にはブログを提供する方向で設定を後編でしていこうかと思います。

考えたところでは、動的なページをそのままCloudFront経由でという構成も考えたのですが、ドメインが変わるなどの条件もあり、Locationヘッダの書換やら、生成されたHTMLのドメイン書換やら意外にCloudFrontのオリジンとして動かすことをかんがえるといろいろやるプラグインなりが必要そうです。しかし、自分のPHP力とWordpress力の無さをかんがえると、そういうプラグインを書くのが辛かったので、Staticpressで静的HTMLファイルを生成しつつ、そういった置換処理をフックして追加することでCloudFrontのカスタムオリジンとして静的HTMLファイルを提供することで対応しました。あと、実際のところ、ブログは日本語しか今のところないですし、S3に置いてしまえばそもそもCloudFrontいらないんじゃね?という話もあって、そっちの運用にも簡単に対応できるようにしておこうという保険的な心もあります。

実際、Staticpressで静的HTMLを生成するだけだと、WP Social Bookmark Lightで生成したいいねボタンなどのhrefまで相対パスになっちゃうとか、一部のドメインはうまく書き換えられないとか、X-Pingbackは書き換わってないとか、/無しのアクセスの場合に、originのホスト名を返してしまう問題などもあり、CloudFrontで運用することを考えるといくつかの対応が必要になってきます。そのへんの対応を後編ではメモとして残して置きたいな、と。

ただ、実際のところ、ソーシャルボタンの問題を除けば、StaticPressで静的HTMLを生成したあとに、S3に転送してしまえば大抵の問題は起こらないですし、S3はそうそうなことでは落ちないという意味での信頼性も高くなります。実際のところでは、ソーシャルボタン系をただしく生成するように↓上で、staticpress-s3を入れてS3でホストしてしまうのが最適な気が、いろいろやった結果ではしています。海外からのアクセスなんかもあれば、それをオリジンにするのがいいんでしょうかね。でも、その場合は、ドメイン問題が起こるのかな、相対パスへの書換で大抵はどうにかなりそうという気もしますが。

そんなこんなで、後編へ続く。