Let’s Encrypt でサイトの SSL 化

Let’s Entrypt という素晴らしいサービスが無料のSSL証明書が提供していると同僚に教えてもらったので、試しにこのサイトに導入することにしました。
このエントリーは導入過程のメモです。

Let’s Encrypt は Certbot というコマンドラインインターフェースを持っていて、証明書の取得とインストール、更新までコマンドでできるようになっているとのこと。なんとまあ便利ですね。

証明書の有効期限は90日間しかないので、crontab などで有効期限前に自動で更新していく運用が望ましいみたいです。ではそうしていきましょう。

事前に以下の準備をしておきます。

  • Really Simple SSL プラグインを WordPress にインストールしておく
  • ファイヤーウォールがあるならインバウンド 443 ポートを開けておく

また、環境としてはさくらのVPS(CentOS 6)で Nginx + WordPress を動かしている状態です。

証明書のインストールとWebサーバーの設定

サーバーに SSH でログインして、作業開始。
certbot-auto スクリプトをダウンロードして、 /usr/bin に移動、実行権限をつけて、実行。ウェブサーバーは Nginx なので、--nginx オプションをつける。

$ wget https://dl.eff.org/certbot-auto
$ sudo mv ./certbot-auto /usr/bin/certbot-auto
$ sudo chmod a+x /usr/bin/certbot-auto
$ sudo certbot-auto --nginx

これでインストールウィザードが始まる。 以下のくだりでは「2」と答えておくと、Nginx 設定ファイルにリダイレクトの設定を勝手に書き込んでくれる。

Please choose whether HTTPS access is required or optional.
-------------------------------------------------------------------------------
1: Easy - Allow both HTTP and HTTPS access to these sites
2: Secure - Make all requests redirect to secure HTTPS access
-------------------------------------------------------------------------------

設定を反映させる。

$ sudo service nginx reload

この状態でもうすでにSSL化はできていた。https でサイトにアクセスしてみると以下のような状況。

SSL証明書を表示確認しているところ

http 接続を https 接続に強制リダイレクトをかける。
certbot-auto が /etc/nginx/conf.d/default.conf に設定を書き込んでいるが、コメントアウトされているのでそれを外して有効にする。

     # Redirect non-https traffic to https
-    # if ($scheme != "https") {
-    #     return 301 https://$host$request_uri;
-    # } # managed by Certbot
+    if ($scheme != "https") {
+        return 301 https://$host$request_uri;
+    } # managed by Certbot

設定を反映させる。

$ sudo service nginx reload

最後に自動更新の設定。
毎週日曜日の5時に更新処理が走るように設定した例。

$ sudo crontab -e

0 5 * * 0 certbot-auto renew --post-hook "service nginx reload" >/dev/null 2>&1

Really Simple SSL プラグインを使う

インストールしてアクティベートすると以下のようなメッセージが表示される。

Relly Simple SSL Plugin

「Go ahead, activate SSL!」ボタンを押す。すると以下のようなメッセージが表示される。

SSL activated!  Don't forget to change your settings in Google Analytics en Webmaster tools.  More info.

えっと…、本当に簡単だな…。
Google Analytics と Webmaster tools の面倒も見ろとな。あとでね。

以上です。


P.S.

URLが変わるので、はてブ数などはリセットされてしまいます。まぁそれはそうだわな。
本文「likealunatic.jp」を検索 - はてなブックマーク


References

webpack にまつわるぐだぐだ。キャッシュ対策と CommonsChunkPlugin

webpack (version 2) の公式ドキュメントではバンドルファイルのブラウザキャッシュ対策として、ファイル名にハッシュ値を埋め込む方法が提案されている

こうするとアプリのコードを変更する度に、バンドルファイル名に埋め込まれたハッシュ値も更新され、ブラウザキャッシュ対策ができる、という寸法だが…。
当然ファイル名が変わるわけだから、<sript> タグも更新しなくてはならない。それを解決するには、HTML ファイルも動的に扱わなければならない。chunk-manifest-webpack-pluginhtml-webpack-plugin を導入し、HTML のテンプレーティングを行い…、となると今使っている Pug はどうなる…、となってさらにさらに掘り下げないといけなくなり、はっきり言ってソリューションとして無理がある。

