2026年9月4日
2026年9月4日
WordPressサイトのSSL証明書の有効期限を自動監視してアラートを出す方法
SSL証明書の期限切れは、自動更新を設定していても、更新の失敗やDNS・サーバー設定の変更をきっかけに起こります。対策は「更新の仕組み」とは別に「期限を外から確認して、残りが少なくなったら知らせる仕組み」を用意することです。この記事では、opensslコマンドで期限を確かめる方法、cronで定期確認して通知するスクリプト、外部の監視サービスの使い方、Certbotの更新が動いているかの確認方法を順に説明します。
なぜ自動更新だけでは足りないのか
Let's Encryptなどの証明書は有効期間が短く、Certbotなどのツールで自動更新する運用が一般的です。それでも期限切れが起きるのは、主に次のような理由です。
- 更新処理は動いたが、認証(HTTP-01やDNS-01)に失敗していた。DNSの移転、CDNの導入、
.well-knownへのリダイレクト設定の変更などが原因になりやすい - 証明書ファイルは更新されたが、Webサーバーが再読み込みされず古い証明書を出し続けていた
- サーバー移転の後、旧サーバーでだけ更新処理が動いていた
wwwありとなしなど、一部のホスト名だけが証明書から漏れていた
また、Let's Encryptは有効期限が近づいたときに送っていた通知メールを2025年に終了しました。これまでそのメールを頼りにしていた場合は、自分で監視を用意する必要があります。証明書の最大有効期間は今後さらに短くなる方向で業界のルールが決まっており、更新の回数が増えるほど、失敗に気づく仕組みの重要性は高まります(2026年10月現在)。具体的な日程は各認証局の発表を確認してください。
opensslで期限を確認する
まずは手元やサーバーから、公開されている証明書の期限を直接確認する方法です。
echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null \
| openssl x509 -noout -subject -issuer -enddate
-servername はSNI(1つのIPアドレスで複数のドメインの証明書を出し分ける仕組み)のための指定で、省略すると別のドメインの証明書が返ってくることがあります。notAfter= の後に表示される日時が有効期限です。表示はUTCなので、日本時間では9時間進めて読みます。
「残り何日以内か」を判定するには -checkend(秒数)を使います。期限まで指定秒数以上あれば終了コード0、なければ1を返すため、スクリプトで扱いやすくなります。
echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null \
| openssl x509 -noout -checkend $((14*24*60*60)) && echo "14日以上あります" || echo "14日以内に期限切れです"
CDNを使っている場合、この方法で見えるのはCDNが出している証明書です。オリジンサーバー側の証明書も確認したいときは、-connect にオリジンのIPアドレスを指定し、-servername にはドメイン名を指定します。
cronで定期確認して通知するスクリプト
監視したいホスト名をまとめて確認し、期限が近いものや取得できなかったものがあれば通知するスクリプトの例です。通知先はチャットツールのWebhookを想定しています。URLはダミーなので、利用するサービスで発行したものに置き換えてください。
#!/usr/bin/env bash
# /usr/local/bin/check-cert-expiry.sh
set -u
DOMAINS="example.com www.example.com"
DAYS=14
WEBHOOK_URL="https://hooks.example.com/your-webhook-path"
notify() {
local msg="$1"
if ! curl -fsS -m 15 -X POST -H 'Content-Type: application/json' \
-d "{\"text\":\"${msg}\"}" "$WEBHOOK_URL" >/dev/null; then
# 通知に失敗したときは標準エラーに出す(cronのメールやログで拾う)
echo "$msg" >&2
fi
}
for d in $DOMAINS; do
cert=$(echo | timeout 20 openssl s_client -connect "${d}:443" -servername "$d" 2>/dev/null | openssl x509 2>/dev/null)
if [ -z "$cert" ]; then
notify "[SSL監視] ${d}: 証明書を取得できませんでした"
continue
fi
if ! echo "$cert" | openssl x509 -noout -checkend $((DAYS*24*60*60)) >/dev/null; then
end=$(echo "$cert" | openssl x509 -noout -enddate | cut -d= -f2)
notify "[SSL監視] ${d}: 有効期限まで${DAYS}日未満です(期限: ${end})"
fi
done
実行権限を付けて手動で一度動かし、DAYS を大きな値(たとえば 400)にして通知が届くかを確かめてから、元の値に戻します。動作を確認できたら、cronに登録します。
# crontab -e で追記(毎日9時に実行)
0 9 * * * /usr/local/bin/check-cert-expiry.sh
このスクリプトのポイントは次のとおりです。
- 証明書を取得できなかった場合も通知します。証明書の期限より先に、ポート443が閉じている、名前解決ができないといった問題に気づけます。
timeoutで接続待ちの時間に上限を設けています。応答しないホストがあっても、スクリプト全体が止まりません。- 監視は、証明書を更新するサーバーとは別の場所から実行するのが理想です。同じサーバーで動かすと、そのサーバーが止まったときに監視も止まります。
WordPressの中(WP-Cronやプラグイン)で期限を確認する方法もありますが、WP-Cronはサイトへのアクセスをきっかけに動く仕組みのため、サイトが表示できない状態では動きません。証明書の監視は、サイトの外から行うほうが目的に合っています。
外部の監視サービスを使う
自分でスクリプトを管理したくない場合は、外部の監視サービスを使う方法があります。
- Uptime Kuma:自分で設置するオープンソースの監視ツールです。HTTPの監視項目で証明書の期限切れ通知を有効にでき、メールやチャットツールなど多くの通知先に対応しています。監視対象とは別のサーバーに設置します。
- UptimeRobot、Better Stack などのSaaS:サイトの死活監視とあわせて、証明書の期限を通知する機能を提供しているサービスがあります。無料の範囲で使える機能や監視間隔はプランによって異なり、変更されることもあるため、各サービスの最新の案内を確認してください。
どのサービスでも、通知の受け手が1人だけだと、その人が不在のときに対応が遅れます。複数人に届く通知先(チームのチャンネルなど)を設定しておくと安心です。
Certbotの自動更新が動いているかを確認する
監視で「期限が近い」と通知されたら、更新の仕組みのほうを確認します。Certbotを使っている場合の主な確認方法です。
# 管理している証明書と有効期限の一覧
sudo certbot certificates
# 実際には更新せずに、更新処理が通るかを試す
sudo certbot renew --dry-run
# systemdのタイマーで更新している場合、次回の実行予定を確認
systemctl list-timers | grep -i certbot
--dry-run が失敗する場合は、表示されるエラーから原因を探します。HTTP-01の認証では、http://ドメイン/.well-known/acme-challenge/ へのアクセスが外部から届くかが重要です。HTTPSへの強制リダイレクトやBasic認証、CDNやWAFの設定が認証を妨げていないかを確認してください。Certbotのインストール方法(OSのパッケージかsnapか)によって、タイマーの名前や設定ファイルの場所が異なります。
更新に成功しても、Webサーバーが新しい証明書を読み込まなければ意味がありません。更新後にnginxやApacheを再読み込みするフック(--deploy-hook など)が設定されているかも確認します。共用サーバーやマネージドなWordPressホスティングで証明書が自動で発行されている場合は、更新の仕組みはサーバー会社の管理です。期限の監視だけを自分で行い、問題があればサーバー会社のサポートに問い合わせます。
通知が来たときの対応手順
- opensslでいま公開されている証明書の期限と発行者を確認し、通知が正しいかを確かめる
- サーバー上の証明書ファイル(
certbot certificatesの表示)の期限と比べる。ファイルが新しいのに公開されている証明書が古いなら、Webサーバーの再読み込みが漏れている - ファイルも古いなら
certbot renew --dry-runで更新処理のエラーを確認し、原因を直してから更新する - 更新後にもう一度opensslで確認し、すべてのホスト名で新しい期限になっていることを確かめる
設定を変更する前には、Webサーバーの設定ファイルと証明書のディレクトリをバックアップしておきます。
まとめ
- 証明書の自動更新とは別に、公開されている証明書の期限を外から定期確認する仕組みを用意します。
openssl s_clientとopenssl x509 -checkendで、期限までの残りを判定できます。CDNを使っている場合はオリジン側も確認します。- cronのスクリプトでは、期限が近い場合に加えて、証明書を取得できなかった場合も通知します。監視は更新するサーバーとは別の場所から行うのが理想です。
- Let's Encryptの期限通知メールは2025年に終了したため、メールに頼らない監視に切り替えます。
- 通知が来たら、公開中の証明書とサーバー上のファイルの期限を比べ、再読み込み漏れか更新失敗かを切り分けます。