HTTPS 証明書の実践 — Let's Encrypt の発行から自動更新まで (certbot・ACME・管理型)
HTTPS 証明書は、かつては毎年お金を払い、手動で発行してサーバーにコピーする面倒な作業でした。今は無料の証明書と自動化ツールが標準になり、一度きちんと設定すれば人が手を出すことはほとんどありません。この記事では、証明書を実際に発行し、サーバーやクラウドに設置し、自動で更新されるようにまとめる流れを、段階を追って扱います。証明書が何を保証するのか、認証局と信頼の連鎖とは何かに馴染みがなければ、証明書とは何で、なぜ必要なのかを先に読むことをおすすめします。
発行の基本の流れ:ACME とドメイン所有の検証 #
自動発行の核心は ACME というプロトコルです。Let’s Encrypt のような認証局が ACME で「本当にこのドメインの持ち主か」を自動で確認し、証明書を出します。確認の方式は二つがよく使われます。
- HTTP-01: 認証局が
http://ドメイン/.well-known/acme-challenge/...のパスに特定の値を要求し、サーバーがその値を応答すれば所有が証明されます。80番ポートが外部から開いている必要があります。 - DNS-01: 認証局が要求した値をドメインの TXT レコード(
_acme-challenge)に置けば所有が証明されます。80番ポートが要らず、ワイルドカード証明書を発行するときは必ずこの方式を使います。
Linux サーバーで Let’s Encrypt を発行する #
もっとも一般的な構成である Linux + Nginx を前提にします。certbot が発行から Nginx 設定の修正まで一度に処理します。
# インストール (例: Ubuntu/Debian)
sudo apt install certbot python3-certbot-nginx
# 発行 + Nginx 設定へ自動反映 (HTTP-01)
sudo certbot --nginx -d schoolofweb.net -d www.schoolofweb.net発行が終わると、証明書ファイルが次の場所にできます。各ファイルの役割を知っておくとエラーを診断しやすくなります。
/etc/letsencrypt/live/schoolofweb.net/
├── privkey.pem # 秘密鍵。絶対に外部へ漏らさない
├── cert.pem # サイト証明書一枚
├── chain.pem # 中間証明書
└── fullchain.pem # cert + chain。Nginx にはふつうこれを指定Nginx で直接指定するなら fullchain.pem と privkey.pem を使います。サイト証明書だけ入れて中間証明書(chain)を抜かすと、一部の環境で信頼の連鎖が切れてエラーになります。だから cert.pem ではなく fullchain.pem を使うのが安全です。
server {
listen 443 ssl;
server_name schoolofweb.net www.schoolofweb.net;
ssl_certificate /etc/letsencrypt/live/schoolofweb.net/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/schoolofweb.net/privkey.pem;
# ...
}自動更新:90日が基本である理由 #
Let’s Encrypt 証明書の有効期限は 90日です。短く見えますが、短いからこそ自動更新を前提に設計されています。certbot をパッケージでインストールすると、たいてい更新タイマーも一緒に登録されます。
# 自動更新タイマーが登録されているか確認
systemctl list-timers | grep certbot
# 実際の更新を真似て問題なく回るか点検 (実際の更新はしない)
sudo certbot renew --dry-runrenew は期限が迫った証明書だけを実際に更新します。更新後に Nginx が新しい証明書を読み直すよう、更新フックに systemctl reload nginx を仕込んでおくところまで確認すれば完成です。自動更新が標準になった今でも、事故の大半は「タイマーが止まっていた」「更新はできたがサーバーが reload しなかった」から生まれます。
ワイルドカード証明書 #
*.schoolofweb.net のようにサブドメイン全体を一枚で覆う証明書をワイルドカード証明書と呼びます。ワイルドカードは HTTP-01 では発行できず、必ず DNS-01 で発行しなければなりません。
sudo certbot certonly --manual --preferred-challenges dns \
-d "schoolofweb.net" -d "*.schoolofweb.net"手動(--manual)で行うと TXT レコードを自分で入れる必要があるので、自動更新と合いません。実務では、使っている DNS サービスのプラグイン(例: certbot-dns-cloudflare、certbot-dns-route53)を使って TXT レコードの登録まで自動化するのが定石です。
クラウド管理型:自分で管理しない選択 #
サーバーに certbot を置かず、プラットフォームに証明書を代わりに管理させることもできます。最近はこの方式のほうが一般的です。
- AWS Certificate Manager(ACM): 証明書を無料で発行・自動更新し、ALB や CloudFront に付けて使います。検証はふつう Route 53 の DNS レコードで自動処理されます。証明書ファイルをサーバーで直接さわることがありません。
- Cloudflare: プロキシ(オレンジの雲)を入れると、Cloudflare が訪問者との区間の証明書を自動で発行・更新します。オリジンサーバー区間のための Origin 証明書も別に提供します。
管理型は鍵ファイルを直接扱わないので楽ですが、証明書が終端される地点(ロードバランサー・CDN)とオリジンサーバーの間の区間をどう守るかは、別に押さえる必要があります。
証明書の種類を手早く整理 #
- DV(ドメイン検証): ドメインの所有だけを確認します。Let’s Encrypt がこれにあたり、ほとんどのサイトに十分です。
- OV/EV(組織・拡張検証): 発行機関が組織の実体まで確認します。発行が遅くコストがかかり、一部の金融・企業環境で求められます。
- SAN(複数ドメイン): 一枚の証明書に複数のドメインを一緒に収めます。
-dオプションを複数回与えた上の例が SAN 証明書です。 - ワイルドカード: サブドメイン全体を一枚で覆います。
よくあるエラーの診断 #
問題が起きたら、ブラウザの警告だけを見ずにツールで連鎖を直接確認します。
# サーバーが返す証明書の連鎖と有効期限を確認
echo | openssl s_client -connect schoolofweb.net:443 -servername schoolofweb.net 2>/dev/null \
| openssl x509 -noout -dates -subject -issuer
# ヘッダーと証明書の状態を一目で
curl -vI https://schoolofweb.netよく出会う原因は次のとおりです。
- 中間証明書の欠落:
cert.pemだけを設置した場合です。fullchain.pemに変えます。ブラウザでは問題ないのに一部のクライアントだけで失敗する形で現れることもあります。 - 名前の不一致: 証明書に入ったドメインと実際に接続するドメインが違う場合です。
wwwを含むか、SAN に抜けたドメインがないかを確認します。 - 期限切れ: 自動更新タイマーが止まったか、更新後に reload が抜けた場合です。
certbot renew --dry-runで点検します。 - HTTP-01 の失敗: 80番ポートが塞がれているか、ファイアウォール・セキュリティグループで認証局のアクセスを遮断している場合です。ポートを開けられない環境なら DNS-01 に変えます。
- 混在コンテンツ(mixed content): ページは HTTPS なのに画像・スクリプトを
http://で読み込んでいる場合です。証明書の問題ではなく、ページ内のリンクをhttps://に直します。
まとめ #
HTTPS 証明書の実践は、結局三つに圧縮されます。ドメインの所有を ACME で検証して発行し、サーバーやプラットフォームに信頼の連鎖が切れないように設置し、期限の前に自動で更新されるようまとめておくことです。自動化が標準になった今は、「一度きちんと設定し、更新が実際に回っているかをときどき確認する」ことが核心です。
証明書が動くには、その前にドメインが正しくつながっている必要があります。ドメインの接続がまだならDNS レコード設定の実践を、暗号化と鍵マークの原理が気になるならアドレスバーの鍵マークは何を守っているのかを合わせてご覧になることをおすすめします。