閑話休題。

webpack をヘビーに使っていると、サードパーティーフレームワークやライブラリのコード(npm install でインストールしたようなモジュール)を出力ファイル(バンドルファイル)から切り離したくなる。 バンドルファイルにライブラリが直接含まれるが故に、以下のような事象に直面したことがある開発者は多いのではないだろうか。

  • 複数人で開発していて各自のライブラリのバージョンが微妙に異なり、Git経由でやり取りされるバンドルファイルに環境の差分までが含まれてしまう
  • 使っているライブラリが増えて、コンパイルがとても遅くなる

解決策として、フレームワークやライブラリはまとめて別のバンドルファイルにする、もしくは単独で配布されたものを <script> タグを読み込む、という解決方法を取ることもできる。 これを可能にするのが externals オプションで、ここで宣言された名前については、依存関係がグローバルスコープから参照されるようになる。

externals: {
  jquery: 'jQuery'
}

webpack.config.js に設定しておくと、 import jQuery from 'jquery'; というコードはグローバルスコープの jQuery を参照するようになり、バンドルファイルに jQuery のコードは含まれないようになる。 もちろんこの場合には jQuery は新たに別の <script> タグで読み込む必要ある。

よりスマートな解決策としての CommonsChunkPlugin

CommonsChunkPlugin を使うと、複数のバンドルファイルから共通の依存モジュールを切り出してくれる。 サードパーティーライブラリをアプリのコードと分割する、という使い方ももちろんできる。 公式で示されている設定は以下のようなものだ。

plugins: [
  new webpack.optimize.CommonsChunkPlugin({
    name: "vendor",
    minChunks: function(module){
      // node_modules のディレクトリ下に含まれるものだけに絞る
      return module.context && module.context.indexOf("node_modules") !== -1;
    }
  }),
  new webpack.optimize.CommonsChunkPlugin({
    name: "manifest", // 名前は "manifest" でないとダメ
    minChunks: Infinity // entryがいくつあろうと生成。省略可
  }),
]

サードパーティーコードを別にしたいだけなら vendor だけでも目的は果たせるが、manifest を入れると、webpack バンドル共通部分(ソースには webpackBootstrap とコメントが書かれている部分)が manifest.js として別ファイルに書き出される。こうするとビルドするたびに vendor のハッシュ値が変更されることを防げるとのこと。
でもこれ、先述のハッシュ値をファイル名に含めるキャッシュ対策をやっていないと、意味はなさそう。なぜならハッシュ値はバンドルファイルのコード内には現れないから。

manifest を定義した場合、以下のように manifest.js も読み込まないとコードは動かないので注意。

<script src="/js/manifest.js"></script>
<script src="/js/vendor.js"></script>
<script src="/js/bundle.js"></script>

References

WP Pusher による WordPress テーマの自動デプロイ

WP Pusher というプラグインを導入し、GitHub のレポジトリの master ブランチに push したらサイトの WordPress テーマが自動的に更新されるという運用にしてみた。

seckie/likealunatic: Like@Lunatic website source code

サイトの静的ファイルがテーマディレクトリの外に散在していた状態だったから、それもできなかったわけだ。今回自作テーマを大幅に整理したことで、テンプレートも静的ファイルもすべて1つのテーマフォルダに収めることができた。(まあ当たり前の状態になったというべきか…)

GitHub の Webhooks による自動更新は以前からやりたかったのだが、CI ツールを使ったことのない僕にはハードルが高かった。しかし調べてみると、プラグインでそういうものがある、という情報があった ので導入してみることにした。該当記事の紹介によると、ビルドを Travis CI で行い、その後 dist ブランチに自動的にプッシュ、それを Webhooks で拾って本番にデプロイ、というフローになっている。しかし僕の環境だとビルドはローカルでやっているので Travis CI を使うフローは不要になる。シンプルに GitHub と WP Pusher だけの形で実現できた。

