Help us understand the problem. What is going on with this article?

PRで解説する、Jekyll + Heroku で HTTPS 対応

More than 3 years have passed since last update.

AppleのApp Transport Securityが延期になったとはいえ、SEO的にも信頼性的にも「とりあえず https にしとくか」みたいな時代になってきましたね 🤔

ということで、最近話題の Let's Encrypt を使って Jekyll + Heroku で構成されているRailsガイドを HTTPS に対応してみました。

具体的な実装は下記のプルリクエスト (以下、PR) で公開しています。

Enable SSL in Production #277
https://github.com/yasslab/railsguides.jp/pull/277

上記PRから汎用的なコミットをpickupして、1つずつ解説していこうと思います。

  • :beginner: Let's Encryptの使い方や、SSL証明書の取得手順などについては総合ポータルをご参照ください。
  • :warning: 本番環境で動作確認するのは危険なので、HerokuのFork機能などでテスト用の環境を作り、そこで動作確認しましょう。

TL;DR

1. Add acme_challenge gem to be certified

Let's EncryptでSSL証明書を取得するためには、特定のURLにアクセスしたら特定の結果を返す必要があります (ACME CHALLENGEと呼ばれています)。環境変数を使えば良さそうですが、「Jekyllで環境変数を扱うにはどうしたら良いのか?🤔」という点で結構はまっていました :sweat:

_pluginを使った実装とか色々と試してみましたが、結論としては acme_challenge gem が便利でした。

Simple rack middeware for responding to ACME challenge like LetsEncrypt uses.
https://github.com/soffes/acme_challenge

上記のREADMEに詳細がありますが、Jekyll + Heroku の場合は config.ru最初で呼び出すだけです (これだけ!)。

# config.ru

require 'acme_challenge'
use AcmeChallenge, ENV['ACME_CHALLENGE'] if ENV['ACME_CHALLENGE']

あとはローカル環境とプロダクション環境の環境変数 (ACME_CHALLENGE) に、Let's Encrypt で取得したキーを入力します。キーの取得方法は総合ポータルの「Let's Encrypt の使い方」を参照してください。

なお、環境変数に代入する値は戻り値の方です。

Make sure your web server displays the following content at
http://railsguides.jp/.well-known/acme-challenge/FOOBAR before continuing:

FOOBAR.HOGEHOGE
※👆ここに表示される値を ACME_CHALLENGE に代入

If you don't have HTTP server configured, you can run the following
command on the target server (as root):

(中略)

Press ENTER to continue

本番環境でのセットアップが終わったら、総合ポータルの手順に従ってSSL証明書を取得しましょう。

2. Enforce SSL by rack-rewrite gem

1.での手続きが無事に終わると、*.pemが入手できるはずです。まずはそのファイルを Heroku にアップロードします。

$ heroku certs:add \
  /etc/letsencrypt/live/railsguides.jp/fullchain.pem \
  /etc/letsencrypt/live/railsguides.jp/privkey.pem

これで http と https の両方にアクセスできるようになりますが、せっかくなので https に統一させたいです。そのための実装がこちら。

Enforce SSL by rack-rewrite gem
https://github.com/yasslab/railsguides.jp/pull/277/commits/0cc483958d33e1781d607f3649ee424058222391

上のコミットでは、rack-rewrite gem を使って config.ru に次のコードを追記しています (細かな記法は省略)。

require 'rack/rewrite'
use Rack::Rewrite do
  if ENV['RACK_ENV'] == 'production'
    r301 %r{.*}, 'https://railsguides.jp$&', :scheme => 'http'
  end
end

これをデプロイすれば、ブックマークなどから http://railsguides.jp/ に来る人も https に切り替わるようになります。ただし、後述の問題がまだ残っているので、この時点ではまだ本番環境にデプロイしない方が良いです (テスト用の環境だけにデプロイする) :warning:

3. Implement custom headers with rack-contrib gem

2. で https でも表示できるようになりましたが、実際に https でアクセスしてみると、Facebook の Like ボタンや Twitter の Tweet ボタンなど、他サイトのドメインから埋め込んだコードに対してエラーまたは警告が表示されてしまいます。

エラー例 (Chromeなら Option + Cmd + i で確認)

ここで表示されるエラーおよび警告は、そのサイトでどんなコードを使っているかによって変わります。したがって解決方法もその内容によるところが大きいですが、1つの汎用的な解決策としては、Content-Security-Policy (CSP) に許容するドメインを適宜追加していく方法があります。

例えばRailsガイドの場合は、はてなブックマークやGoogleアナリティクスなどをサイト内で使っているため、次のようなコードを config.ru に追記しています。

require 'rack/contrib/try_static'
use Rack::TryStatic,
  urls: %w[/],
  root: '_site',
  try: ['.html', 'index.html', '/index.html'],
  header_rules: [
    [:all, {
      'Strict-Transport-Security' => 'max-age=31536000; preload',
      'X-Xss-Protection'          => '1; mode=block',
      'X-Content-Type-Options'    => 'nosniff',
      'X-Frame-Options'           => 'DENY',
      'Content-Security-Policy'   => "default-src 'self' 'unsafe-inline' 'unsafe-eval' *.dropboxusercontent.com *.google-analytics.com *.facebook.net *.facebook.com *.twitter.com ghbtns.com *.hatena.ne.jp *.st-hatena.com *.google.com;"
    }],

# (後略)

コミットの詳細: Implement custom headers with rack-contrib gem
(rack/jekyllrun Rake::Jekyll.new置き換えるようにして追記している点に注意してください :warning: )

CSPをどのように対応するかはサイトごとに異なると思うので、必要に応じて適宜コードを修正してください。目安としては、(Chromeの場合) アイコンが鍵マーク🔒に変わったかどうか、Console上にエラーや警告が出ないかどうかなどがあります。

railsguidesjp_SSL-Check.png

他の目安としては、SSL Server Testなどの外部サービスを使ったチェックもあります。どこまで対応するかはケースバイケースだと思うので、その塩梅については各ケースに応じて判断してもらえればと思います :bow:

railsguides.jpのSSL Reportの結果

まとめ (再掲)

https 対応のご参考になれば幸いです 😆

参考記事

宣伝 :loudspeaker:

Railsガイドのソースコードはオープンソースとして yasslab/railsguides.jp から公開され、YassLab社によって運営されています。

コンテンツ内の誤字・脱字はもとより、コードとして改善できそうなところがあれば、お気軽に Issue または PR を送っていただけると嬉しいです! :smile_cat:

yasslab_logo_copy.png

yasulab
YassLab (株) 代表取締役。(一社) CoderDojo Japan 代表理事。未踏ジュニア PM。RailsチュートリアルやRailsガイド、coderdojo.jp の運営・開発をしています。
https://yasslab.jp/ja
yasslab
RailsチュートリアルとRailsガイドを開発しています。解説動画や電子書籍、法人向け研修・協業プラン、全文検索・バージョン切替機能などを提供しています。
https://yasslab.jp/ja
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away