🦁

Let's Encryptの無料SSL証明書を自動更新しつつNginxで運用する

2024/06/23に公開

自分の備忘も兼ねて、Let's EncryptのSSL証明書の導入をまとめておきます。

今回やること

  • Let's Encryptで無料のSSL証明書を発行する
  • 発行した証明書をNginxで利用する
  • 証明書は自動で更新する
    Let's Encryptで発行した証明書の有効期限は3カ月なので
  • 自動更新した証明書をNginxにも自動適用する
  • 証明書の発行にはcertbotを利用する
    ただし、Nginxの設定の書き換えはcertbotからは行わない

記事の前提

本記事は下記前提で記載しています。

  • 運用するドメインはssl.test.devとする

certbot のインストール

まずはcertbotをインストールします。

sudo apt install certbot

Nginxで対象ドメインの/.well-known/acme-challengeのパスにHTTPでアクセス可能にする

Let's Encryptで対象ドメインの所有権を確認する為、/.well-known/acme-challengeのパスで指定されたファイルを公開する必要があります。
その為、HTTP(ポート80)でアクセスできるようにしておきます。
ファイルの作成(認証が終われば削除)はcertbotが自動で行ってくれます。

/etc/nginx/conf.d/ssl.test.dev.conf
server {
  listen 80;
  server_name  ssl.test.dev;

  location /.well-known/acme-challenge {
    root   /usr/share/nginx/html;
    index  index.html index.htm;
  }
}

設定したらチェックしてリロード。

sudo nginx -t
sudo systemctl reload nginx

※1 証明書の更新の際にも利用するので、この設定は消さないでください。
※2 DNSやポート開放など、必要に応じて行ってください。

certbotを利用してLet's EncryptのSSL証明書を発行する

下記コマンドで証明書を発行します。
下記コマンドは証明書の発行のみを行うコマンドになっているので、Nginxへの設定は後から手動で行います。
(自動でNginxの設定を書き換えるのは嫌だったので、この手法にしています。

sudo certbot certonly --webroot -w /usr/share/nginx/html -d ssl.test.dev

初めて利用する場合は下記のようにメールアドレスの入力と、規約の同意が求められます。

Saving debug log to /var/log/letsencrypt/letsencrypt.log
Enter email address (used for urgent renewal and security notices)
 (Enter 'c' to cancel):

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Please read the Terms of Service at
https://letsencrypt.org/documents/LE-SA-v1.3-September-21-2022.pdf. You must
agree in order to register with the ACME server. Do you agree?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o: Y

証明書の期限が迫った場合の通知などが届きますので、管理者のメールアドレスを登録し、規約に同意します。

Would you be willing, once your first certificate is successfully issued, to
share your email address with the Electronic Frontier Foundation, a founding
partner of the Let's Encrypt project and the non-profit organization that
develops Certbot? We'd like to send you email about our work encrypting the web,
EFF news, campaigns, and ways to support digital freedom.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o:

次にニュースなどのメールを受け取るか聞かれるので、これはお好みで。(Noを選択しても問題無いです。

Requesting a certificate for ssl.test.dev

Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/ssl.test.dev/fullchain.pem
Key is saved at:         /etc/letsencrypt/live/ssl.test.dev/privkey.pem
This certificate expires on 2024-09-21.
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
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

問題無ければ、証明書が発行され所定の場所に格納されます。
証明書の有効期限は3カ月です。

発行したSSL証明書をNginxに適用する

下記のように発行された証明書を指定してあげればOKです。

/etc/nginx/conf.d/ssl.test.dev.conf
server {
  listen 443 ssl;
  server_name ssl.test.dev;
  ssl_certificate /etc/letsencrypt/live/ssl.test.dev/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/ssl.test.dev/privkey.pem;

}

設定したらチェックしてリロード。

sudo nginx -t
sudo systemctl reload nginx

これでHTTPSでのアクセスが可能となっているはずなので、試してみてください。

証明書更新時にNginxをリロードするように設定

証明書の更新自体はcertbotが自動で行ってくれます。
下記のようにcertbot.timerが動いていればOKです。

$ systemctl status certbot.timer
● certbot.timer - Run certbot twice daily
     Loaded: loaded (/usr/lib/systemd/system/certbot.timer; enabled; preset: enabled)
     Active: active (waiting) since Fri 2024-06-21 19:19:19 JST; 1 day 19h ago
    Trigger: Sun 2024-06-23 18:23:27 JST; 3h 9min left
   Triggers: ● certbot.service

Jun 21 19:19:19 server2024 systemd[1]: Started certbot.timer - Run certbot twice daily.

ただし証明書が更新された際に、利用しているNginxをリロードしてあげる必要があります。
その為、certbot.serviceのコマンド(ExecStart)に--post-hookのオプションでNginxのリロードを追加します。

/lib/systemd/system/certbot.service
[Unit]
Description=Certbot
Documentation=file:///usr/share/doc/python-certbot-doc/html/index.html
Documentation=https://certbot.eff.org/docs
[Service]
Type=oneshot
ExecStart=/usr/bin/certbot -q renew --no-random-sleep-on-renew --post-hook "systemctl reload nginx"
PrivateTmp=true

これで証明書を更新した後にNginxがリロードされるようになります。

これで一通りの設定が完了となります。

Discussion