ただしハマったポイントが一つある。

WP Pusher は公式プラグインディレクトリに置いていないので、FTP を使ってアップロードした。すると、該当ファイルとディレクトリのオーナーは当然その FTP ユーザーになる。それによってパーミッションの問題が発生。

このサイトは Nginx + WordPress で動作している。 Nginx を使っている場合、wp-content ディレクトリなどに対して nginx ユーザーに書き込み権限を与えておけば、 WordPress (PHP) から自動更新やらプラグインの追加削除が行えるようになる。そうでない場合、WordPress は FTP 経由でファイルを出し入れしようとして FTP 情報を入力するプロンプト画面を表示する。
WP Pusher による自動デプロイも例外ではなく、パーミッションが適切でないと WordPress がそのページを表示しようとしてしまい、正しく通信できないらしい。

ちなみにエラーは GitHub の 該当 Webhook のページ下方に “Recent Deliveries” というセクションがあるのでそこで確認できる。 Webhook を設定すると通信確認のためなのか Recent Deliveries に1つ通信が記録される。それがエラーになっていた場合、Response が “500” となっているはず。Body のセクションを確認すると「FTP credentials を入力してください」という感じの HTML が出力されている。

GitHub Webhook setting screen
これは正常な状態。

今回のケースでは wp-content 以下すべてのファイル、ディレクトリオーナーを nginx ユーザーに変更したら解決した。 ちなみにこのことは WP Pusher Troubleshooting のページにもちらっと記述があった…。なんだろうこの徒労感。

参考

サイトのアップデート

直近の仕事が延期になってぽっかりと時間が空いたので、このサイトのメンテを一気にやった。

  • Bootstrap のアップグレード(v.1 -> v.3)
  • タスクランナーを Grunt から gulp に乗り換え
  • CSS プリプロセッサは Stylus から Sass (indented syntax) へ乗り換え
  • JavaScript は ES2015 + Babel を Webpack でビルドする環境へ
  • WordPress テーマディレクトリの整理
  • WP touch プラグインを廃止。スマホ向けスタイルは Bootstrap ベースで自作
  • WP Pusher による自動デプロイ

何年もサボっていたのでもう色々古かった。 Bootstrap はタイポグラフィーが格段に良くなりました。感心。それとモバイルファースト感が増していて、時代が移り変わった感じがします。 とはいえ今回使った v3.3.7 は2016年7月のリリースバージョンとなっていて、そんなに最新のトレンドっていう訳でもないです…。 というかこのリリースノートを見る限り Bootstrap ってもうあまり活発にメンテされていない感じか。

さくらのレンタルサーバーからさくらのVPSに引っ越しした

実際に引っ越ししたのは5月のことなのだが、今更書く話。

さくらのVPSは仕事でも使っているのだが、使い勝手がよいので個人でも使うことにした。
このサイトはそちらに引っ越ししました。

Linuxの設定は問題ない…と思っていたのだが、旧レンタルサーバーと使いたい構成が異なった(Apache + MySQL + WordPress → Nginx + MySQL + WordPress)のと、メールサーバーをどうするかという課題があって結構手こずってしまった。

このサイトはWordPressで稼働しているのだが、今回はNginxで動かすことにした。Nginxを使うのは初めてだが、ネット上にいくらでもノウハウが転がっていたのであまり困ることはなかった。Nginxはその頃に 1.8.0 がリリースされたのでそれを使うことにした。メールサーバーはノウハウもないのでやりたくないぜ…と思ったので、Gmailに転送するだけにした。postfix設定についても探せばノウハウはたくさんあった。

しばらく運用してみたが、以前よりサイトが重くなっている。。VPSのスペックの問題かNginx + WordPressという構成の問題か…、分からないがこのまま様子を見よう。