SSL/TLS証明書とは
SSL/TLS証明書は、Webサイトとユーザーのブラウザ間の通信を暗号化するために使われます。
HTTPSのメリット
- 🔒 通信の暗号化: データの盗聴を防ぐ
- ✅ 信頼性の証明: サイトの正当性を保証
- 🚀 SEOの向上: Googleが推奨(ランキング要因)
- 📱 PWA対応: Service Workerに必須
- 🌐 HTTP/2利用: 高速な通信プロトコル
従来のSSL証明書の問題
- 💰
年間数千円~数万円のコスト - 📝
複雑な申請手続き - ⏰
手動での更新作業
Let's Encryptはこれらの問題をすべて解決します!
Let's Encryptとは
Let's Encryptは、無料で自動化されたSSL証明書を提供する認証局(CA)です。
特徴
- ✅ 完全無料
- ✅ 自動更新可能
- ✅ 主要ブラウザで信頼されている
- ✅ APIで自動化できる
- ⚠️ 有効期限は90日(自動更新で解決)
certbotツール
certbotは、Let's Encrypt証明書の取得・更新を自動化するツールです。
前提条件の確認
必要なもの
- ✅ 独自ドメイン(example.comなど)
- ✅ ドメインがサーバーのIPに紐付いている(Aレコード設定済み)
- ✅ ポート80と443が開いている
- ✅ Nginxがインストール済み
DNS設定の確認
# ドメインの名前解決ができるか確認
dig +short example.com
# → 123.45.67.89(サーバーのIP)が返ればOK
# または
nslookup example.comNginxのインストールと設定
Nginxのインストール
# Ubuntuの場合
sudo apt update
sudo apt install -y nginx
# 起動と自動起動設定
sudo systemctl start nginx
sudo systemctl enable nginx
# 確認
sudo systemctl status nginx初期設定ファイルの作成
まずHTTPで動作させる設定を作成します:
# /etc/nginx/sites-available/myapp の作成
sudo nano /etc/nginx/sites-available/myapp以下の内容を記述:
server {
listen 80;
server_name example.com www.example.com;
location / {
proxy_pass http://localhost:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}設定の有効化
# シンボリックリンクの作成
sudo ln -s /etc/nginx/sites-available/myapp \
/etc/nginx/sites-enabled/
# デフォルト設定の削除
sudo rm /etc/nginx/sites-enabled/default
# 設定の検証
sudo nginx -t
# Nginxの再起動
sudo systemctl reload nginxcertbotのインストール
Ubuntu/Debianの場合
# Snapでインストール(推奨)
sudo snap install --classic certbot
# シンボリックリンクの作成
sudo ln -s /snap/bin/certbot /usr/bin/certbot
# 確認
certbot --versionapt経由でのインストール(代替方法)
sudo apt update
sudo apt install -y certbot python3-certbot-nginxSSL証明書の取得
自動設定モード(推奨)
Nginxの設定を自動で書き換えてくれます:
sudo certbot --nginx -d example.com -d www.example.comインタラクティブな質問に回答
# メールアドレスの入力
Enter email address: your_email@example.com
# 利用規約への同意
(A)gree/(C)ancel: A
# メール配信の設定
(Y)es/(N)o: N # 任意
# HTTPSリダイレクトの設定
1: No redirect
2: Redirect - Make all requests redirect to secure HTTPS
Select: 2 # 推奨: すべてHTTPSにリダイレクト手動設定モード
証明書のみ取得し、Nginx設定は手動で行う場合:
sudo certbot certonly --nginx -d example.com -d www.example.com証明書ファイルの場所
/etc/letsencrypt/live/example.com/
├── fullchain.pem # 証明書チェーン(Nginxで使用)
├── privkey.pem # 秘密鍵(Nginxで使用)
├── cert.pem # サーバー証明書
└── chain.pem # 中間証明書Nginx設定の手動カスタマイズ
自動設定でうまくいかない場合や、細かくカスタマイズしたい場合:
server {
listen 80;
server_name example.com www.example.com;
# HTTPからHTTPSへリダイレクト
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name example.com www.example.com;
# SSL証明書の設定
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_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256';
ssl_prefer_server_ciphers off;
# HSTSの有効化(推奨)
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
# その他のセキュリティヘッダー
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
location / {
proxy_pass http://localhost:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}設定後:
sudo nginx -t
sudo systemctl reload nginxDocker Composeとの統合
docker-compose.ymlの例
version: '3.8'
services:
web:
build: .
container_name: flask_app
restart: always
expose:
- "8000"
volumes:
- ./:/app
command: gunicorn -w 4 -b 0.0.0.0:8000 app:app
nginx:
image: nginx:alpine
container_name: nginx_proxy
restart: always
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx/nginx.conf:/etc/nginx/conf.d/default.conf
- /etc/letsencrypt:/etc/letsencrypt:ro
- /var/lib/letsencrypt:/var/lib/letsencrypt:ro
depends_on:
- webNginxコンテナ用の設定ファイル
nginx/nginx.conf:
upstream flask_app {
server web:8000;
}
server {
listen 80;
server_name example.com www.example.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name example.com www.example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
location / {
proxy_pass http://flask_app;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}自動更新の設定
更新テストの実行
# Dry-run(実際には更新しない)
sudo certbot renew --dry-runcronでの自動更新
certbotはsystemdタイマーで自動的に更新を試行します:
# タイマーの確認
sudo systemctl list-timers | grep certbot
# 手動でタイマーを有効化(通常は不要)
sudo systemctl enable certbot.timer
sudo systemctl start certbot.timer更新後のNginxリロード
更新時に自動でNginxをリロードする設定:
# /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh を作成
sudo nano /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh内容:
#!/bin/bash
sudo systemctl reload nginx実行権限を付与:
sudo chmod +x /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.shHTTPSの確認
ブラウザでの確認
- 🔒 鍵マークが表示される
- 証明書情報でLet's Encryptが発行者と確認できる
- 有効期限を確認(90日以内)
SSL Labsでのテスト
SSL/TLSの設定品質をチェックできます:
https://www.ssllabs.com/ssltest/analyze.html?d=example.com目標: A+評価
コマンドラインでの確認
# 証明書の詳細表示
openssl s_client -connect example.com:443 -servername example.com
# 有効期限の確認
echo | openssl s_client -connect example.com:443 2>/dev/null | \
openssl x509 -noout -datesトラブルシューティング
証明書取得エラー: "DNS問題"
- ドメインのDNS設定を確認
- DNSの反映を待つ(最大48時間)
- ファイアウォールでポート80/443が開いているか確認
sudo ufw status
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp証明書取得エラー: "Rate limit"
Let's Encryptにはレート制限があります:
- 同一ドメイン: 週50回まで
- 失敗試行: 時間あたり5回まで
解決策:
- テスト時は
--dry-runや--stagingオプションを使う - 時間をおいて再試行
"Permission denied" エラー
# certbot実行時はsudoを使う
sudo certbot ...
# 証明書ファイルの権限確認
sudo ls -la /etc/letsencrypt/live/example.com/Nginxが証明書を読み込めない
# Nginxの設定テスト
sudo nginx -t
# エラーログの確認
sudo tail -f /var/log/nginx/error.log
# 証明書パスの確認
sudo ls -l /etc/letsencrypt/live/example.com/fullchain.pem更新が自動実行されない
# タイマーの状態確認
sudo systemctl status certbot.timer
# ログの確認
sudo journalctl -u certbot.timer
# 手動での更新テスト
sudo certbot renew --dry-runセキュリティのベストプラクティス
1. 強力なSSL設定
- TLS 1.2以上のみを許可
- 弱い暗号スイートを無効化
- HSTS(HTTP Strict Transport Security)の有効化
2. セキュリティヘッダーの追加
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "no-referrer-when-downgrade" always;
add_header Content-Security-Policy "default-src 'self' http: https: data: blob: 'unsafe-inline'" always;3. 定期的な監視
- 証明書の有効期限を監視
- 自動更新のログを定期確認
- SSL Labsで定期的にテスト
料金とコスト
- ✅ Let's Encrypt: 完全無料
- ✅ 更新: 無料(自動)
- ✅ ワイルドカード証明書: 無料(DNS-01チャレンジが必要)
年間の追加コストはゼロです!
高度な設定
ワイルドカード証明書の取得
*.example.comのような証明書:
sudo certbot certonly --manual \
--preferred-challenges=dns \
-d example.com -d '*.example.com'DNS TXTレコードの追加が必要になります。
複数ドメインの証明書
sudo certbot --nginx \
-d example.com \
-d www.example.com \
-d api.example.com \
-d blog.example.comまとめ
この記事では、Let's Encryptで無料HTTPS化する方法を解説しました。
学んだこと
- Let's Encryptの仕組みと利点
- certbotでのSSL証明書取得
- NginxでのHTTPS設定
- 自動更新の仕組み
- Docker環境での統合
- セキュリティのベストプラクティス
これでWebサービスが完成!
Flask + Gunicorn + Docker + Nginx + HTTPSの構成で、本番環境レベルのWebサービスが構築できました。
次のステップ
- CDN(CloudflareなどでのDDoS対策
- モニタリング(Prometheus, Grafana)
- バックアップの自動化
- CI/CDパイプラインの構築