certbotの自動更新が動いているかを確かめる:Ubuntu 24.04の既定値

公開日: 2026-10-14 / 運用・復元 #certbot #Let's Encrypt #証明書 #systemd #nginx

Ubuntu 24.04にaptで入れたcertbot(2.9.0)は、certbot.timerが1日2回certbot renewを実行する。このとき更新されるのは、期限まで30日を切った証明書だけだ。90日の証明書なら、取ってから60日ほどは何も起きないのが正常で、ログに更新が無いことは失敗を意味しない。

確かめるのは「タイマーが動いているか」「次に期限を迎える証明書の残り日数」「更新後にWebサーバーが新しい証明書を読み込むか」の3点になる。3つ目はcertbot renew --dry-runでは分からない。

Let’s Encryptは2025年1月に、期限が近いことを知らせるメールの送信を2025年6月4日で終えると発表した。以前はメールが来て気づけた期限切れも、今は自分で見ないと気づけない。2026年10月14日にUbuntu 24.04のコンテナへcertbotを入れ、パッケージに入っている設定ファイルと更新の判定の処理を読んだので、その結果と、VPSで実行する確認の手順をまとめた。

  1. 1日2回、renewを呼ぶcertbot.timer が0時と12時(サーバーの時刻)から最大12時間ずらして certbot renew を実行する
  2. 残り30日を切った証明書だけ更新それ以外の証明書は何もせずに終わる(apt版2.9.0の既定)
  3. 更新後にWebサーバーへ反映--nginx で取った証明書は certbot が nginx を再読み込みする。certonly で取った証明書は deploy フックを自分で置く
Ubuntu 24.04のapt版certbot 2.9.0の自動更新の流れ(2026年10月14日、パッケージの設定ファイルで確認)

確かめた環境と方法

  • コンテナ: Docker Hubのubuntu:24.04(2026年10月14日に取得)。certbot 2.9.0-1、python3-certbot-nginx 2.9.0-1
  • 見たもの: certbot.timerとcertbot.serviceのユニットファイル、/etc/cron.d/certbot、/etc/logrotate.d/certbot、certbotのconstants.py・storage.py(更新の判定)・hooks.py(フックの実行)・renewal.py(結果の表示)、certbot --help renewの出力

ドメインを用意していないので、実際の証明書の取得・更新とOSの再起動は試していない。VPS事業者が配っているOSイメージや、snapで入れたcertbotでは中身が違うことがあるので、自分のVPSでも下の手順でコマンドを実行してほしい。

どの方法で入れたかで、タイマーの名前と更新の基準が違う

入れ方 タイマー 更新する時期 見分け方
apt(Ubuntu 24.04のcertbot 2.9.0) certbot.timer 期限まで30日を切ったとき dpkg -l certbotで版が出る
snap(Certbot公式の手順) snap.certbot.renew.timer Certbot 4.0.0以降は、有効期間の3分の1を切ったとき snap list certbotで版が出る

snap版のcertbotは今回入れていないので、タイマーの名前は自分のVPSのsystemctl list-timersで確かめてほしい。更新する時期の違いは、Certbotのドキュメントに書かれている。4.0.0より前は一律に30日前で、4.0.0から有効期間の3分の1に変わった。今のLet’s Encryptの証明書(90日)ならどちらも残り30日で同じになる。証明書ごとの設定ファイル(/etc/letsencrypt/renewal/<名前>.conf)にrenew_before_expiryを書くと、日数を変えられる(apt版・snap版とも)。

aptとsnapの両方が入っていると、どちらのタイマーも動き、certbotコマンドがどちらを指すかも分かりにくくなる。Certbotの公式サイトのインストール手順は、snapで入れる前にsudo apt-get remove certbotでaptのcertbotを外すよう案内している。

タイマーは1日2回、時刻はずらして動く

apt版のユニットファイルは次のとおりだった。

項目 値 意味
OnCalendar *-*-* 00,12:00:00 サーバーの時刻で0時と12時
RandomizedDelaySec 43200 そこから最大12時間ずらす。実行の時刻は日によって変わる
Persistent true 止まっていた間の実行は、起動した後に行う
実行するコマンド /usr/bin/certbot -q renew --no-random-sleep-on-renew 画面に何も出さずに実行する

/etc/cron.d/certbotにも同じcertbot renewの行がある。ただし/run/systemd/systemがあると何もしない書き方になっていて、systemdで動いているVPSではタイマーの方だけが使われる。同じファイルのコメントにも「Renewal will only occur if expiration is within 30 days.」と書かれていた。

VPSで確かめる手順

