Nginx SSL/TLS 証明書管理
作成日:
Nginx SSL TLS HTTPS infrastructure Certbot
概要
Nginx で HTTPS を有効にするには、SSL/TLS 証明書の取得と設定が必要。Let’s Encrypt + Certbot を使えば無料で自動化可能。
証明書管理の基本概念
SSL/TLS 証明書とは
- 公開鍵証明書: サーバーの身元を証明し、暗号化通信を実現
- 認証局(CA): 証明書を発行する第三者機関
- Let’s Encrypt: 無料で証明書を発行する認証局
必要なファイル
| ファイル | 説明 |
|---|---|
fullchain.pem | サーバー証明書 + 中間証明書 |
privkey.pem | 秘密鍵(厳重に管理) |
chain.pem | 中間証明書のみ |
cert.pem | サーバー証明書のみ |
Certbot による証明書取得
インストール
# Ubuntu/Debian
sudo apt update
sudo apt install -y certbot python3-certbot-nginx
取得方法の比較
| 方法 | 説明 | 適したケース |
|---|---|---|
| Nginx プラグイン | Nginx 設定を自動更新 | 最も簡単、推奨 |
| Webroot | 既存のドキュメントルートを使用 | Nginx 設定を手動管理したい |
| Standalone | 一時的に :80 を占有 | Nginx 未起動時 |
| DNS-01 | DNS レコードで認証 | ワイルドカード証明書 |
Nginx プラグイン方式(推奨)
# 基本的な取得コマンド
sudo certbot --nginx -d example.com -d www.example.com
# 対話なし(自動化向け)
sudo certbot --nginx -d example.com \
--non-interactive \
--agree-tos \
--email admin@example.com
このコマンドは以下を自動で行う:
- 証明書の取得
- Nginx 設定に SSL 設定を追加
- HTTP → HTTPS のリダイレクト設定
Webroot 方式
# 証明書のみ取得(Nginx 設定は手動)
sudo certbot certonly --webroot \
-w /var/www/html \
-d example.com
Nginx での SSL 設定
基本設定
server {
listen 80;
server_name example.com;
# HTTP → HTTPS リダイレクト
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
server_name example.com;
# 証明書のパス
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
# SSL 設定(推奨)
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers off;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
# HSTS(オプション、慎重に)
# add_header Strict-Transport-Security "max-age=63072000" always;
root /var/www/example.com;
index index.html;
}
複数サイトの証明書管理
# site-a.conf
server {
listen 443 ssl http2;
server_name site-a.example.com;
ssl_certificate /etc/letsencrypt/live/site-a.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/site-a.example.com/privkey.pem;
root /var/www/site-a;
}
# site-b.conf
server {
listen 443 ssl http2;
server_name site-b.example.com;
ssl_certificate /etc/letsencrypt/live/site-b.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/site-b.example.com/privkey.pem;
root /var/www/site-b;
}
ワイルドカード証明書(DNS-01)
# Cloudflare DNS を使用する例
sudo apt install python3-certbot-dns-cloudflare
# API トークンを設定
cat > ~/.secrets/cloudflare.ini << 'EOF'
dns_cloudflare_api_token = YOUR_API_TOKEN
EOF
chmod 600 ~/.secrets/cloudflare.ini
# 証明書取得
sudo certbot certonly \
--dns-cloudflare \
--dns-cloudflare-credentials ~/.secrets/cloudflare.ini \
-d "*.example.com" \
-d example.com
ワイルドカード証明書のメリット:
- 1つの証明書で全サブドメインをカバー
- 新しいサブドメイン追加時に証明書更新不要
自動更新
仕組み
Certbot は systemd タイマーで自動更新を行う(APT 版)。
# タイマーの確認
systemctl status certbot.timer
systemctl list-timers | grep certbot
# 手動テスト(ドライラン)
sudo certbot renew --dry-run
更新後のリロード
Nginx プラグインで取得した場合、更新後に自動でリロードされる。
Webroot 方式の場合は、更新フックを設定:
# /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh
#!/bin/bash
systemctl reload nginx
chmod +x /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh
証明書ファイルの配置場所
なぜ VPS/サーバーに証明書を配置するのか
TLS/SSL 終端の仕組み:
- HTTPS 通信では、クライアント(ブラウザ)とサーバー間で暗号化が行われる
- この暗号化を解除(終端)するのは、秘密鍵を持つサーバー
- 秘密鍵はサーバー上になければ暗号化通信を復号できない
証明書配置が必要な理由:
- 暗号化の復号: 秘密鍵がないと HTTPS リクエストを処理できない
- 身元証明: 証明書でドメイン所有者であることを証明
- リアルタイム参照: TLS ハンドシェイク時に証明書を提示する必要
CDN/クラウドサービス利用時:
- Cloudflare などの CDN を使う場合、CDN がエッジで TLS 終端する
- この場合、CDN 側で証明書を管理し、オリジンサーバーとの間は別の暗号化
- それでもオリジンサーバー側でも証明書を持つのが推奨(エンドツーエンド暗号化)
Let’s Encrypt のファイル構造
/etc/letsencrypt/
├── live/
│ └── example.com/
│ ├── fullchain.pem → ../archive/example.com/fullchain1.pem
│ ├── privkey.pem → ../archive/example.com/privkey1.pem
│ ├── cert.pem → ../archive/example.com/cert1.pem
│ └── chain.pem → ../archive/example.com/chain1.pem
├── archive/
│ └── example.com/
│ ├── fullchain1.pem
│ ├── privkey1.pem
│ ├── cert1.pem
│ └── chain1.pem
└── renewal/
└── example.com.conf
live/はシンボリックリンク → 更新後も同じパスで参照可能archive/に履歴が残るrenewal/に更新設定が保存される
セキュリティのベストプラクティス
秘密鍵の保護
# パーミッション確認
ls -la /etc/letsencrypt/live/example.com/
# 秘密鍵は root のみ読み取り可能にする
sudo chmod 600 /etc/letsencrypt/live/example.com/privkey.pem
SSL 設定の強化
# 推奨設定(Mozilla SSL Configuration Generator 参照)
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers off;
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;
# OCSP Stapling
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
SSL 設定のテスト
# SSL Labs でテスト
# https://www.ssllabs.com/ssltest/
# コマンドラインでテスト
openssl s_client -connect example.com:443 -servername example.com
トラブルシューティング
よくある問題
証明書が見つからない:
# パスを確認
sudo ls -la /etc/letsencrypt/live/
sudo certbot certificates
更新に失敗:
# ログを確認
sudo cat /var/log/letsencrypt/letsencrypt.log
# 手動で更新を試行
sudo certbot renew --force-renewal
Nginx が起動しない:
# 設定をテスト
sudo nginx -t
# よくある原因:証明書パスの間違い、パーミッション
Traefik との比較
| 観点 | Nginx + Certbot | Traefik |
|---|---|---|
| 設定方法 | 手動(設定ファイル) | 自動(Docker ラベル) |
| 証明書取得 | Certbot コマンド | 自動(設定のみ) |
| 更新 | systemd タイマー | 自動(内蔵) |
| 複雑さ | 中程度 | 低い(Docker 環境) |
| 柔軟性 | 高い | Docker 環境に最適化 |
Docker 環境では Traefik の方が簡単だが、非 Docker 環境や細かいチューニングが必要な場合は Nginx + Certbot が適している。
関連トピック
- Certbot - Certbot の詳細
- Nginx - Nginx の基本設定
- マルチサイトホスティング - 複数サイトの運用
- Traefik - Docker 環境での自動証明書管理