このページの目次
wildwindstudio.com 証明書の自動更新 + Tencent Cloud CLB 再バインド
ホスト:bj-middleware-1(root、TencentOS、Tencent Cloud 北京)
1. 全体フロー
ログは /var/log/certbot-renewal.log に一元化されます。certbot 自身のデバッグログは /var/log/letsencrypt/ にあります。
重要な設計ポイント
- 証明書ごとの直列実行 + sleep 60:根本的な目的は Tencent Cloud DNS API のレートリミットを回避することです(第4節の根本原因参照)。
certbot renewで一括実行する旧方式に戻さないでください。 - deploy-hook モデル:証明書が「実際に更新された場合のみ」アップロード/再バインドがトリガーされ、同じ証明書の無意味な再アップロードを避けます。これは旧スクリプト(無条件で再送信)よりも正しいアプローチですが、同時に——更新に失敗した場合、CLB は更新されないことを意味するため、更新自体の健全性監視が必要です(第6節参照)。
2. 証明書 ↔ CLB マッピング
リージョンは固定 ap-beijing、現在はすべて単一ドメイン証明書です:
| 証明書(certbot cert-name) | ドメイン | CLB | Listener |
|---|---|---|---|
jsvc.wildwindstudio.com-0001 | jsvc.wildwindstudio.com | lb-fkcz6lot | lbl-ehxkll9d |
passport.wildwindstudio.com | passport.wildwindstudio.com | lb-b6j4kn47 | lbl-0jzb58rx |
cn-reserve-api.wildwindstudio.com | cn-reserve-api.wildwindstudio.com | lb-mm70ra69 | lbl-naeanxnv |
マッピングは
clb-deploy-hook.shのcaseブランチで管理されています。証明書の新規追加/変更時は、こことrenew-and-update-clb.sh上部のCERTS=(...)リストを修正してください。
jsvc証明書の cert-name に-0001サフィックスが付いているのは歴史的経緯です(同名の3ドメイン SAN 系譜がjsvc.wildwindstudio.comという名前を占有していたため)。機能には影響ありません。 resflow.wildwindstudio.com は退役済み(DNS なし、オンラインサービスなし)であり、その旧 CLBlb-mm70ra69は現在 cn-reserve-api で再利用されています。
3. ファイル一覧
| パス | 説明 | 権限 |
|---|---|---|
/etc/crontab | 定期エントリ(平文キーを含まない) | 644 |
/usr/local/bin/renew-and-update-clb.sh | 更新オーケストレーションスクリプト | 755 |
/usr/local/bin/clb-deploy-hook.sh | certbot deploy-hook: アップロード + CLB 再バインド | 755 |
/usr/local/bin/clb-bind-one.sh | 手動単一証明書再バインドツール(緊急用) | 755 |
/etc/letsencrypt/tccli.env | tccli 認証情報(アップロード/再バインド用) | 600 |
/etc/letsencrypt/tencentcloud.ini | certbot DNS プラグイン認証情報(DNS-01 TXT 書き込み用) | 600 |
/var/log/certbot-renewal.log | 更新チェーンログ | - |
注意:DNS プラグインと tccli は異なる2セットの Tencent Cloud API Keyを使用しています。前者は DNSPod 権限のみ必要、後者は SSL + CLB 権限が必要です。
4. トラブルシューティング記録(2026-06-24)
現象
- CLB
lb-fkcz6lot(jsvc.wildwindstudio.com)の証明書が期限切れ、「更新スクリプトが反応せず」、オンラインでは期限切れの証明書が発行されていました。 - 同一バッチの passport、jsvc はすべて 2026-06-24 に期限切れとなりました。
調査手順と発見
- エントリポイントの特定:
/etc/crontabに毎月1日/15日 02:00 にrenew-and-update-clb.shを実行する設定があり、ログは/var/log/certbot-renewal.logに出力されます。 - ログの確認:06-15 の
certbot renewで jsvc/resflow に対して以下が報告されました。
つまり、certbot の更新は常に失敗していました。failed to determine base domain, please report to dev. Tried: ['wildwindstudio.com', 'jsvc.wildwindstudio.com'] - プラグインソースコードの読取
certbot_dns_tencentcloud/certbot_tencentcloud_plugins.pyのdetermine_base_domain():
任意の API 例外(レートリミット / QPS / 一時的エラー)がすべてキャッチされ、最終的にこの誤解を招く "base domain" エラーがスローされます。= # ← 任意の API 例外を「このドメインを所有していない」として扱う continue ... - 対照確認:cn-reserve-api は同じアカウント、同じ
tencentcloud.ini、同じルートドメインですが、06-16 に個別に発行した場合は成功しました。違いは「個別実行 vs 一括連続実行」のみです。 - staging / 本番発行の再現:単一
certbot renew --cert-name jsvc...を実行すると base-domain のステップをスキップして更新に成功 → 一括連続実行がレートリミットをトリガーし、プラグインによって base-domain エラーとして隠蔽されていたことが確定。 - 旧スクリプトが問題を隠蔽:06-16 以前の旧スクリプトロジックは「certbot の成否に関わらず、無条件で既存証明書を再アップロードして CLB に再バインド」でした。そのため、04〜06月は毎回「✓ 再バインド成功」と表示されていましたが、バインドされていたのは03-26に発行され06-24に期限切れとなる古い証明書であり、「更新が正常に動作している」という偽りの状態を演出していました。06-16 に deploy-hook モデルに変更した後、更新失敗時に再バインドが行われなくなったため、問題が表面化しました。
根本原因
予約(cn-reserve)サービスで2つのドメインが新規追加された後、1回の更新バッチで処理するドメイン数が増加し、短時間で Tencent Cloud DNS API への密集呼び出しが発生 → レートリミットをトリガー → certbot DNS 検証で結果が取得できず → 更新失敗 → 証明書が期限切れになっても自動更新されなかった。
5. 今回の対応
緊急更新
- jsvc / passport を個別(直列、隔離)で手動更新し、レートリミットを回避;
clb-bind-one.shを使用して対応する CLB にアップロードおよび再バインド。 - 結果:lb-fkcz6lot、lb-b6j4kn47 のオンライン証明書がすべて更新され、有効期限は 2026-09-22 まで。
根本解決(スクリプト改造、オンライン + 自己テスト EXIT=0)
renew-and-update-clb.shを証明書ごとの直列実行 + 各処理後に sleep 60 +--no-random-sleep-on-renewに変更し、根本からレートリミットを回避。clb-deploy-hook.shで証明書名マッピングを修正し、「実際の更新後のみ再バインド」を維持。
クリーンアップ
- 期限切れで冗長な jsvc 3ドメイン SAN 系譜(退役済み resflow を含む)を削除。
- 平文キーを含む旧
.bakスクリプトを削除。 - 平文 tccli キーを 644 の
/etc/crontabから 600 の/etc/letsencrypt/tccli.envへ移行し、3つのスクリプトが統一してここから読み込むように変更;crontab のバックアップを 600 に権限降格。
6. 運用 Runbook
手動更新 + 単一証明書の再バインド(緊急時)
# 1) 更新(必ず単一、隔離して実行し、一度に複数実行しないこと)
# 2) アップロード + 再バインド(認証情報は /etc/letsencrypt/tccli.env から自動読み込み)
CLB オンライン証明書の検証
| |
証明書一覧 / 期限の確認
ドメイン/証明書の追加
certbot certonly --dns-tencentcloud --dns-tencentcloud-credentials /etc/letsencrypt/tencentcloud.ini -d <ドメイン>clb-deploy-hook.shのcaseにマッピングを追加;renew-and-update-clb.shのCERTS=(...)に cert-name を追加。- 初回のみ手動で
clb-bind-one.shでバインド。
未完了 / 改善項目
-
tccli API Key のローテーション(
AKIDqgLrCLI2...):644 の crontab で平文保存されていた期間が数ヶ月に及び、漏洩として扱う必要があります。 - 証明書の残り日数アラート追加(既存の Prometheus + DingTalk に接続)、残り < 14 日でアラート;「スクリプトがエラーを返さない」ことに依存しないようにする。
-
certbot-dns-tencentcloudプラグインにリトライ/指数バックオフを追加することを検討(注意:site-packages の変更はアップグレードで上書きされる可能性があります;現在はスクリプト層での直列実行 + 負荷分散で十分対応可能)。