確かめること コマンド 見るところ
タイマーが動いているか systemctl list-timers | grep certbot 「LAST」が昨日か今日の日付か(サーバーを動かし続けているのに2日以上前なら、タイマーが止まっている)、「NEXT」に日時があるか。何も出なければタイマーが無い
証明書の残り日数 sudo certbot certificates 「Expiry Date」と「VALID: N days」。30日を切っているのに日付が進んでいなければ更新に失敗している
更新の結果 journalctl -u certbot.service(snap版はjournalctl -u snap.certbot.renew.service) 失敗したときのエラー(-qで動くので、成功したときはほとんど何も出ない)
詳しいログ sudo less /var/log/letsencrypt/letsencrypt.log 毎回の実行の記録。logrotateで週1回まとめ、12週分を残す設定だった
認証が今も通るか sudo certbot renew --dry-run 「Congratulations, all simulated renewals succeeded:」の後に証明書のパスが並ぶか
配信中の証明書の期限 echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null | openssl x509 -noout -enddate certbot certificatesの期限と同じ日付か

--dry-runはLet’s Encryptのステージング環境で試しに証明書を取るだけで、手元の証明書は書き換えない。DNSの向き先を変えた、80番ポートを閉じた、webrootのディレクトリを移した、といった変更の後で、認証が通るかを確かめるのに使う。--pre-hookと--post-hookは--dry-runでも実行されるので、standaloneで取るためにnginxを止めるフックを置いている場合は、試すだけでもnginxが止まる。

更新されても、Webサーバーが古い証明書のままのことがある

certbot certificatesの期限は新しいのに、ブラウザやopensslで見る期限が古いことがある。nginxやApacheは起動したときに読み込んだ証明書を使い続けるので、ファイルが新しくなっても、再読み込みするまで配信される証明書は変わらない。

どう再読み込みされるかは、証明書の取り方で決まる。/etc/letsencrypt/renewal/<名前>.confの[renewalparams]を見ると分かり、certbotが再読み込みするのはinstallerにnginxなどが書かれているときだけだ。

設定ファイルの値 取り方 更新後の再読み込み
installer = nginx(またはapache) certbot --nginxなどで取った certbotが行う
installer = None(または行が無い)。authenticatorはwebroot・standalone・nginxなど certbot certonlyで取った 行われない。フックを自分で置く
renew_hook = ... --deploy-hookを付けて取った 書かれたコマンドが更新のたびに動く

フックは、/etc/letsencrypt/renewal-hooks/deploy/に実行できるファイルを置く方法が分かりやすい。証明書が実際に更新されたときにだけ、名前の順に動く。

#!/bin/sh
# /etc/letsencrypt/renewal-hooks/deploy/reload-nginx(chmod +x を付ける)
systemctl reload nginx

nginxをDockerのコンテナで動かし、ホストの/etc/letsencryptをマウントしている場合は、systemctlの代わりにdocker compose -f /srv/app/compose.yaml exec -T nginx nginx -s reloadのように、コンテナの中のnginxへ再読み込みを送る(パスとサービス名は自分の環境のものにする)。

ここで気をつけたいのが--dry-runの扱いだ。certbot 2.9.0の--help renewには、--dry-runでは「–deploy-hook commands do not run, unless enabled by –run-deploy-hooks」と書かれていた。renewal-hooks/deploy/に置いたファイルも同じ扱いになる。フックが動くかまで試すならsudo certbot renew --dry-run --run-deploy-hooksを使う。このときnginxは実際に再読み込みされる。

Let’s Encryptの証明書は短くなっていく

Let’s Encryptは2025年12月2日に、証明書の有効期間を短くする予定を公表している。

日付(予定) 既定の証明書の有効期間
2026年10月時点 90日
2027年2月10日から 64日
2028年2月16日から 45日

apt版certbot 2.9.0は残り30日で更新するので、64日の証明書なら取ってから34日目ごろ、45日なら15日目ごろに更新が始まる計算になる(45日の証明書では試していない)。更新の回数が増えるぶん、フックが動かない・認証が通らないといった問題に早く当たる。期限通知のメールも無いので、certbot certificatesの残り日数と配信中の証明書の期限を、外から定期的に見る仕組みを作っておく。何を誰に知らせるかは監視と通知の検証に、OSの更新で再起動する時刻の決め方はUbuntuの自動更新と再起動に書いた。

参考資料(確認日: 2026年10月14日)

  1. snap list certbot と dpkg -l certbot で、どちらの方法で入れたかを見る
  2. systemctl list-timers | grep certbot で、タイマーの前回と次回の実行日時を見る
  3. sudo certbot certificates で、各証明書の期限と残り日数を見る
  4. journalctl -u certbot.service と /var/log/letsencrypt/letsencrypt.log で、更新の結果を見る
  5. sudo certbot renew --dry-run で、認証が今も通るかを試す
  6. /etc/letsencrypt/renewal/<名前>.conf の installer と renew_hook を見て、更新後にWebサーバーが再読み込みされるかを確かめる
  7. openssl s_client で、配信中の証明書の期限を見る