AlmaLinuxでcertbotを正しくインストールする方法

こんにちは。日々是発見が楽しみな西山です。

HTTP通信は常時SSLがデフォルトの時代、欠かせないのはLet's Encrypt。
気が付けば登場から何年も経ち、より使いやすくする工夫も加えられています。
今回は、AlmaLinuxでcertbotを利用する時に便利な仕組みをご紹介します。

※RedHat系統であれば他のディストリでも同様に使えるとは思います(が、確認はできていません)

自動更新はcronを使わない

Let's Encryptの自動更新のため、定期的に「certbot renew」コマンドを実行する設定。cronでこんな風に書く場合が多いですね。

30 04 * * * /usr/bin/certbot renew 2>&1

実は、AlmaLinuxで「dnf install certbot」と打ってcertbotを導入すると、デフォルトでsystemdのtimerユニットファイルがインストールされます。
ファイルの中身を見てみると、

$ cat /usr/lib/systemd/system/certbot-renew.timer

[Unit]

Description=This is the timer to set the schedule for automated renewals

[Timer]
OnCalendar=*-*-* 00/12:00:00
RandomizedDelaySec=12hours
Persistent=true

[Install]
WantedBy=timers.target

そして、「systemctl enable certbot-renew.timer」と打ってこのタイマーを有効化すると、1日2回「certbot-renew.service」が実行されます。

certbot-renew.service」は

$ cat /usr/lib/systemd/system/certbot-renew.service

[Unit]

Description=This service automatically renews any certbot certificates found

[Service]
EnvironmentFile=/etc/sysconfig/certbot
Type=oneshot
ExecStart=/usr/bin/certbot renew --noninteractive --no-random-sleep-on-renew $PRE_HOOK $POST_HOOK $RENEW_HOOK $DEPLOY_HOOK $CERTBOT_ARGS

certbot-renew.timerでキックされ起動すると『certbot renew』を実行する」という内容です。

なので、certbotを一回手動実行して証明書発行が成功したら、cronを書く代わりに

systemctl  enable certbot-renew.timer

を実行してtimerを有効化するだけ。後はsystemdが1日2回「certbot renew」を実行してくれます。
毎回「cronの書き方どうだったっけ?」と調べ直す必要もなく、お手軽で確実です。

systemdが想定通り動いているかどうかは「journalctl -u certbot-renew.service」で確認できます。

$ journalctl -u certbot-renew.service

Jan 04 01:53:45 localhost systemd[1]: Starting This service automatically renews any certbot certifica>
Jan 04 01:53:46 localhost certbot[1864]: Saving debug log to /var/log/letsencrypt/letsencrypt.log
Jan 04 01:53:46 localhost certbot[1864]: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ->
Jan 04 01:53:46 localhost certbot[1864]: Processing /etc/letsencrypt/renewal/hoge.example.net.co>
Jan 04 01:53:46 localhost certbot[1864]: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ->
Jan 04 01:53:46 localhost certbot[1864]: Certificate not yet due for renewal
Jan 04 01:53:46 localhost certbot[1864]: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ->
Jan 04 01:53:46 localhost certbot[1864]: The following certificates are not due for renewal yet:
Jan 04 01:53:46 localhost certbot[1864]:   /etc/letsencrypt/live/hoge.example.net/fullchain.pem >
Jan 04 01:53:46 localhost certbot[1864]: No renewals were attempted.
Jan 04 01:53:46 localhost certbot[1864]: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ->
Jan 04 01:53:46 localhost systemd[1]: certbot-renew.service: Deactivated successfully.
Jan 04 01:53:46 localhost systemd[1]: Finished This service automatically renews any certbot certifica>

cronにcertbot以外の定時処理も書かれている場合、編集を間違えて他の設定を壊してしまう危険が伴います。うっかりcrontab -rで全消ししてしまうとか。
「certbotのtimerをenable / disableする」だけの手順なら作業ミスも減らせますね。

証明書更新後の処理は /etc/sysconfig/certbot に書こう

certbotで証明書が自動更新された後は、証明書を使用しているデーモン(ApacheやNginxなど)をrestart / reloadさせて反映させる必要があります。
certbotのpost-hookやpost-deployオプションを使うと、証明書更新後に実行させたいコマンドをcertbotが実行してくれます。

dnfでcertbotをインストールすると「/etc/sysconfig/certbot」というファイルがインストールされます。
このファイルに「pre-hook」「post-hook」「post-deploy」のコマンドを書けます。

cat  /etc/sysconfig/certbot

# An example to restart httpd would be:
# POST_HOOK="--post-hook 'systemctl restart httpd'"
POST_HOOK="--post-hook 'systemctl reload httpd'"

# An example to run a script to alert each cert would be:
# DEPLOY_HOOK="--deploy-hook /usr/local/bin/cert-notifier.sh"
DEPLOY_HOOK="--deploy-hook 'systemctl reload nginx'"
※certbotコマンドの変数として渡されるので、先頭に「--post-hook」「--deploy-hook」を書くこと、またコマンドをシングルクォートで囲む必要があります。

certbot本来の設計として、「pre-hook」「post-hook」「post-deploy」は/etc/letsencrypt/renewal-hooks/配下のディレクトリにスクリプト(実行ファイル)を置くと動くのですが、ディレクトリ階層が深く散らばって見づらい面もあります。
/etc/sysconfig/certbotにまとまっていると、ぱっと見で全体の設定内容を把握できるメリットがあるかと思います。

ディストリが便利な構成を作ってパッケージしてくれてるので、それをありがたく利用して楽に環境構築できるといいですね。