SSL 証明書の設定:Let's Encrypt 自動更新とマルチドメイン管理
本番環境で Let’s Encrypt の SSL 証明書 が一度期限切れになり、監視アラートとブラウザの警告が出て、手動で certbot renew して復旧したことがあります。原因は証明書を取得しただけで、systemd timer や Cron による自動更新と Nginx の reload を設定していなかったことです。
Certbot は期限の約30日前から更新を試みます。Deploy Hook を設定しておけば、更新成功時に Web サーバーが自動でリロードされます。本文では単一ドメイン、マルチドメイン SAN、ワイルドカードの DNS-01、複数証明書のグループ戦略まで扱い、HTTPS を長期間手動更新なしで維持する手順をまとめます。
Let’s Encrypt とは?まず仕組みを押さえる
Let’s Encrypt を使っていても、仕組みを理解していないと障害時に切り分けが遅くなります。原理を押さえておくと、設定やトラブルシュートが楽になります。
認証局(CA)の役割
Let’s Encrypt は認証局(CA)です。無料・自動化・オープンという方針が明確で、2016年の開始以降 HTTPS の普及を大きく後押ししました。現在は2億枚以上のアクティブ証明書があり、主要ブラウザでの信頼率は100%です。
従来の CA(DigiCert、GeoTrust など)は高額で手続きも煩雑でした。Let’s Encrypt は申請から検証・発行まで自動化され、証明書の有効期限は90日です。期間は短いですが、自動更新と組み合わせるとローテーションが速く、漏洩時のリスクを抑えやすくなります。
ACME プロトコル:自動化の中心
Let’s Encrypt は ACME(Automated Certificate Management Environment)プロトコル(RFC 8555)を使います。ドメイン所有権の自動検証と証明書発行の手順が定義されています。
検証方式は主に3つ:
- HTTP-01:最も一般的。CA が
/.well-known/acme-challenge/配下にアクセスし、検証トークンを確認します。ドメインを制御していることの証明になります。 - DNS-01:ワイルドカード証明書に必須。DNS の TXT レコードにトークンがあるかを確認します。Web サーバーは不要ですが、DNS API の権限が必要です。
- TLS-ALPN-01:利用は少なく、特殊な構成向けです。
HTTP-01 は80番が外部から到達できることが前提です。DNS-01 は社内向けやワイルドカードに向いています。
Certbot:公式推奨クライアント
Certbot は Let’s Encrypt が推奨するクライアントです。証明書の申請、Web サーバー設定、自動更新のセットアップまでを担います。
Certbot の主な機能:
- 複数の検証方式に対応
- Nginx/Apache プラグインによる設定の自動変更
- systemd timer または cron の自動設定
- 更新のドライラン(dry-run)テスト
このあとの手順で問題が出たとき、どのレイヤーを見るべきか判断しやすくなります。
単一ドメインの SSL 証明書:ゼロから設定
まずは1ドメイン・1サーバーから始めます。基本フローを理解すれば、マルチドメインも同じ考え方で進められます。
Certbot のインストール
OS ごとに手順が異なります。Ubuntu/Debian では Snap がおすすめです(公式も推奨、更新が速い)。
Ubuntu/Debian(Snap):
# Snap のインストール(未導入の場合)
sudo apt update
sudo apt install snapd
# Certbot のインストール
sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/bin/certbot
CentOS/RHEL:
sudo yum install certbot
# または
sudo dnf install certbot
インストール後に確認:
certbot --version
# 例:certbot 2.11.0
証明書の取得:3つの方法
用途に応じて選びます。
方法1:Nginx プラグインで自動設定(初心者向け)
Certbot が Nginx 設定を書き換え、証明書取得・HTTPS 化・HTTP リダイレクトまで一括で行えます。
sudo certbot --nginx -d example.com -d www.example.com
実行中にメールアドレス(緊急通知用)、利用規約への同意、メール共有の可否、HTTP から HTTPS へのリダイレクト(Yes 推奨)などを聞かれます。
完了後、証明書のパスが表示されます。
Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/example.com/fullchain.pem
Key is saved at: /etc/letsencrypt/live/example.com/privkey.pem
方法2:Apache プラグインで自動設定
Nginx と同様で、プラグインだけ Apache 用です。
sudo certbot --apache -d example.com -d www.example.com
方法3:証明書のみ取得(手動設定)
Certbot に設定ファイルを触らせたくない場合、Caddy や Node.js など別の Web サーバーを使う場合は certonly です。
sudo certbot certonly --webroot \
-w /var/www/html \
-d example.com \
-d www.example.com
-w は Web ルートです。検証用ファイルを配置し、取得後は自分で Web サーバーを設定します。
証明書が有効か確認する
証明書ファイルの確認
sudo ls -la /etc/letsencrypt/live/example.com/
次の4ファイルがあります。
cert.pem:サーバー証明書chain.pem:中間証明書fullchain.pem:フルチェーン(Nginx ではこちら)privkey.pem:秘密鍵(Nginx ではこちら)
SSL Labs でテスト
https://www.ssllabs.com/ssltest/ にドメインを入力します。A+ から F までの評価が出ます。目標は少なくとも A です。
よくある結果:
- B や C:TLS バージョンや暗号スイートが弱い(後述の最適化を参照)
- F:チェーン不完全。
cert.pemではなくfullchain.pemを使っているか確認
ブラウザで確認
https://example.com を開き、鍵アイコンから発行者が Let’s Encrypt であることを確認します。
自動更新の設定:期限切れを防ぐ
Let’s Encrypt の証明書は90日です。自動更新と組み合わせれば、短い有効期限はローテーションのメリットになります。
Certbot の自動更新の仕組み
インストール時に、多くの環境では更新の仕組みも入ります。
Systemd Timer(新しい Linux):
certbot.timer と certbot.service が作成されます。Timer が1日2回、期限30日以内の証明書がないか確認し、必要なら Service で更新します。
状態確認:
sudo systemctl list-timers | grep certbot
出力例:
NEXT LEFT LAST PASSED UNIT ACTIVATES
Thu 2026-04-02 12:00:00 UTC 1h left Thu 2026-04-02 00:00:00 UTC 11h ago certbot.timer certbot.service
次回・前回の実行時刻が分かります。
Cron(従来型):
systemd がない環境では cron が使われます。
sudo crontab -l
# または
cat /etc/cron.d/certbot
典型的な設定:
0 0,12 * * * root certbot renew --quiet
0時と12時に更新チェックが走ります。
自動更新が動くか検証する
Timer や Cron が見えただけでは不十分です。実際に更新処理が通るか確認します。
Dry Run テスト
実際には更新せず、シミュレーションだけ行います。
sudo certbot renew --dry-run
出力例:
Processing /etc/letsencrypt/renewal/example.com.conf
Cert not due for renewal, but simulating renewal for dry run
...
The dry run was successful.
successful が出れば設定は問題ありません。
更新設定ファイルの確認
証明書ごとに /etc/letsencrypt/renewal/ 配下に設定があります。
cat /etc/letsencrypt/renewal/example.com.conf
申請時のパラメータや検証方式が記録され、更新時に読み込まれます。
更新後に Web サーバーを自動リロードする
更新しても、プロセスが古い証明書を握ったままのことがあります。リロードが必要です。
Deploy Hook(推奨)
更新が成功したときだけコマンドを実行します。
sudo certbot renew --deploy-hook "systemctl reload nginx"
または renewal 設定の末尾に追加:
# /etc/letsencrypt/renewal/example.com.conf を編集
# 末尾に追加:
deploy_hook = systemctl reload nginx
Post Hook(毎回実行)
成功・失敗にかかわらず毎回実行されます。
sudo certbot renew --post-hook "systemctl reload nginx"
更新成功時だけ Web サーバーを触りたいなら Deploy Hook の方が適切です。
更新に失敗したとき
自動更新でも失敗はあります。よくある原因と対処です。
DNS の問題
DNS を変更した直後、CA がまだ古い IP を見ていることがあります。TTL 分待つか、手動更新を試します。
sudo certbot renew --force-renewal
ファイアウォール・ポート
HTTP-01 は80番が必要です。
sudo ufw status
sudo iptables -L -n
一時的に開放:
sudo ufw allow 80/tcp
権限
sudo ls -la /etc/letsencrypt/live/
sudo ls -la /etc/letsencrypt/archive/
Web サーバーのユーザー(例:www-data)が読めるか確認します。
ログ
sudo tail -f /var/log/letsencrypt/letsencrypt.log
失敗理由が記録されます。メッセージに沿って対処してください。
マルチドメイン SSL の管理:一元化と分離
ドメインが増えると、更新タイミングやファイル配置のばらつきが障害の元になります。方針を決めておくと運用が楽です。
1証明書・複数ドメイン(SAN)
1枚の証明書に複数ドメインを入れる方法が扱いやすいことが多いです。
sudo certbot --nginx \
-d example.com \
-d www.example.com \
-d api.example.com \
-d admin.example.com
メリット:
- 更新が1回で済む
- 証明書ディレクトリが1つ
- Web サーバーの参照パスが単純
SAN(Subject Alternative Names):証明書に列挙された名前だけが有効です。ブラウザはアクセス先が SAN に含まれるかを確認します。
含まれるドメインの確認:
sudo certbot certificates
出力例:
Found the following certs:
Certificate Name: example.com
Domains: example.com www.example.com api.example.com admin.example.com
Expiry Date: 2026-07-01 (VALID: 89 days)
Certificate Path: /etc/letsencrypt/live/example.com/fullchain.pem
ワイルドカード証明書
*.example.com は1階層のサブドメインをまとめてカバーします。
DNS-01 が必須:HTTP-01 ではワイルドカードを発行できません。DNS API で TXT レコードを追加する必要があります。
DNS プラグインの設定
プロバイダごとにプラグインが異なります。Cloudflare の例:
# Cloudflare プラグイン
sudo snap install certbot-dns-cloudflare
# 認証情報ファイル
sudo nano /root/.secrets/certbot/cloudflare.ini
ファイル内容:
dns_cloudflare_api_token = your_cloudflare_api_token
API Token は Cloudflare コンソールで作成し、権限は「DNS:Edit」を選びます。
ワイルドカード証明書の申請
sudo certbot certonly \
--dns-cloudflare \
--dns-cloudflare-credentials /root/.secrets/certbot/cloudflare.ini \
-d "*.example.com" \
-d example.com
*.example.com だけではルートの example.com はカバーされません。両方指定してください。
ワイルドカードの制限
1階層のサブドメインのみ:sub.example.com は OK、sub.sub.example.com は NG です。
2階層が必要なら追加で申請します。
sudo certbot certonly \
--dns-cloudflare \
--dns-cloudflare-credentials /root/.secrets/certbot/cloudflare.ini \
-d "*.example.com" \
-d "*.api.example.com" \
-d example.com
api.example.com と v1.api.example.com の両方をカバーできます。
複数証明書の運用方針
サービス単位で分ける(推奨)
Web グループ:本番・ブログ・ドキュメント
sudo certbot --nginx -d example.com -d www.example.com -d blog.example.com -d docs.example.com
API グループ:API・管理画面
sudo certbot --nginx -d api.example.com -d admin.example.com -d v1.api.example.com
社内グループ:監視・ログ・内部ツール
sudo certbot certonly --dns-cloudflare -d "*.internal.example.com"
メリット:
- 更新の影響範囲を限定できる
- 権限を分離できる
- 1枚の障害が他サービスに波及しにくい
ドメイン階層で組み合わせる
# サブドメイン一式
sudo certbot certonly --dns-cloudflare -d "*.example.com" -d example.com
# 特別な設定が必要なホストだけ別証明書
sudo certbot --nginx -d secure.example.com
証明書ディレクトリの構造
実体の参照先:/etc/letsencrypt/live/[証明書名]/
シンボリックリンクが最新の archive を指します。更新のたびにリンク先が切り替わります。
sudo ls -la /etc/letsencrypt/live/example.com/
lrwxrwxrwx 1 root root 42 Apr 2 12:00 cert.pem -> ../../archive/example.com/cert2.pem
lrwxrwxrwx 1 root root 43 Apr 2 12:00 chain.pem -> ../../archive/example.com/chain2.pem
lrwxrwxrwx 1 root root 44 Apr 2 12:00 fullchain.pem -> ../../archive/example.com/fullchain2.pem
lrwxrwxrwx 1 root root 40 Apr 2 12:00 privkey.pem -> ../../archive/example.com/privkey2.pem
アーカイブ:/etc/letsencrypt/archive/[証明書名]/
過去の世代が cert1.pem、cert2.pem のように残ります。
更新設定:/etc/letsencrypt/renewal/[証明書名].conf
cat /etc/letsencrypt/renewal/example.com.conf
検証方式(webroot、nginx、dns-cloudflare)、ドメイン一覧、Deploy Hook などが含まれます。
高度な設定と最適化:セキュリティと性能
基本ができたら、SSL Labs の評価と体感速度を上げる設定を足します。
HTTP/2 と OCSP Stapling
HTTP/2 で転送効率を上げ、OCSP Stapling で証明書状態確認の遅延を減らします。
Nginx で HTTP/2
server {
listen 443 ssl http2; # http2 を付与
server_name example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
# ... その他の設定
}
設定後:
sudo nginx -t
sudo systemctl reload nginx
OCSP Stapling
OCSP で証明書の失効状態を確認します。Stapling ではサーバーが事前に結果を保持し、クライアントが CA に直接問い合わせる回数を減らせます。
server {
# ... SSL 設定
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
}
SSL Labs で「OCSP Stapling: Yes」と表示されれば有効です。
セキュリティ強化:旧 TLS の無効化
TLS 1.0 と 1.1 は非推奨です。主要ブラウザはすでに対応を終えています。
server {
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
}
このあと SSL Labs で A または A+ を目指せます。
HSTS ヘッダー
HSTS(HTTP Strict Transport Security)は、ブラウザに HTTPS 接続を記憶させます。http:// でアクセスしても HTTPS に寄せられます。
server {
# ... SSL 設定
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
}
パラメータ:
max-age=31536000:1年(秒)includeSubDomains:サブドメインも対象preload:ブラウザのプリロードリスト登録の前提
注意:HSTS を有効にしたあと一時的に HTTP だけ試すと、ブラウザが拒否することがあります。本番適用前に影響範囲を確認してください。
監視とアラート
自動更新だけに頼らず、残り日数を定期的に見ておくと安心です。期限の1週間前に気づければ、手動対応の余裕があります。
シンプルな監視スクリプト
#!/bin/bash
# /usr/local/bin/check-ssl-expiry.sh
DOMAIN="example.com"
EXPIRY_DAYS=$(openssl s_client -connect $DOMAIN:443 -servername $DOMAIN 2>/dev/null | openssl x509 -noout -enddate | cut -d= -f2)
EXPIRY_DATE=$(date -d "$EXPIRY_DAYS" +%s)
CURRENT_DATE=$(date +%s)
DAYS_LEFT=$(( ($EXPIRY_DATE - $CURRENT_DATE) / 86400 ))
if [ $DAYS_LEFT -lt 7 ]; then
echo "WARNING: SSL certificate for $DOMAIN expires in $DAYS_LEFT days"
# メール通知(メール送信の設定が必要)
mail -s "SSL Certificate Expiry Warning" [email protected] <<< "SSL certificate for $DOMAIN expires in $DAYS_LEFT days"
fi
cron で毎日実行:
0 6 * * * /usr/local/bin/check-ssl-expiry.sh
Certbot のメール通知
更新失敗時は申請時に登録したメールに通知されます。アドレスが有効で、迷惑メールに入らないか確認しておいてください。
よくある問題と対処
証明書の申請が失敗する
原因1:DNS がサーバーを向いていない
HTTP-01 では CA がドメインに到達できる必要があります。
dig example.com +short
# または
nslookup example.com
返る IP がサーバーのものか確認し、伝播を待ってから再試行します。
原因2:80番が塞がれている
sudo netstat -tulpn | grep :80
sudo lsof -i :80
Nginx/Apache 以外が占有している場合は停止します。
sudo systemctl stop <service-name>
ファイアウォール:
sudo ufw status
# または
sudo iptables -L -n
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
原因3:webroot の権限
certonly --webroot では .well-known に書き込める必要があります。
ls -la /var/www/html/.well-known/
sudo mkdir -p /var/www/html/.well-known/acme-challenge
sudo chown -R www-data:www-data /var/www/html/.well-known
更新失敗の対処
sudo tail -100 /var/log/letsencrypt/letsencrypt.log
よくあるメッセージ:
Connection refused:ポートDNS problem: NXDOMAIN:DNSRate limit exceeded:申請回数制限
手動で強制更新:
sudo certbot renew --force-renewal
設定ファイルの確認:
cat /etc/letsencrypt/renewal/example.com.conf
破損している場合は削除して再申請:
sudo certbot delete --cert-name example.com
sudo certbot --nginx -d example.com -d www.example.com
複数証明書の取り違え
sudo nginx -T | grep ssl_certificate
server ブロックごとに正しいパスか確認します。
よくあるミス:
fullchain.pemではなくcert.pemを指定- 証明書名とパスが一致していない
Certbot は最初の -d を証明書名にします。
sudo certbot --nginx -d api.example.com -d example.com
この場合、パスは /etc/letsencrypt/live/api.example.com/ です。Nginx で example.com のパスを書くと読み込めません。
sudo certbot certificates
証明書名とパスを一致させてください。
ワイルドカードの制限(再掲)
*.example.com は sub.example.com のみ。sub.sub.example.com には別証明書が必要です。
sudo certbot certonly --dns-cloudflare -d "*.example.com" -d example.com
sudo certbot certonly --dns-cloudflare -d "*.api.example.com"
ルートドメインは -d example.com を忘れずに。
# NG:ルートだけ HTTPS にならない
sudo certbot certonly --dns-cloudflare -d "*.example.com"
# OK
sudo certbot certonly --dns-cloudflare -d "*.example.com" -d example.com
まとめ:手動運用から自動運用へ
SSL 証明書の運用は、従来 CA の手作業から、Let’s Encrypt と Certbot による自動化へ移行する流れです。
要点:
- 仕組み:ACME が検証と発行を定義。HTTP-01 と DNS-01 は用途が異なります。
- 自動更新:Certbot が systemd timer または cron を設定。期限30日前・1日2回のチェックが一般的です。
- マルチドメイン:SAN で一元化、ワイルドカードでサブドメインをまとめ、サービス単位のグループ化が現場では扱いやすいです。
- セキュリティ:HTTP/2、OCSP Stapling、旧 TLS 無効化、HSTS で SSL Labs A+ を目指せます。
- 監視:残り日数のチェックとメール通知で、更新失敗に気づけるようにします。
さらに規模が大きい場合:
- Kubernetes:cert-manager
- リバースプロキシ:Traefik の自動 SSL
- 外部監視:SSL Monitor、Uptime Robot など
- CI/CD:デプロイ時に証明書状態を確認
一度自動化の流れが整えば、証明書期限は日常の心配事から外れます。HTTPS が安定すれば、利用者の信頼と検索エンジン評価の両方に効いてきます。
Let's Encrypt SSL 証明書の自動更新を設定する
Certbot のインストールから自動更新の設定まで、HTTPS が切れないための SSL 証明書設定の全体フロー
⏱️ 目安時間: 30 分
- 1
ステップ1: Certbot をインストール
OS に応じてインストール:
• Ubuntu/Debian(推奨):sudo snap install --classic certbot
• CentOS/RHEL:sudo yum install certbot
• 動作確認:certbot --version - 2
ステップ2: SSL 証明書を申請
用途に合った申請方法を選択:
• Nginx 自動設定:sudo certbot --nginx -d example.com -d www.example.com
• Apache 自動設定:sudo certbot --apache -d example.com -d www.example.com
• 証明書のみ取得:sudo certbot certonly --webroot -w /var/www/html -d example.com - 3
ステップ3: 自動更新を検証
Certbot が自動更新を設定しているか確認:
• Systemd Timer:sudo systemctl list-timers | grep certbot
• Dry Run テスト:sudo certbot renew --dry-run
• 出力に "successful" があること - 4
ステップ4: 更新後の自動リロードを設定
更新設定に Deploy Hook を追加:
• 編集:sudo nano /etc/letsencrypt/renewal/example.com.conf
• 追加:deploy_hook = systemctl reload nginx
• または:sudo certbot renew --deploy-hook "systemctl reload nginx" - 5
ステップ5: セキュリティ強化の設定
Nginx 設定に最適化を追加:
• 旧 TLS 無効:ssl_protocols TLSv1.2 TLSv1.3;
• HTTP/2:listen 443 ssl http2;
• OCSP Stapling:ssl_stapling on;
• HSTS:add_header Strict-Transport-Security "max-age=31536000" always; - 6
ステップ6: 監視・アラートを設定
証明書期限の監視スクリプトを作成:
• 作成:sudo nano /usr/local/bin/check-ssl-expiry.sh
• Cron 追加:0 6 * * * /usr/local/bin/check-ssl-expiry.sh
• Certbot 登録メールの通知が届くことを確認
FAQ
Let's Encrypt 証明書の有効期限はなぜ90日だけなのか?
HTTP-01 と DNS-01 検証の違いは?
DNS-01:CA が DNS の TXT レコードを確認。DNS API の権限が必要です。ワイルドカード証明書はこの方式が必須。社内サービスや多数のサブドメイン向け。
ワイルドカード証明書 *.example.com はどのドメインにマッチする?
マッチしない例:
• 2階層サブドメイン:sub.sub.example.com(*.sub.example.com を別途申請)
• ルートドメイン:example.com(-d example.com を別途追加)
Certbot の自動更新はいつ実行される?
SSL Labs の評価が B や C のときは?
• TLS バージョンが古い:Nginx で ssl_protocols TLSv1.2 TLSv1.3;
• 暗号スイートが弱い:推奨スイートを設定(本文第6節参照)
• 証明書チェーンが不完全:cert.pem ではなく fullchain.pem を使用
• OCSP Stapling 未設定:ssl_stapling on; を追加
設定後に Nginx をリロードし、再テストで A または A+ を目指します。
複数ドメインは1枚の証明書と複数証明書、どちらがよい?
• 1証明書・複数ドメイン(SAN):関連ドメインをまとめ、更新も一元化。例:example.com、www.example.com、blog.example.com
• 複数証明書:サービスごとに分離し、障害影響と権限を分ける。Web、API、社内ツールなど
• ワイルドカード:サブドメインが多い場合に証明書枚数を削減。*.example.com で1階層サブドメインをカバー
証明書の更新に失敗したら?
よくある原因:
• DNS 解決:伝播を待つか、手動で --force-renewal
• ポート占有:80番を確認し、占有プロセスを一時停止
• ファイアウォール:80/443 を開放
• 権限:証明書ファイルのパーミッションを確認
解決後:sudo certbot renew --force-renewal
6 min read · 公開日: 2026年4月2日 · 更新日: 2026年5月19日
関連記事
AIゲーム効果音プロンプト完全ガイド:攻撃・拾得・勝利・失敗の効果音記述術
AIゲーム効果音プロンプト完全ガイド:攻撃・拾得・勝利・失敗の効果音記述術
Cocos ミニゲームのキャラクター移動と攻撃:ノードからアニメーションまでの実装
Cocos ミニゲームのキャラクター移動と攻撃:ノードからアニメーションまでの実装
ゲームの手触りはどこから来るのか:フラッシュ、振動、浮遊文字、音効、粒子フィードバック
コメント
GitHubアカウントでログインしてコメントできます