heroku にデプロイした環境をLet’s EncryptでSSL化して、自動更新までしたいの
Overview
herokuにデプロイしたサービスをSSL化するのに、Let’s Encryptを使いたいけど
なかなか面倒に感じてしまうところがあると思います。
そこで、herokuにデプロイするアプリにはLet’s Encryptのチャレンジレスポンス用のエンドポイントだけを作り
そのエンドポイントに環境変数でキーを渡すようにすれば、ある程度外部から自動化出来るのではないかと思い試してみました。
環境はRuby on Railsです。
今回使うツール
- certbot
https://certbot.eff.org/ - certbot-heroku
https://github.com/gboudreau/certbot-heroku - heroku_cli
https://devcenter.heroku.com/articles/heroku-cli
今回試してみた事
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買ってしまう方が管理の手間は省けるのかもしれないですが、それでも更新の手間はあったりするので、個人の環境はしばらくはこのやり方で対応しようかと思っています。