無料でSSL証明書を発行してもらえるサービスであるLet’s Encryptですが、同時に更新とSSL証明書の設定の自動化を行うCertbotという仕組みを提供しているのも特徴です。
このCertbotですが、いくつかプラグインがあり、ワイルドカード(任意のサブドメインに適用できる)SSL証明書を取得しない場合、メインで使用しているWebサーバー向けのCertbotプラグインを使用すると、自分の方で細工しなくても、Webサーバーを停止することなく自動で取得時の認証や証明書の適用を行ってくれます。
ただ、ワイルドカード証明書の場合はDNS-01という、ドメインを登録しているDNSサーバーを使用した認証方法に限定されてしまうため、上記のようなWebサーバー向けのプラグインを使用することができません。
この場合、ワイルドカード証明書を取得時、もしくは更新時にSSL証明書のインストールや差し替えは行われますが、Webサーバーへの自動適用は行われません。
この状態のままだと、せっかくSSL証明書を自動で更新できても、自動でWebサーバーに読み込まれないため、”いつの間にか期限切れになってた…”なんて状況が発生してしまうことになります。
そこで、僕の場合はSSL更新時に合わせてWebサーバーを自動的に再起動できるように、スクリプトを次のようにしていました。
/usr/bin/certbot renew --force-renew >> /var/log/letsencrypt/ssl-renew.log 2>&1 && service webサーバーのサービス名 restart >> /var/log/letsencrypt/ssl-renew.log 2>&1
ただこの方法では、まれにSSL更新とWebサーバーの再起動のタイミングが悪く、Webサーバーの再起動が失敗してしまうことがありました。
SSL更新からWebサーバー再起動の間で数秒間マージンを置くことで一応はちゃんと動作するようになったのですが、あくまで固定した秒数待つだけで、SSLの更新状態のチェックなどは行っていないため、必ずしも対策できているとはいいがたい状況でした。
さてどうやればうまくできるかなーと考えていたところ、実はCertbot自体に、処理完了後に特定のコマンドを実行させることができる機能があることを知りました。
例えば、証明書取得時のコマンドに
sudo certbot certonly --manual \
-d example.com -d *.example.com -d ... \
-m mail@example.com \
--agree-tos \
--manual-public-ip-logging-ok \
--preferred-challenges dns-01 \
--server https://acme-v02.api.letsencrypt.org/directory
のようにするかと思いますが、このコマンドに
--post-hook="実行したいコマンド"
のようなオプションを付加することで、SSL取得処理終了後に指定したコマンドを実行してくれます。
例えば、証明書取得終了後にnginxを再起動させたい場合は
sudo certbot certonly --manual \
-d example.com -d *.example.com -d ... \
-m mail@example.com \
--agree-tos \
--manual-public-ip-logging-ok \
--preferred-challenges dns-01 \
--server https://acme-v02.api.letsencrypt.org/directory
--post-hook="service nginx restart"
のようにすると、SSL取得処理が終了した時点でnginxを再起動させることができます。
取得時に指定したオプションはcertbotの設定ファイルに記録されるため、2回目以降の更新時では
sudo certbot renew
とするだけでpost-hookも含めて処理してくれるようになります。
なお、このpost-hookはssl証明書の処理が完了したら、失敗・成功にかかわらず実行する、という指定になってますが、処理前に実行させたり、証明書更新が行われた後のみ実行、といった指定も可能となっているようです。
Let’s EncryptのSSL証明書更新時にサービスを再起動する – Qiita
このあたりの設定をうまく使えば、運用がより楽になりそうですね。