エラーの内容
ブラウザを開くと、ウェブサイトの代わりに以下のエラーが表示されます:
NET::ERR_CERT_DATE_INVALID
The server's security certificate has expired.
Firefoxでは少し異なる表示になります:
SEC_ERROR_EXPIRED_CERTIFICATE
Your connection is not secure.
ほとんどのユーザーは警告画面を無視して進もうとはせず、そのままサイトを離れてしまいます。問題を修正するまで、サイトは事実上ダウンした状態になります。
原因
SSL/TLS証明書にはすべて有効期限があります。Let's Encryptの証明書は90日で失効します。DigiCertやSectigoなど商用認証局の証明書は1〜2年有効です。期限が過ぎると、ブラウザは例外なく、猶予期間もなく接続を拒否します。
なぜ気づかないまま期限が切れてしまうのでしょうか?
- 自動更新のcronジョブがエラーを出さずに失敗していた
- Certbotが証明書を更新したがNginx/Apacheをリロードしなかった — 古い証明書がメモリに残り続けた
- 更新試行時にポート80またはDNSに問題があった
- 証明書を手動でインストールし、更新の自動化を設定していなかった
- 有効期限の警告メールがスパムまたは無効な受信箱に届いていた
簡易診断
何かを触る前に、証明書が単なる設定ミスではなく実際に期限切れであることを確認しましょう。
コマンドラインで有効期限を確認します:
echo | openssl s_client -connect yourdomain.com:443 -servername yourdomain.com 2>/dev/null | openssl x509 -noout -dates
出力例:
notBefore=Jan 1 00:00:00 2024 GMT
notAfter=Apr 1 00:00:00 2024 GMT
notAfterが過去の日付であれば、証明書は期限切れです。次に、サーバーが実際に読み込んでいる証明書ファイルを確認します:
# Nginx
grep -r 'ssl_certificate ' /etc/nginx/
# Apache
grep -r 'SSLCertificateFile' /etc/apache2/
修正方法:Let's Encrypt(Certbot)
Let's Encryptは最も一般的な構成です。まず強制的に更新を実行します:
sudo certbot renew --force-renewal
成功したら、Webサーバーをリロードします:
# Nginx
sudo systemctl reload nginx
# Apache
sudo systemctl reload apache2
更新に失敗した場合は、--dry-runオプションを付けて実行すると、変更を加えずにエラーの内容を確認できます:
sudo certbot renew --force-renewal --dry-run
よくある失敗の原因として以下の3つが挙げられます:
- ポート80がブロックされている:CertbotのHTTP-01チャレンジにはポート80が必要です。開放するには:
sudo ufw allow 80 - DNSがこのサーバーを指していない:ドメインがこのサーバーのIPアドレスに解決される必要があります。
dig yourdomain.comで確認してください - Webサーバーの設定エラー:設定に問題があるとCertbotがチャレンジファイルを配信できません。
sudo nginx -tまたはsudo apachectl configtestでテストしてください
修正方法:商用または手動インストールの証明書
DigiCert、Sectigo、またはその他の認証局から証明書を購入した場合は、ダッシュボードから更新し、新しいファイルを手動でインストールします。
まず、新しいCSRを生成します:
openssl req -new -newkey rsa:2048 -nodes \
-keyout yourdomain.key \
-out yourdomain.csr \
-subj "/C=US/ST=State/L=City/O=YourOrg/CN=yourdomain.com"
CSRを認証局に提出し、新しい証明書バンドルをダウンロードしたら、サーバーの設定を更新します:
# Nginx — パスを更新してください
ssl_certificate /etc/ssl/yourdomain/yourdomain.crt;
ssl_certificate_key /etc/ssl/yourdomain/yourdomain.key;
# Apache — パスを更新してください
SSLCertificateFile /etc/ssl/yourdomain/yourdomain.crt
SSLCertificateKeyFile /etc/ssl/yourdomain/yourdomain.key
SSLCertificateChainFile /etc/ssl/yourdomain/ca-bundle.crt
更新後にWebサーバーをリロードし、新しい有効期限を確認してください。
修正方法:自動更新が機能していなかった場合
ほとんどの場合、これが本当の原因です — 更新ジョブは実行されたが途中で何かが壊れた、あるいは一度も実行されていなかったというケースです。systemdタイマーまたはcronジョブが有効かどうかを確認しましょう:
# systemdタイマーを確認(最新のシステムの場合)
systemctl status certbot.timer
# cronを確認
crontab -l
cat /etc/cron.d/certbot
certbot.timerが無効な場合は有効化します:
sudo systemctl enable certbot.timer
sudo systemctl start certbot.timer
cronエントリがない場合は追加します:
sudo crontab -e
# 以下の行を追加:
0 3 * * * certbot renew --quiet --post-hook "systemctl reload nginx"
--post-hookフラグは非常に重要です。これがないと、Certbotは新しい証明書をディスクに書き込みますが、Nginxはメモリ上の古い証明書を使い続けます。更新が技術的には「成功」していても、サイトは壊れたままになります。
修正の確認
再度、有効期限を確認します:
echo | openssl s_client -connect yourdomain.com:443 -servername yourdomain.com 2>/dev/null | openssl x509 -noout -dates
notAfterが約90日後(Let's Encrypt)または1〜2年後(商用証明書)になっているはずです。
証明書チェーン全体も確認します:
curl -vI https://yourdomain.com 2>&1 | grep -E 'SSL|expire|issuer'
またはhttps://www.ssllabs.com/ssltest/でフルチェーンテストを実行してください — opensslだけでは検出できない中間証明書の問題も発見できます。
ブラウザのキャッシュをクリア(Ctrl+Shift+Delete)してリロードしてください。NET::ERR_CERT_DATE_INVALIDの警告が消えているはずです。
再発防止策
- 証明書の有効期限を監視する:UptimeRobotの無料プランでは、期限の30日前にアラートを送信できます — 設定は約2分で完了します
- 自動更新を毎月テストする:月に一度
sudo certbot renew --dry-runを実行し、更新プロセス全体が正常に機能することを確認します - 必ず--post-hookを含める:更新コマンドは成功時にWebサーバーをリロードする必要があります。そうしないと新しい証明書が有効になりません
- 更新ログを確認する:
cat /var/log/letsencrypt/letsencrypt.log— ファイアウォールのルールやDNS設定が変わる可能性があるOSアップデート後は特に確認してください - Certbotのメールを監視する:Certbotは証明書登録時のメールアドレスに有効期限の警告を送信します。そのメールアドレスが有効で、実際に誰かが確認していることを確かめてください

