はじめに
Certbot を使用して Let's Encrypt で証明書発行を行い、Webサーバーの証明書置き換えを手動で実施した記録です。
- 1枚まとめ図
動画
当記事を元にした動画です。理解の一助にご参照ください。
基礎知識:Certbotと証明書の更新について
Certbot(サートボット)とは?
Certbot は、Let's Encrypt などの無料で利用できる SSL/TLS 証明書を、コマンド操作で簡単に取得・更新・管理するためのオープンソースツールです。通常、証明書の発行手続きには煩雑な作業が伴いますが、Certbot を使うことでその手順を大幅に自動化・簡略化でき、手軽に Web サイトの HTTPS 化(暗号化通信)を実現できます。
証明書の「更新」とは?なぜ必要なのか?
SSL/TLS 証明書には必ず「有効期限」が設定されています。特に Let's Encrypt の証明書は、セキュリティを高く保つ目的で有効期限が 「90日間」 と短く設定されています。
期限が切れる前に新しい証明書を取得し直してサーバーに適用する作業が「更新」です。もし更新を忘れて期限切れになってしまうと、ブラウザでサイトを開いた際に「この接続ではプライバシーが保護されません」といった警告画面が表示され、ユーザーがサイトにアクセスできなくなってしまいます。そのため、計画的な更新(または運用フェーズでの自動化)が不可欠となります。
なぜ証明書発行サーバーを分けたのか?
通常の Certbot 導入では Web サーバー内で直接実行することが多いですが、今回は以下の理由から証明書発行・管理用のサーバーを独立させています。
- Webサーバー(本番環境)に不要なパッケージ(PythonやCertbot関連)をインストールしたくないため。
- 複数台のWebサーバーへ証明書を配布する、中央集権的な証明書管理を見据えているため。
- DNS認証(Route53プラグイン)を利用するため、Webサーバーを外部公開する前の段階から証明書を発行できることを確認するため。
環境
-
AWS Route53 (DNS)
- 前提: ドメインの A レコード設定: 証明書を取得するドメインが、サーバーのグローバル IP アドレスを指している。
-
証明書発行リクエスト・Certbot 導入サーバー (AWS EC2 RHEL10)
-
証明書置き換え Webサーバー (RHEL9 ppc64le)
(補足) AWS Route 53 とは?
AWS Route 53(ルートフィフティスリー) は、Amazon Web Services (AWS) が提供するクラウド型のDNS(ドメインネームシステム)サービスです。
一言でいうと、「インターネット上の高機能な電話帳」 のような役割を果たします。
私たちがWebサイトにアクセスするとき、ブラウザにはtest-cert-web.netのような人間が読める「ドメイン名」を入力しますが、コンピュータ同士は198.51.100.1のような「IPアドレス(数字の羅列)」で通信しています。Route 53は、このドメイン名とIPアドレスを紐づけて、ユーザーを正しいサーバーへと案内(ルーティング)してくれます。
Route 53 の主な3つの機能
- ドメインの取得・管理: 新しいドメインを購入したり、管理したりできます。
- DNSルーティング(名前解決): ドメインへのアクセスを、EC2やS3などの正しいサーバーへ割り振ります。
- ヘルスチェック: サーバーが正常に動いているかを監視し、もし障害が起きていれば、自動的に予備のサーバーへアクセスを切り替える(フェイルオーバー)ことができます。
【補足】なぜ今回の証明書発行で Route 53 が重要だったのか?
Let's Encrypt で
*.test-cert-web.netのようなワイルドカード証明書を発行する場合、「本当にそのドメインの所有者であるか」を証明するために DNS認証(DNS-01チャレンジ) という手順が必須になります。
Route 53 を利用していると、Certbot が AWSのAPI(プログラム間の通信)を通じて、一時的な証明用パスワード(TXTレコード)を自動で Route 53 に書き込み、認証が終わると自動で消去してくれます。この連携が非常にスムーズに行えるため、Certbot と Route 53 はとても相性が良い組み合わせです。
Webサーバーでポート443 のみを使用する設定
Web(Nginx) サーバーをポート443番のみで正常起動するように修正します。
1. 仮の証明書と秘密鍵を作成
空の(自己署名の)証明書を作成します。
### 対象 Web サーバーで実行 ###
# ディレクトリ作成
$ sudo mkdir -p /etc/pki/nginx/private
# 証明書の生成(対話はすべて Enter で飛ばしてOKです)
$ sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout /etc/pki/nginx/private/server.key \
-out /etc/pki/nginx/server.crt
# 権限設定
$ sudo chmod 600 /etc/pki/nginx/private/server.key
2. 設定ファイルの更新
/etc/nginx/conf.d/test-cert-web.net.conf を編集し、listen 443 と証明書パスを追記します。
### 対象 Web サーバーで実行 ###
$ sudo vi /etc/nginx/conf.d/test-cert-web.net.conf
ファイルの内容を以下に差し替え
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name test-cert-web.net www.test-cert-web.net cert-test01.test-cert-web.net;
ssl_certificate "/etc/pki/nginx/server.crt";
ssl_certificate_key "/etc/pki/nginx/private/server.key";
root /var/www/test-cert-web.net/html;
index index.html index.htm;
location / {
try_files $uri $uri/ =404;
}
}
【設定項目の補足解説】
listen 443 ssl http2;
HTTPS通信の標準ポートである443番で待ち受けます。http2を追記することで、通信の並列処理が可能になりWebサイトの表示速度が向上する(HTTP/2)設定を有効にしています。下の行([::]:443)はIPv6環境用の通信設定です。server_name
このサーバーが応答する対象のドメイン名を指定します(サブドメインなどもスペース区切りで複数指定可能)。ssl_certificate/ssl_certificate_key
使用する証明書と秘密鍵のファイルパスです。ここでは「手順1」で作成した 仮の証明書(自己署名証明書) のパスを指定しています。後ほどの「対象Webサーバーへ配置」の手順で、このパスに Let's Encrypt の本物の証明書を上書きします。root/location
rootはWebサイトのファイル(HTMLなど)が置かれている場所(ドキュメントルート)の指定です。location /のブロックでは、アクセスされたURLに対してファイルが存在するか順番に探し(try_files)、見つからなければ404 Not Foundエラーを返すという基本的なルーティングを設定しています。
3. 反映と確認
設定反映のため Nginx を再起動します。
### 対象 Web サーバーで実行 ###
# 設定テスト
$ sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
### 対象 Web サーバーで実行 ###
# 再起動
$ sudo systemctl restart nginx
ポート確認結果
ss コマンドの結果、80番ポートは表示されず、:443 のみが出力しています。
設定が反映され、80番ポートが nginx に使用されていない構成になりました。
### 対象 Web サーバーで実行 ###
$ ss -atn | grep -E ':(80|443)'
LISTEN 0 511 0.0.0.0:443 0.0.0.0:*
LISTEN 0 511 [::]:443 [::]:*
Certbot 導入
ここからは、別の Certbot 導入サーバーでの作業です。
1. 事前準備
- ファイアウォールの開放: HTTP (80) と HTTPS (443) の通信を許可する
### Certbot 導入サーバーで実行 ###
$ sudo firewall-cmd --permanent --add-service=http
success
$ sudo firewall-cmd --permanent --add-service=https
success
$ sudo firewall-cmd --reload
success
$
2. EPEL リポジトリの有効化
- EPEL リポジトリのインストール
EPEL リポジトリとは
「標準のRHEL(Red Hat系OS)には含まれていない、便利で高品質な追加ソフトウェアが詰まった『公式の拡張倉庫』」の役割です。
### Certbot 導入サーバーで実行 ###
$ sudo dnf install https://dl.fedoraproject.org/pub/epel/epel-release-latest-10.noarch.rpm
~ 省略 ~
Many EPEL packages require the CodeReady Builder (CRB) repository.
It is recommended that you run /usr/bin/crb enable to enable the CRB repository.
Installed products updated.
Installed:
epel-release-10-7.el10_1.noarch
Complete!
- CRB (CodeReady Builder) リポジトリの有効化(依存関係で必要な場合があるため)
現在、CRB (CodeReady Builder) リポジトリは disabled 状態です。
### Certbot 導入サーバーで実行 ###
$ dnf repolist all | grep codeready
codeready-builder-for-rhel-10-rhui-debug-rpms Red Hat CodeReady Linux disabled
codeready-builder-for-rhel-10-rhui-rpms Red Hat CodeReady Linux disabled
codeready-builder-for-rhel-10-rhui-source-rpms Red Hat CodeReady Linux disabled
/etc/yum.repos.d/redhat-rhui.repo で対象のリポジトリを enable化
### Certbot 導入サーバーで実行 ###
$ sudo vi /etc/yum.repos.d/redhat-rhui.repo
[rhel-10-extensions-rhui-rpms]
name=Red Hat Enterprise Linux 10 - Extensions from RHUI (RPMs)
mirrorlist=...
enabled=1 <-- ここを 0 から 1 に書き換える
...
リポジトリ確認
### Certbot 導入サーバーで実行 ###
$ sudo dnf repolist
repo id repo name
codeready-builder-for-rhel-10-rhui-rpms Red Hat CodeReady Linux Builder for RHEL 10 x86_64 from RHUI (RPMs)
epel Extra Packages for Enterprise Linux 10 - x86_64
rhel-10-appstream-rhui-rpms Red Hat Enterprise Linux 10 for x86_64 - AppStream from RHUI (RPMs)
rhel-10-baseos-rhui-rpms Red Hat Enterprise Linux 10 for x86_64 - BaseOS from RHUI (RPMs)
rhui-client-config-server-10 Red Hat Enterprise Linux 10 Client Configuration
目的のリポジトリが全て有効化されました。
3. certbot と python3-certbot-dns-route53 の導入
certbot 本体と、route53操作用のプラグイン python3-certbot-dns-route53 を導入します。
### Certbot 導入サーバーで実行 ###
$ sudo dnf install certbot python3-certbot-dns-route53
~ 省略 ~
Installed products updated.
Installed:
certbot-4.2.0-1.el10_1.noarch fontawesome4-fonts-1:4.7.0-23.el10.noarch
python-josepy-doc-2.0.0-2.el10_1.noarch python3-acme-4.2.0-1.el10_1.noarch
python3-boto3-1.35.81-1.el10_0.noarch python3-botocore-1.35.81-1.el10_0.noarch
python3-certbot-4.2.0-1.el10_1.noarch python3-certbot-dns-route53-4.2.0-1.el10_1.noarch
python3-configargparse-1.7.5-1.el10_1.noarch python3-jmespath-1.0.1-8.el10.noarch
python3-josepy-2.0.0-2.el10_1.noarch python3-parsedatetime-2.6-1.el10_0.noarch
python3-pyOpenSSL-25.0.0-1.el10_1.noarch python3-pyrfc3339-1.1-20.el10_0.noarch
python3-pytz-2025.1-1.el10_1.noarch python3-s3transfer-0.10.4-1.el10_0.noarch
python3-typing-extensions-4.9.0-6.el10.noarch
Complete!
$
4. Route53 認証用の IAM 権限設定
AWS Route53 の DNS レコードを操作するため、以下の IAM ポリシーを作成し、Certbot導入サーバーである対象のEC2 にアタッチします。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"route53:ListHostedZones",
"route53:GetChange"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"route53:ChangeResourceRecordSets"
],
"Resource": "arn:aws:route53:::hostedzone/【ホストゾーンIDに置き換える】"
}
]
}
- AWS 環境変数設定(念の為)
### Certbot 導入サーバーで実行 ###
$ export AWS_ACCESS_KEY_ID="AKIA..."
$ export AWS_SECRET_ACCESS_KEY="YOUR_SECRET_KEY"
5. 証明書の初回生成
ワイルドカード指定で生成します。
### Certbot 導入サーバーで実行 ###
$ sudo certbot certonly \
--dns-route53 \
-d "*.test-cert-web.net" \
--register-unsafely-without-email \
--agree-tos \
--non-interactive
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Requesting a certificate for *.test-cert-web.net
Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/test-cert-web.net/fullchain.pem
Key is saved at: /etc/letsencrypt/live/test-cert-web.net/privkey.pem
This certificate expires on 2026-07-17.
These files will be updated when the certificate renews.
Certbot has set up a scheduled task to automatically renew this certificate in the background.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
If you like Certbot, please consider supporting our work by:
* Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate
* Donating to EFF: https://eff.org/donate-le
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- 発行したサーバー上の配置を確認
### Certbot 導入サーバーで実行 ###
$ sudo ls -l /etc/letsencrypt/live/test-cert-web.net/
total 4
-rw-r--r--. 1 root root 692 Apr 18 14:39 README
lrwxrwxrwx. 1 root root 39 Apr 18 14:39 cert.pem -> ../../archive/test-cert-web.net/cert1.pem
lrwxrwxrwx. 1 root root 40 Apr 18 14:39 chain.pem -> ../../archive/test-cert-web.net/chain1.pem
lrwxrwxrwx. 1 root root 44 Apr 18 14:39 fullchain.pem -> ../../archive/test-cert-web.net/fullchain1.pem
lrwxrwxrwx. 1 root root 42 Apr 18 14:39 privkey.pem -> ../../archive/test-cert-web.net/privkey1.pem
- README 確認
### Certbot 導入サーバーで実行 ###
$ sudo cat /etc/letsencrypt/live/test-cert-web.net/README
(内容は省略しますが、要約すると以下の通りです)
privkey.pem: 証明書の秘密鍵です。
fullchain.pem: ほとんどのサーバーソフトウェアで使用される証明書ファイルです。
chain.pem: Nginx 1.3.7 以降などで OCSPスタップリング を使用する場合に利用します。
cert.pem: 多くのサーバー構成でエラーの原因となるため使用しないでください。
警告:これらのファイルを移動したり、名前を変更したりしないでください!
対象Webサーバーへ配置
発行した証明書(実体)を Certbot サーバーから Web サーバーへ転送し、Nginx に適用します。
1. 証明書ファイルの Web サーバーへの転送
Certbot サーバーで発行された証明書を、対象の Web サーバーに安全に転送します。今回は scp コマンドを使用して対象サーバーの作業ディレクトリにコピーしました。
### Certbot導入サーバーから実行 ###
$ sudo scp /etc/letsencrypt/live/test-cert-web.net/fullchain.pem user@<WebサーバーIP>:~/
$ sudo scp /etc/letsencrypt/live/test-cert-web.net/privkey.pem user@<WebサーバーIP>:~/
作業後は一時配置した証明書ファイルを確実に削除することが鍵の流出を防ぎ、安全確保につながります。
2. 証明書の置き換えと適用
現在の証明書のバックアップを取得します。
(※以下の手順はrootユーザーで実行しました)
### 対象 Web サーバーで実行 ###
# cp -p /etc/pki/nginx/server.crt /etc/pki/nginx/server.crt_bk
# cp -p /etc/pki/nginx/private/server.key /etc/pki/nginx/private/server.key_bk
#
安全のため、一度 Nginx を停止して行います。
### 対象 Web サーバーで実行 ###
# systemctl stop nginx
転送してきた新しい証明書を配置します。
### 対象 Web サーバーで実行 ###
# cp -p ./fullchain.pem /etc/pki/nginx/server.crt
cp: overwrite '/etc/pki/nginx/server.crt'? y
# cp -p ./privkey.pem /etc/pki/nginx/private/server.key
cp: overwrite '/etc/pki/nginx/private/server.key'? y
【Tips】秘密鍵のパーミッションについて
秘密鍵(server.key)は非常に機密性の高いファイルです。rootでコピーした後は、他のユーザーから読み取られないように権限が絞られているか(600など)を念のため確認しておくことをおすすめします。
設定ファイルの構文確認を行います。
### 対象 Web サーバーで実行 ###
# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
Nginx を起動し、ステータスを確認します。
### 対象 Web サーバーで実行 ###
# systemctl start nginx
# systemctl status nginx
● nginx.service - The nginx HTTP and reverse proxy server
Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; preset: disabled)
Active: active (running) since Sat 2026-04-18 10:59:18 EDT; 6s ago
Process: 789937 ExecStartPre=/usr/bin/rm -f /run/nginx.pid (code=exited, status=0/SUCCESS)
Process: 789938 ExecStartPre=/usr/sbin/nginx -t (code=exited, status=0/SUCCESS)
Process: 789939 ExecStart=/usr/sbin/nginx (code=exited, status=0/SUCCESS)
Main PID: 789940 (nginx)
Tasks: 9 (limit: 4475)
3. 証明書ファイルの内容・適用確認
配置された証明書の有効期限やドメイン名が意図したものか、ファイル自体を直接確認します。
### 対象 Web サーバーで実行 ###
# openssl x509 -in /etc/pki/nginx/server.crt -text -noout | grep -E "Subject:|Not After"
Not After : Jul 17 13:40:37 2026 GMT
Subject: CN=*.test-cert-web.net
- Subject: ドメイン名が正しい
- Not After: 有効期限が約 90 日後
外部から curl でも確認します。
### 対象 Web サーバーで実行 ###
# curl -vI https://cert-test01.test-cert-web.net 2>&1 | grep -i "server certificate" -A 5
* Server certificate:
* subject: CN=*.test-cert-web.net
* start date: Apr 18 13:40:38 2026 GMT
* expire date: Jul 17 13:40:37 2026 GMT
* subjectAltName: host "cert-test01.test-cert-web.net" matched cert's "*.test-cert-web.net"
* issuer: C=US; O=Let's Encrypt; CN=E8
OpenSSL s_client でも確認します。
### 対象 Web サーバーで実行 ###
# openssl s_client -connect cert-test01.test-cert-web.net:443 -servername cert-test01.test-cert-web.net </dev/null 2>/dev/null | openssl x509 -noout -dates -subject
notBefore=Apr 18 13:40:38 2026 GMT
notAfter=Jul 17 13:40:37 2026 GMT
subject=CN=*.test-cert-web.net
無事に意図した Let's Encrypt の証明書が適用されていることが確認できました。
おわりに / 今後の課題
今回は Certbot サーバーで Route53 を利用した DNS 認証による証明書発行と、Webサーバーへの手動配置・適用までを確認しました。
Let's Encrypt の証明書は有効期限が90日と短く、今後さらに半分程度の期間に短くなることが予定されているため、本番運用においては 「証明書の自動更新発行」 と 「更新された証明書の Web サーバーへの自動配布とNginx再起動」 を仕組み化する必要があります。
また別の機会に自動化の仕組みを検証してみたいと思います。
以上です。
