Let's Encryptで取得した証明書をHerokuに反映させてみた
Let's Encryptで取得したSSL証明書を、Herokuで公開しているアプリケーションに反映させた話です。
Let's Encryptで取得した証明書は90日後までには更新しないといけないようなので、次回更新時に手順がわからず途方に暮れないように、作業手順を記事にしてみます。
SSL証明書などの知識に乏しいため、説明が不十分な点などあるかと思いますが、ご了承ください。
なお、作業環境は基本的にMacのターミナルです。
今回対象としたのは、既にHerokuで公開されているアプリケーションです。個人のドメインが設定されており、my_app.herokuapp.comだけでなく、my_domainにアクセスすることでも、アプリケーションを利用できます。
ちなみにそのアプリケーションはSinatraを利用しています。関連情報を検索するとRuby on Railsがよくヒットしますが、やることはそこまで大きく変わらないと思うので、気にせず進めていきましょう。
今回の記事の大まかな流れを示します。
1. Let's Encryptのクライアントソフトウェア、Certbotを導入する
2. Let's EncryptでSSL証明書を取得する
3. 取得したSSL証明書を個人のドメインに反映させる
こんな感じです。それではさっそく1番から進めます。
まずは1番、Let's Encryptのクライアントソフトウェア、Certbotを導入する方法を説明します。
参考:Let's Encrypt 総合ポータル Let's Encrypt の使い方
僕はこちらを参考に進めました。
初めに、gitのインストールが必要になりますが、僕は既にインストールされていたため、それは飛ばします。
次に、git cloneしてCertbotクライアントをダウンロードします。gitを使ったことのある方にはおなじみですね。
ダウンロードしたら、cloneしたディレクトリに移動して、Certbotを実行できる環境が整っているかテストします。基本的には書いてある通りに進めればいいのですが、僕はこんな警告が出ました。
$ cd certbot/ $ ./certbot-auto WARNING: Mac OS X support is very experimental at present... if you would like to work on improving it, please ensure you have backups and then run this script again with the --debug flag!
どうやらMac OS Xのサポートはとても実験的(?)なようです。それでも動作させたいなら、バックアップを確認して、--debugフラグをつけて再びこのスクリプトを実行するように言われています。
もちろん--debugをつけて再度実行します。
$ ./certbot-auto --debug
実行すると、Homebrewで自動的にいくつかのパッケージがインストールされていきます。途中、root権限が要求されるので、パスワードを入力してあげましょう。
パッケージのインストールが終わると、Certbotクライアントが起動して、TUIが表示されます。ここでは一旦NOを選択して、クライアントを終了します。
これでLet's Encryptのクライアントソフトウェア、Certbotの導入は完了です。
次に2番、Let's EncryptでSSL証明書を取得する方法を説明します。
参考:Let's encryptをHerokuにあるRailsアプリに適用する
僕はこちらを参考に進めました。
Let's Encryptでは、特定のURLへのアクセスに対して特定の値を返すことで認証を行い、証明書を発行してもらう仕組みのようです。
具体的には、
my_domain/.well-known/acme-challenge/REQUEST_KEY
というURLにアクセスしたら、
RESPONSE_KEY
という値を返せばいいということです。もちろん、REQUEST_KEYとRESPONSE_KEYは、Let's Encryptのコマンドを実行したときに取得できる値です。
さっそくやってみます。
まず、今回の対象はSinatraを利用しているアプリケーションなので、main.rbに以下のような記述を追加してあげます。
get "/.well-known/acme-challenge/:id" do ENV["LETSENCRYPT_RESPONSE"] if params[:id] == ENV["LETSENCRYPT_REQUEST"] end
LETSENCRYPT_REQUESTとLETSENCRYPT_RESPONSEはHerokuの環境変数です。
記述を追加したら、デプロイを忘れないようにしましょう。
次に、Herokuの環境変数を設定するのですが、その前にHeroku Toolbeltという、Heroku用のコマンドラインツールなどを含んだアプリケーションをインストールする必要があります。
次のステップでも必要になるので、インストールしておきましょう。
無事インストールが完了したら、環境変数をセットします。セットの前にHerokuにログインしておきます。メールアドレスとパスワードを入力するだけです。
$ heroku login Enter your Heroku credentials. Email: my_email Password (typing will be hidden): Logged in as my_email $ heroku config:set LETSENCRYPT_REQUEST=aaa -a my_app $ heroku config:set LETSENCRYPT_RESPONSE=bbb -a my_app
環境変数をセットしたら、ちゃんと期待通りの動作をするか、確認しておきましょう。
今回の例だと、
my_domain/.well-known/acme-challenge/aaa
にアクセスして、
bbb
という値が返ってくれば、期待通りの動作をしていることになります。
さて、いよいよSSL証明書を取得します。Certbotのディレクトリに移動して、以下のコマンドを実行します。
$ cd certbot/ $ ./certbot-auto certonly --manual -d my_domain Requesting root privileges to run certbot... /Users/USERNAME/.local/share/letsencrypt/bin/letsencrypt certonly --manual -d my_domain Password:
root権限のパスワードを入力して表示された画面でYESを選択すると、以下のような指示が表示されます。
Make sure your web server displays the following content at http://my_domain/.well-known/acme-challenge/REQUESTREQUESTREQUESTREQUESTREQUESTREQUESTR before continuing: RESPONSERESPONSERESPONSERESPONSERESPONSERESPONSERESPONSERESPONSERESPONSERESPONSERESPONS If you don't have HTTP server configured, you can run the following command on the target server (as root): mkdir -p /tmp/certbot/public_html/.well-known/acme-challenge cd /tmp/certbot/public_html printf "%s" RESPONSERESPONSERESPONSERESPONSERESPONSERESPONSERESPONSERESPONSERESPONSERESPONSERESPONS > .well-known/acme-challenge/REQUESTREQUESTREQUESTREQUESTREQUESTREQUESTR # run only once per server: $(command -v python2 || command -v python2.7 || command -v python2.6) -c \ "import BaseHTTPServer, SimpleHTTPServer; \ s = BaseHTTPServer.HTTPServer(('', 80), SimpleHTTPServer.SimpleHTTPRequestHandler); \ s.serve_forever()" Press ENTER to continue
ここで、新しいターミナルのウィンドウを開いて、そちらでHerokuの環境変数を設定し直します。
$ heroku config:set LETSENCRYPT_REQUEST=REQUESTREQUESTREQUESTREQUESTREQUESTREQUESTR -a my_app $ heroku config:set LETSENCRYPT_RESPONSE=RESPONSERESPONSERESPONSERESPONSERESPONSERESPONSERESPONSERESPONSERESPONSERESPONSERESPONS -a my_app
環境変数の設定が完了したら、元のターミナルのウィンドウに戻って、Enterキーを押します。
認証が成功すると、こんな感じの情報が表示されます。
IMPORTANT NOTES: - Congratulations! Your certificate and chain have been saved at /etc/letsencrypt/live/my_domain/fullchain.pem. Your cert will expire on 2016-11-01. To obtain a new or tweaked version of this certificate in the future, simply run certbot-auto again. To non-interactively renew *all* of your certificates, run "certbot-auto renew" - If you like Certbot, please consider supporting our work by: Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate Donating to EFF: https://eff.org/donate-le
この先必要になるのは、
- crtファイル:/etc/letsencrypt/live/my_domain/fullchain.pem
- keyファイル:/etc/letsencrypt/live/my_domain/privkey.pem
です。
確認してみましょう。
$ sudo ls /etc/letsencrypt/live/my_domain/ cert.pem chain.pem fullchain.pem privkey.pem
これでSSL証明書の取得は完了です。
最後に3番、取得したSSL証明書を個人のドメインに反映させる方法を説明します。
参考:Heroku SSL (Beta) | Heroku Dev Center
基本的にはこちらの解説にしたがって進めていきます。
日本語の情報を調べてみると、月額20ドルかかるとかなんとか出てきたりしますが、Beta版のHeroku SSLを使うことで無料で(クレジットカードの登録などをすることなく)反映できました。
SSLを使用するには、フラグを有効にしてCLIプラグインをインストールする必要があるようなので、ますはそちらを行います。
$ heroku labs:enable http-sni -a my_app Enabling http-sni for my_app... done $ heroku plugins:install heroku-certs Installing plugin heroku-certs... done
もしかしたら何かメッセージが出てくるかもしれません。
次に、いよいよ証明書を反映させます。
$ sudo heroku _certs:add /etc/letsencrypt/live/my_domain/fullchain.pem /etc/letsencrypt/live/my_domain/privkey.pem -a my_app
ここでもし、
Only one SNI endpoint is allowed per app (try sni:update instead)
や、
Must pass either --type with either 'endpoint' or 'sni'
というメッセージが出て失敗する場合は、先ほどのコマンドの代わりに、
$ sudo heroku _certs:update /etc/letsencrypt/live/my_domain/fullchain.pem /etc/letsencrypt/live/my_domain/privkey.pem -a my_app
を実行してみてください。
確認のため、my_appの入力が求められますので、入力します。
無事反映されたら、以下のコマンドで証明書の詳細を確認できます。
$ heroku _certs:info -a my_app
また、SSLのセットアップが正しく行われているかの確認は以下のコマンドです。
$ curl -vI https://my_domain
最後に、DNSが正しく設定されているかの確認です。
$ heroku domains -a my_app === my_app Heroku Domain my_app.herokuapp.com === my_app Custom Domains Domain Name DNS Target ────── ──────────── my_domain dns_target.com $ dig my_domain cname +short dns_target.com.
このようなレスポンスがあれば正しく設定されていますが、グローバルに反映されるにはタイムラグがあるようなのでそこには注意しましょう。
これで証明書の反映は完了です。
以上、少し長くなってしまいましたが、Let's Encryptで取得したSSL証明書を、Herokuで公開しているアプリケーションに反映させた話でした。
少々ややこしいですが、これで個人のドメインにも証明書を反映させることができます。更新時の自分の役に立てばいいのですが。