heroku にデプロイした環境をLet’s EncryptでSSL化して、自動更新までしたいの

2017年1月29日

Overview

herokuにデプロイしたサービスをSSL化するのに、Let’s Encryptを使いたいけど
なかなか面倒に感じてしまうところがあると思います。
そこで、herokuにデプロイするアプリにはLet’s Encryptのチャレンジレスポンス用のエンドポイントだけを作り
そのエンドポイントに環境変数でキーを渡すようにすれば、ある程度外部から自動化出来るのではないかと思い試してみました。
環境はRuby on Railsです。

今回使うツール

今回試してみた事

RailsのプロジェクトにLet’s Encryptのチャレンジレスポンス用のエンドポイントを作成

routes.rb に以下の行を追加します。
#config/routes.rb
get ".well-known/acme-challenge/:id" => "letsencrypt#index"
controllerを作成します。
#app/controller/letsencrypt_controller.rb
letsencrypt_controller.rb
class LetsencryptController < ApplicationController
  def index
    if ENV["LETS_ENCRYPT_CHALLENGE"]
      render text: ENV["LETS_ENCRYPT_CHALLENGE"], layout: nil
    else
      raise ActionController::RoutingError.new('Not Found')
    end
  end
end
これで、アプリ側の対応は終わりました。
マージしてデプロイしておきます。

certbotのインストール

certbotのインストールをします。
基本的には https://certbot.eff.org/ に従ってインストールすると入ります。

certbot-herokuのインストール

certbot-herokuは、heroku用に作られたcertbotのプラグインになります。
こちらも、基本的には https://github.com/gboudreau/certbot-heroku の内容に従ってインストールします。
インストールが終わったらプラグインが入ったかを確認します。
$> certbot plugins
* certbot-heroku:heroku
Description: Heroku SSL
Interfaces: IAuthenticator, IInstaller, IPlugin
Entry point: heroku = certbot_heroku.configurator:HerokuConfigurator
 
* standalone
Description: Automatically use a temporary webserver
Interfaces: IAuthenticator, IPlugin
Entry point: standalone = certbot.plugins.standalone:Authenticator
 
* webroot
Description: Place files in webroot directory
Interfaces: IAuthenticator, IPlugin
Entry point: webroot = certbot.plugins.webroot:Authenticator

herokuコマンドのインストール

こちらも基本的に https://devcenter.heroku.com/articles/heroku-cli の内容に従ってインストールします。
入ったら、一応herokuコマンドで環境変数が操作出来ることを確認して置きます。
$> heroku config -a sample_app

環境変数の一覧が表示されれば問題ないです。

ログインを催促されたりしたら、herokuのアカウントでログインしておいてください。

certbotコマンド実行

$> certbot install --installer certbot-heroku:heroku -H sample_app -d sample.example.jp.example

このコマンドで実行されること

  • ドメインの認証開始
  • ワンタイムトークン取得
  • herokuの環境変数[LETS_ENCRYPT_CHALLENGE]にワンタイムトークンを設定
  • ワンタイムトークン認証
  • 証明書の発行
  • heroku certsで証明書の設定

heroku上でドメインの設定

herokuのDomain Nameのリストに今回のドメインを追加してします。
$> heroku domains:add sample.example.jp.example

確認

$> heroku domains -a sample_app
Enter your Heroku credentials.
=== sample_app Heroku Domain
sample_app.herokuapp.com
 
===sample.example.jp.example Custom Domains
Domain Name                DNS Target
─────────────────────────  ────────────────────────────────────────
sample.example.jp.example  sample.example.jp.example.herokudns.com

こんな感じに設定されていれば、OKです。

DNS設定

DNSにCNAMEで今回のドメインを設定します。
どのエンドポイントを設定するかというのは
以下のコマンドで確認します。
$> heroku certs -a sample_app
Name         Endpoint                   Common Name(s)             Expires               Trusted  Type
───────────  ─────────────────────────  ─────────────────────────  ────────────────────  ───────  ────────
kyoto-?????  kyoto-?????.herokussl.com  sample.example.jp.example  2017-04-26 06:53 UTC  True     Endpoint

ここの、EndpointというところをDNSに設定します。

ここまで作業したところで、実際にSSL化した状態で参照出来るかを確認します。

SSLの自動更新について

Let’s Encryptは、有効期限が短く、3ヶ月で切れてしまうため、更新作業を自動化しておくことが重要となります。

とはいえ、ここまでの作業を全て自動化する必要はなく、更新だけされれば良いので、certbotをcronなどで叩ける環境が構築出来れば問題ないです。

ということで、cronで実行するコマンドですが

$> certbot run --configurator certbot-heroku:heroku -H sample_app -d sample.example.jp.example

を実行すれば良いです。

自動的にheroku certs:updateをしてくれます。

まとめ

今回はheroku上では完結しないやり方となりましたが

heroku上のアプリのSSLを自動更新させる方法としては

ありなのではないかと思います。

自宅などに、更新用のVMをどこかに立ち上げて、cronを仕込んでおくだけで

あとはheroku上のSSLが更新されるとか

素直に、年間10000円くらいのSSL買ってしまう方が管理の手間は省けるのかもしれないですが、それでも更新の手間はあったりするので、個人の環境はしばらくはこのやり方で対応しようかと思っています。

アンケート