Let's Encryptで無料SSL証明書を取得する

Let's Encryptで無料SSL証明書を取得する覚書です

作成日:2018-10-08

方針

  1. ワイルドカード証明書 (*.cobapen.com)を取得する。
  2. 証明書を取得するクライアントにはcertbotを使う。
  3. certbotはDockerコンテナ内で実行する。

公式ドキュメント

https://certbot.eff.org/docs/index.html

SSL証明書はどこに発行されるのか?

/etc/letsencrypt/live/$domain以下。

/etc/letsencrypt/archive/etc/letsencrypt/keysには過去の鍵と証明書が格納され、/etc/letsencrypt/liveはその中の最新版へのリンクが格納される。

https://certbot.eff.org/docs/using.html#where-certs

certbotの入手

https://hub.docker.com/r/certbot/certbot/

2018-10-08時点の最新版はv0.27.1docker pull certbot/xxxを実行する。

証明書の取得 Part1

DNS-01チャレンジを使ったワイルドカード証明書の取得の基本。

docker run -it --rm --name certbot \
    -v "/etc/letsencrypt:/etc/letsencrypt" \
    -v "/var/lib/letsencrypt:/var/lib/letsencrypt" \
    certbot/certbot certonly --manual \
    -d cobapen.com -d *.cobapen.com \
    -m xxx@outlook.com \
    --server https://acme-v02.api.letsencrypt.org/directory \
    --preferred-challenges dns-01 \
    --agree-tos

ワイルドカード無しのドメインを指定しない場合、サブドメイン無しのURLには使えなかった記憶があるので注意。

--dry-runを指定するとテストができること、デフォルトのrunではなくrenewを指定すると更新できることは覚えておくと良い。

証明書の取得 Part2

DNSレコードの編集を対応したもの。

docker run -it --rm --name certbot \
    -v "/etc/letsencrypt:/etc/letsencrypt" \
    -v "/var/lib/letsencrypt:/var/lib/letsencrypt" \
    -v "/home/xxx/.sec/cloudflare.ini:/etc/cloudflare.ini:ro" \
    certbot/dns-cloudflare certonly \
    -d cobapen.com -d *.cobapen.com \
    -m xxx@outlook.com \
    --server https://acme-v02.api.letsencrypt.org/directory \
    --preferred-challenges dns-01 \
    --agree-tos \
    --dns-cloudflare \
    --dns-cloudflare-credentials /etc/cloudflare.ini \
    --dns-cloudflare-propagation-seconds 30

CertbotのDNSプラグインが対応しているサービスのDNSの設定作業は自動化できる。今回は、Cloudflareを利用する。

https://certbot-dns-cloudflare.readthedocs.io/en/latest/

事前準備として、ドメインが使うネームサーバーをcloudflareに向けておいた。

利用にあたって必要な引数は2つ:

Arg Desc
--dns-cloudflare-credentials API認証キー(.ini)
--dns-cloudflare-propagation-seconds DNS浸透用待ち時間(10s)

ここで、credentialsに指定するiniファイルは次のように記述する。

# Cloudflare API credentials used by Certbot
dns_cloudflare_email = cloudflare@example.com
dns_cloudflare_api_key = 0123456789abcdef0123456789abcdef01234567
このファイルは機密情報を含むため、"chmod 600"しておくこと。

プラグインが導入されたDockerイメージはこちら。

https://hub.docker.com/r/certbot/dns-cloudflare

cloudflareのDNSを利用すると、サーバーへのアクセスがcloudflare網を経由するようになる。これはセキュリティ上有用なのだが、特定のポートしか転送してくれないという弊害もある。例えばSSHのログインができなくなるので注意。

SSL証明書取得後のwebサーバの再起動

certbotには--renew-hookというオプションがあり、更新に成功したときだけ実行するスクリプトを指定することができる。通常はこのオプションでwebサーバを再起動すれば、Webサーバが新しいSSL証明書を読み込んでくれるのだが、Dockerコンテナ内では互いのプロセスが見えないので簡単には実行できない。

様々な方法が考えられるが、一時ファイルを使ってDockerホストに通知する方法が簡単そうだ。

  1. ホストの一時ディレクトリ:/tmp/fooをコンテナの/fooにマウント
  2. コンテナ内でrenewに成功したら、--renew-hook 'touch /foo/renewed'してファイルを生成
  3. コンテナ実行後、/tmp/foo/renewedが存在するかを確認する
  4. 存在する場合、webサーバを再起動する

以上の一連の操作をシェルスクリプトとして保存しておき、cron等で実行する。

https://github.com/certbot/certbot/issues/5333