Ubuntu 22.04.1 LTS&NginxのロードバランサにLet’s EncryptのSSL証明書を取得し自動更新&同期する方法
ロードバランサ(Nginx)にLet’s EncryptのSSL証明書を取得
今はSSLが必須なので、WEBサーバー構築も難しくなった。
SSLだけで難易度が2倍くらいになっているような…
自分もけっこう困ったのでわかりやすく解説したい。
<環境>
・Ubuntu 22.04.1 LTS
・Nginx 1.27.0
・certbot 1.21.0
・さくらVPS
1、Let’s EncryptでSSL証明書を取得する仕組み
取得は2つの方法があります。
一つ目は、一時的にランダム名のファイルを作ってアクセスできるか確認する方法。
普通にWEBページが表示できる状態であれば取得できる。
「http://doudonn.com/秘密のファイル」にアクセスできればいい。
Nginxで複雑な設定をしていると404エラーになってしまうので、そこだけ注意です。
この方法が基本となります。
ただし、SSLサイトのサーバー移転等では不可能なため、
下記のDNS認証でサーバー移転前に取得します。
DNSのTXTレコードさえ編集できればOK。
この方法だとエックスサーバーで運営しているサイトもSSL証明書を取得できます。
事前に証明書を準備できるので移転時のダウンが無い。
ただし更新時もDNSの認証が必要となってしまうので、
移転後にファイル認証で再度取得する必要があります。
2、ロードバランサでLet’s EncryptのSSL証明書を取得
ロードバランサでSSL処理をするので、ここに証明書を入れる。
ロードバランサはネットにも繋がっているので理想的。
もちろん、WEBサーバーに入れて使っても良いですが、
ここではロードバランサに入れる方法を解説します。
3、ロードバランサに入れるために
取得はDNS認証ができますが、更新時はファイル認証となります(DNSの自動処理は複雑)。
したがって、Let’s Encryptを更新するロードバランサを固定します。
Let’s Encryptが自動で作成した秘密のファイルにアクセスしないといけないので、
更新時はそのファイルがあるサーバーに絶対に繋がないといけない。
Let’s Encryptからのアクセスを転送する必要があります。
4、取得・更新したLet’s EncryptのSSL証明書を同期
そっくりそのまま同期すれば使い回せる。
「rsync」で同期するだけです。
特にサーバー認識・IP認識というのは無い。
SSL証明書ファイルさえあればOKです。
5、Let’s Encryptの取得方法
ファイル認証の場合
「http://取得したいドメイン/.well-known/acme-challenge/xxxxx」に
アクセスされて表示できる状態にしてください。
次のコマンドを実行します。
※ドメイン・メールアドレスは変更ください。
certbot certonly --webroot --agree-tos --dry-run -w /var/www/html -m info@doudonn.com -d doudonn.com
「–dry-run」を付けているのでテスト実行です。
通常は連続失敗で制限にかかるので、必ず–dry-runで試してください。
「Successfully received certificate.」と出たら成功です。
「–dry-run」を外して再度実行します。
certbot certonly --webroot --agree-tos -w /var/www/html -m info@doudonn.com -d doudonn.com
DNS認証の場合
最初にDNSのTXTレコードをすぐ変更できるよう、
ドメイン会社、レンサバ等のDNS設定画面を開いておいてください。
そして、取得するサーバーで、
Let’s Encrypt取得・更新ソフトとなる「certbot」をインストールします。
apt -y install certbot
インストールしたら下記コマンドを実行します。
※ドメインは変更してください。
certbot certonly --manual -d doudonn.com --key-type ecdsa --preferred-challenges dns
するとこんな文章がずらっと出ます。
Saving debug log to /var/log/letsencrypt/letsencrypt.log
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Please deploy a DNS TXT record under the name:
_acme-challenge.doudonn.com.
with the following value:
ge-50PQfSCdCDd1W2AF8R67-7YzI6Jm7u2vm-O7heAo
Before continuing, verify the TXT record has been deployed. Depending on the DNS
provider, this may take some time, from a few seconds to multiple minutes. You can
check if it has finished deploying with aid of online tools, such as the Google
Admin Toolbox: https://toolbox.googleapps.com/apps/dig/#TXT/_acme-challenge.doudonn.com.
Look for one or more bolded line(s) below the line ';ANSWER'. It should show the
value(s) you've just added.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Press Enter to Continue
ここで何も入力せずストップしてください。
この指定の通りTXTレコードを追加します。
サブドメイン:_acme-challenge.doudonn.com TXTレコード内容:ge-50PQfSCdCDd1W2AF8R67-7YzI6Jm7u2vm-O7heAo
追加したら、5分ほど放置してください。
「digコマンド」等で反映しているか確認できますが、あてになりません。
経験上、5分待った方がいいです。
5分後にエンターボタンを押すと、証明書発行完了!です。
「/etc/letsencrypt」というフォルダが作られていることを確認してみてください。
6、Let’s Encryptの証明書の暗号方式をECDSAに指定する
デフォルトだとRSAという方式なので、それを変えます。
公式マニュアルを見たら、
今はデフォルトで「ecdsa」の「secp256r1」になっていましたので、
この設定は特にやらなくても良いです。
一応、高セキュリティ型の「secp384r1」をデフォルトにする方法を記載します。
(処理は若干遅くなる)
<編集ファイル(新規作成)>
/etc/letsencrypt/cli.ini
<下記を記載する>
key-type = ecdsa
elliptic-curve = secp384r1
※個人サイトで高セキュリティ型はやる必要無いと思います
7、ssl_dhparamを作成する
Nginxのssl設定で指定して使うファイルです。
<このディレクトリを作成し、ここに移動>
/etc/nginx/ssl/
<次のコマンドを実行>
openssl dhparam 2048 -out dhparam.pem
ファイル作成に1分くらいかかるので休憩です。
8、Let’s Encrypt更新用のNginxの設定方法
※参考として自分の設定を紹介します。
※暗号関係はこちらのサイトを参考にしました
証明書を取得するサーバー
server {
listen 80;
server_name doudonn.com www.doudonn.com;
location ^~ /.well-known/acme-challenge/ {
root /var/www/html;
}
location / {
return 301 https://$host$request_uri;
}
}
server {
listen 443 ssl;
http2 on;
server_name doudonn.com www.doudonn.com;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 5m;
ssl_prefer_server_ciphers on;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_certificate /etc/letsencrypt/live/doudonn.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/doudonn.com/privkey.pem;
ssl_dhparam /etc/nginx/ssl/dhparam.pem;
ssl_ciphers ECDHE+AESGCM:DHE+aRSA+AESGCM:ECDHE+AESCCM:DHE+aRSA+AESCCM:+AES256:ECDHE+CHACHA20:DHE+aRSA+CHACHA20:+DHE:ECDHE+AES128:ECDHE+CAMELLIA128:ECDHE+AES:ECDHE+CAMELLIA:+ECDHE+SHA:DHE+aRSA+AES128:DHE+aRSA+CAMELLIA128:DHE+aRSA+AES:DHE+aRSA+CAMELLIA:+DHE+aRSA+SHA;
ssl_conf_command Ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_128_CCM_SHA256:TLS_AES_128_CCM_8_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256;
location / {
proxy_pass http://backend;
}
}
更新時もLet’s Encryptはhttp(80番ポート)でアクセスして来ます。
そのため「/.well-known/acme-challenge/」のアクセスだけはバックエンドに流さず、
このサーバーで処理するようにします。
自分の場合は「root /var/www/html;」というルートを指定しています。
転送するサーバー
upstream backend2 {
server 192.168.0.1:80;
}
server {
listen 80;
server_name doudonn.com www.doudonn.com;
location ^~ /.well-known/acme-challenge/ {
proxy_pass http://backend2;
}
location / {
return 301 https://$host$request_uri;
}
}
server {
listen 443 ssl;
http2 on;
server_name doudonn.com www.doudonn.com;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 5m;
ssl_prefer_server_ciphers on;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_certificate /etc/letsencrypt/live/doudonn.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/doudonn.com/privkey.pem;
ssl_dhparam /etc/nginx/ssl/dhparam.pem;
ssl_ciphers ECDHE+AESGCM:DHE+aRSA+AESGCM:ECDHE+AESCCM:DHE+aRSA+AESCCM:+AES256:ECDHE+CHACHA20:DHE+aRSA+CHACHA20:+DHE:ECDHE+AES128:ECDHE+CAMELLIA128:ECDHE+AES:ECDHE+CAMELLIA:+ECDHE+SHA:DHE+aRSA+AES128:DHE+aRSA+CAMELLIA128:DHE+aRSA+AES:DHE+aRSA+CAMELLIA:+DHE+aRSA+SHA;
ssl_conf_command Ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_128_CCM_SHA256:TLS_AES_128_CCM_8_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256;
location / {
proxy_pass http://backend;
}
}
「/.well-known/acme-challenge/」に来たやつを更新用のサーバーへ転送するだけです。
この段階で表示されるかのテストをします。
上記設定の場合、「/var/www/html/.well-known/acme-challenge/test.html」でファイルを作り
「http://doudonn.com/.well-known/acme-challenge/test.html」にアクセスして表示されるか確認してください。
表示できれば大丈夫。
(このテストせず下記のcertbotでのテストをしてもいい)
9、正しく更新できるかどうかテストをする
※DNS認証で取得した場合は、ファイル認証にて再度取得してください。
下記の更新方法はファイル認証の場合です。
テストコマンドは下記
certbot renew --dry-run --cert-name doudonn.com
「--dry-run」を付ければテストができます。
Saving debug log to /var/log/letsencrypt/letsencrypt.log
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Processing /etc/letsencrypt/renewal/doudonn.com.conf
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Simulating renewal of an existing certificate for doudonn.com
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Congratulations, all simulated renewals succeeded:
/etc/letsencrypt/live/doudonn.com/fullchain.pem (success)
「succeeded」と出れば成功です。
10、自動更新用Cronを修正する
certbotでLet's Encryptの発行をすると、
自動的に更新用cronを作成してくれます。
ただ、Nginxのリロードをしないと新しい証明書が反映しないので、そこだけ修正。
<編集ファイル>
/etc/cron.d/certbot
<certbotのcron>
SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
0 */12 * * * root test -x /usr/bin/certbot -a \! -d /run/systemd/system && perl -e 'sleep int(rand(43200))' && certbot -q renew && nginx -s reload
「 && nginx -s reload」を追加してください。
もしくは別にcronを作っても良いです。
11、他サーバーへ同期する
rsyncで「/etc/letsencrypt」を丸ごと同期してください。
<rsyncコマンド参考>
rsync -a -e 'ssh -i /home/doudonn/rsyncuser/id_ed25519 -p 10022' /etc/letsencrypt/ rsyncuser@192.168.0.2:/etc/letsencrypt/
次回からはcronで自動で同期させます。
<cron作成場所>
/etc/cron.d/
この場所に自由な名前でファイルを作ってください。
cronを登録します。
1 */12 * * * root rsync -a -e 'ssh -i /home/doudonn/rsyncuser/id_ed25519 -p 10022' /etc/letsencrypt/ rsyncuser@192.168.0.2:/etc/letsencrypt/
このあたりは自由に作成してください。
当然、同期後にNginxのリロードが必要なので、
同期先でリロードするCronを作ってください。
<cron内容>
3 */12 * * * root nginx -s reload
12、以上です
これでLet's EncryptのSSL証明書自動更新システムができました。
「/etc/letsencrypt/」に全てのドメインのSSL証明書が保存されるので、
ドメインを増やしても同期はこのままで大丈夫です。
一応、初回更新時はちゃんと更新されているか確認しておこう。
補足(エラーについて)
DNS認証で取得したのにファイル認証で更新すると、
更新時に下記のようなエラーが出ます。
Failed to renew certificate doudonn.com with error: The manual plugin is not working; there may be problems with your existing configuration.
The error was: PluginError('An authentication script must be provided with --manual-auth-hook when using the manual plugin non-interactively.')
この場合はファイル認証で再度取得してください。
途中でこんな選択肢を聞いてきます。
1: Keep the existing certificate for now
2: Renew & replace the certificate (may be subject to CA rate limits)
これは「2」を選んでください。