前回のfail2ban + ufw設定で基本的なセキュリティ対策は完璧になりましたが、今度は「SSL証明書の管理が面倒」という声をよく聞きます。
実際、私も最初はSSL証明書の期限切れでサイトがエラーになったり、更新し忘れて夜中に慌てて対応したりという経験があります。Lovate開発中も、複数のサブドメインでSSL証明書を管理するのが本当に大変でした。
でも、Let’s Encryptとcertbotを使えば、SSL証明書の取得から更新まで、すべて自動化できるんです。一度設定すれば、もう証明書の心配をする必要はありません。

Let’s Encryptが革命的な理由
従来のSSL証明書は年間数千円〜数万円かかり、手動での更新作業も必要でした。しかしLet’s Encryptは:
- 完全無料:個人サイトでも商用サイトでも無料
- 自動更新:certbotで90日ごとに自動更新
- 簡単設定:数コマンドで証明書取得&Nginx設定
- ワイルドカード対応:*.example.comの形式で複数サブドメインをカバー
ACME(Automatic Certificate Management Environment)プロトコルを使用し、ドメイン所有権を自動検証。証明書の発行から更新まで、すべてプログラムで自動化できる設計になっています。
実際の設定手順:失敗しないSSL証明書導入
ステップ1:certbotインストールと初期設定
1-1. snapパッケージでcertbotインストール(推奨)
# Ubuntu 18.04以降の場合(snapを使用)
sudo apt update
sudo apt install snapd
sudo snap install core; sudo snap refresh core
sudo snap install --classic certbot
# コマンドリンクの作成
sudo ln -s /snap/bin/certbot /usr/bin/certbot
1-2. 従来のAPTパッケージでインストール(代替手段)
# Ubuntu/Debian
sudo apt install certbot python3-certbot-nginx
# CentOS/AlmaLinux
sudo dnf install epel-release
sudo dnf install certbot python3-certbot-nginx
- ドメインのDNS設定が正しくサーバーIPを指している
- ファイアウォールでHTTP(80)とHTTPS(443)ポートが開放済み
- Nginxが正常に動作している
ステップ2:SSL証明書の取得と自動設定
2-1. 単一ドメインの証明書取得
# 基本的なSSL証明書取得(Nginx自動設定込み)
sudo certbot --nginx -d example.com
#複数ドメイン対応
sudo certbot --nginx -d example.com -d www.example.com
2-2. 実際の私のサーバー設定例
私のjunchi8.comでの実際の設定コマンド:
# メインドメインとサブドメインを一括取得
sudo certbot --nginx -d blog.junchi8.com -d api.junchi8.com -d cloud.junchi8.com
# 取得中の対話形式の質問
# Email address (used for urgent renewal and security notices): your-email@example.com
# (A)gree/(C)ancel: A
# (Y)es/(N)o: N (メール通知不要の場合)
成功すると、以下のような表示が出ます:
Congratulations! You have successfully enabled HTTPS on https://blog.junchi8.com
You should test your configuration at:
![]()
SSL Server Test: blog.junchi8.com (Powered by Qualys SSL Labs)
ステップ3:ワイルドカード証明書(上級者向け)
複数のサブドメインがある場合、ワイルドカード証明書が便利です:
# DNS認証が必要(Cloudflare使用例)
sudo certbot certonly \
--dns-cloudflare \
--dns-cloudflare-credentials ~/.secrets/certbot/cloudflare.ini \
-d '*.junchi8.com' \
-d junchi8.com
Cloudflare認証ファイル(`~/.secrets/certbot/cloudflare.ini`):
# Cloudflare API credentials
dns_cloudflare_api_token = YOUR_CLOUDFLARE_API_TOKEN
自動更新の設定と確認
3-1. 自動更新の動作確認
# 更新のテスト実行(実際には更新しない)
sudo certbot renew --dry-run
# 証明書の状況確認
sudo certbot certificates
正常に設定されていれば、以下のような表示になります:
Certificate Name: blog.junchi8.com
Serial Number: 4a7b8c9d1e2f3a4b5c6d7e8f9a0b1c2d
Key Type: RSA
Domains: blog.junchi8.com api.junchi8.com cloud.junchi8.com
Expiry Date: 2025-12-15 12:34:56+00:00 (VALID: 89 days)
Certificate Path: /etc/letsencrypt/live/blog.junchi8.com/fullchain.pem
Private Key Path: /etc/letsencrypt/live/blog.junchi8.com/privkey.pem
3-2. Cronジョブでの自動更新設定
# crontabの編集
sudo crontab -e
# 以下の行を追加(毎日午前3時に更新チェック)
0 3 * * * /usr/bin/certbot renew --quiet --post-hook "systemctl reload nginx"
トラブルシューティング:よくある問題と解決法
問題1:「Challenge failed」エラー
症状:証明書取得時に以下のようなエラーが出る
Challenge failed for domain example.com
http-01 challenge for example.com
原因と解決法:
# ファイアウォールの確認
sudo ufw status
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
# Nginxの設定確認
sudo nginx -t
sudo systemctl status nginx
# DNS設定の確認
nslookup example.com
問題2:「Rate limit exceeded」エラー
原因:Let’s Encryptには同一ドメインでの取得制限があります
– 1週間に50回までの証明書発行制限
– 1時間に5回までの失敗試行制限
対策:
# テスト時は必ず --dry-run を使用
sudo certbot --nginx --dry-run -d example.com
# 成功確認後に本番実行
sudo certbot --nginx -d example.com
問題3:「Certificate verification failed」
よくある原因:
# 混在コンテンツの確認
curl -I https://example.com
# リダイレクトループの確認
curl -L https://example.com
# SSL設定の詳細確認
openssl s_client -connect example.com:443 -servername example.com
セキュリティ強化:SSL設定の最適化
証明書取得後、さらにセキュリティを強化できます:
4-1. SSL/TLS設定の最適化
Nginx設定ファイル(`/etc/nginx/sites-available/your-site`)に追加:
server {
listen 443 ssl http2;
server_name example.com;
# Let's Encryptで自動生成される証明書パス
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
# セキュリティ強化設定
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;
# HSTS(HTTP Strict Transport Security)
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
# その他のセキュリティヘッダー
add_header X-Frame-Options DENY always;
add_header X-Content-Type-Options nosniff always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
}
4-2. 設定テストと適用
# Nginx設定の文法確認
sudo nginx -t
# 設定の適用
sudo systemctl reload nginx
# SSL品質の確認(外部サービス)
# https://www.ssllabs.com/ssltest/ でテスト
運用時の監視とメンテナンス
5-1. 証明書状況の定期確認
# 証明書の有効期限確認
sudo certbot certificates | grep -E "(Certificate Name|Expiry Date)"
# ログの確認
sudo tail -f /var/log/letsencrypt/letsencrypt.log
# 更新履歴の確認
sudo grep "Successfully renewed" /var/log/letsencrypt/letsencrypt.log
5-2. 監視スクリプト(オプション)
証明書の期限切れを事前に通知するスクリプト:
#!/bin/bash
# ssl-check.sh
DOMAIN="example.com"
THRESHOLD=30 # 30日前に警告
EXPIRY=$(openssl x509 -enddate -noout -in /etc/letsencrypt/live/$DOMAIN/cert.pem | cut -d= -f2)
EXPIRY_EPOCH=$(date -d "$EXPIRY" +%s)
NOW_EPOCH=$(date +%s)
DAYS_LEFT=$(( ($EXPIRY_EPOCH - $NOW_EPOCH) / 86400 ))
if [ $DAYS_LEFT -le $THRESHOLD ]; then
echo "警告: SSL証明書が ${DAYS_LEFT} 日で期限切れです"
# メール通知やSlack通知をここに追加
fi
💡 Pro Tips
- 複数サーバー管理:Ansible等でcertbot設定を自動化
- CDN利用時:CloudflareやCloudFrontでも証明書管理は重要
- 開発環境:mkcertで自己署名証明書を使用して開発効率化
まとめ:安全で信頼性の高いHTTPS環境の実現
Let’s Encrypt + certbotの組み合わせで、もうSSL証明書の管理で悩むことはありません。
今回設定した内容の復習:
- ✅ certbotインストールと基本設定
- ✅ SSL証明書の自動取得とNginx設定
- ✅ 自動更新システムの構築
- ✅ セキュリティ設定の最適化
- ✅ トラブルシューティング手法
前回のfail2ban + ufwと組み合わせれば、セキュリティ面では企業レベルの対策が完成します。次回は「Nginxパフォーマンス最適化とキャッシュ戦略」について詳しく解説します。
