certbotをnginxを起動したままsystemdのtimerで動かして証明書を自動更新する仕組みが出来た気がします
問題
今日サイトやメールの証明書が突然切れて叩き起こされました.
本来はLet's Encryptには切れそうな証明書をメールで通知する機能があるのですが,昔古い証明書に関する通知を消したら,メールアドレスごと通知が消滅する仕組みだったようで,通知が全く来なくなってしまいました.通知の復活方法が調べても出てこない…
要望
自動更新するようにしたい.
他のシステムも自動更新出来るようにしたいですが,まずは自分の個人サイトで試してうまく行くか試したい.
実装方法
certbotはcertbot renewだけで証明書更新が出来るため,これをsystemdのタイマーで動かせば自動更新が出来るはず.
課題
certbotは認証に80や443ポートを使うため,nginxを起動したままだと更新が出来ません.
nginxを起動したまま更新できるnginxプラグインがあるのですが,これを昔(1年前ぐらい?)試してみたことがあるのですが,うまく動きませんでした.
そしてwebrootは超面倒くさいです.
解決
とりあえずもう一度試してみるかとユーザーガイド - Let's Encrypt 総合ポータルを読んで試してみたのですが普通に使えました.
バグが開発が進んで治った?
なお,ユーザーガイドに書いてあるcertbot --nginxは既にlet's encryptの設定が終わっているなら実行する必要は全くありません.これはnginx.confにlet's encryptの設定を行うものなので,既に設定している人には何のメリットもありません.むしろサブジェクトをずらずら並べた証明書に変更されてしまうので罠です.
certbot --nginx renew --force-renewalで証明書発行し直してみたらシリアル番号が変わっているので再更新と参照の読み替えはちゃんと動いているようですね.なお,--force-renewalオプションはテスト用途以外では使ってはいけません.通常certbot renewは期限切れが1ヶ月以内になっている時だけ更新をするので,サーバの負荷が減ります.
systemdのファイル
systemd/タイマー - ArchWikiによると,systemd-analyze calendar 'Mon *-*-* 13:00:00'のようにすることで次の起動時刻が計算できるらしいですね.知らなかった…
というわけで以下のtimerを書きました.
[Unit]
Description=certbot --nginx renew timer
After=network-online.target
[Timer]
OnCalendar=Mon *-*-* 13:00:00
Persistent=true
[Install]
WantedBy=timers.target
起動が月曜日の13時になっているのは私が月曜日が休みで,13時なら割と起きてるだろうからです.
そしてサービスファイルを書きました.
[Unit]
Description=certbot --nginx renew
After=network-online.target
[Service]
Type=oneshot
Nice=19
ExecStart=/usr/bin/certbot --nginx renew --post-hook "systemctl restart dovecot.service postfix.service && echo 'Subject: complete certbot renew'|sendmail -f root@ncaq.net ncaq@ncaq.net"
nginxは自動で適用されるけれどdovecotとpostfixが自動で更新されるのか分からないので,post-hookに再起動する処理を書いています.
そしてsendmailで更新が完了したことをメール通知します.sendmailに関しては以下を参考にしました.sendmail コマンドによるメール発信 - Postfix Advent Calendar 2014 - ダメ出し Blog
実際動くかどうかはまだわからない
実際に証明書が切れそうになって,更新がかかるのが,証明書が切れるのが9月ぐらいなので8月になります.
それまで本当にこれが動くかは全くわかりません.待つしか無いでしょう.
何にせよnginxプラグインが正常に動くようになったようなのは喜ばしいですね.
これで証明書切れ画面をwebアプリケーションで見せる醜態がなくなれば良いですが.
