FreeBSD 14.1 に certbot をインストールして Let’s Encrypt の証明書を取得して自動更新まで設定する方法

Let’s Encrypt の証明書を取得する

certbot をインストールする

Let’s Encrypt の証明書を取得するためのツールである certbot をインストールする。

以下のコマンドでは、certbot (py311-certbot) に加えて certbot の Nginx 用プラグイン (py311-certbot-nginx) までインストールしちゃっています。あとで要らないと気づいたので sudo pkg remove py311-certbot-nginx コマンドで削除しました。

nobi@futro:~ % sudo pkg install -y py311-certbot py311-certbot-nginx
Updating FreeBSD repository catalogue...
FreeBSD repository is up to date.
All repositories are up to date.
The following 23 package(s) will be affected (of 0 checked):

New packages to be INSTALLED:
py311-acme: 2.11.0,1
py311-certbot: 2.11.0,1
py311-certbot-nginx: 2.11.0
py311-certifi: 2024.8.30
py311-cffi: 1.17.1
py311-charset-normalizer: 3.3.2_1
py311-configargparse: 1.5.3_1
py311-configobj: 5.0.9
py311-cryptography: 42.0.8_3,1
py311-distro: 1.9.0
py311-idna: 3.10
py311-josepy: 1.14.0
py311-openssl: 24.1.0,1
py311-parsedatetime: 2.6
py311-pycparser: 2.22
py311-pyparsing: 3.1.4
py311-pyrfc3339: 1.1_1
py311-pysocks: 1.7.1_1
py311-pytz: 2024.2,1
py311-requests: 2.32.3
py311-setuptools: 63.1.0_1
py311-six: 1.16.0_1
py311-urllib3: 1.26.20,1

Number of packages to be installed: 23

The process will require 36 MiB more space.
6 MiB to be downloaded.
[1/23] Fetching py311-urllib3-1.26.20,1.pkg: 100% 241 KiB 247.1kB/s 00:01 
[2/23] Fetching py311-pyparsing-3.1.4.pkg: 100% 214 KiB 218.8kB/s 00:01 
[3/23] Fetching py311-cryptography-42.0.8_3,1.pkg: 100% 1 MiB 1.2MB/s 00:01 
[4/23] Fetching py311-cffi-1.17.1.pkg: 100% 282 KiB 288.9kB/s 00:01 
[5/23] Fetching py311-certifi-2024.8.30.pkg: 100% 162 KiB 165.5kB/s 00:01 
[6/23] Fetching py311-distro-1.9.0.pkg: 100% 32 KiB 32.7kB/s 00:01 
[7/23] Fetching py311-configobj-5.0.9.pkg: 100% 69 KiB 70.6kB/s 00:01 
[8/23] Fetching py311-configargparse-1.5.3_1.pkg: 100% 37 KiB 37.6kB/s 00:01 
[9/23] Fetching py311-certbot-nginx-2.11.0.pkg: 100% 183 KiB 186.9kB/s 00:01 
[10/23] Fetching py311-pycparser-2.22.pkg: 100% 230 KiB 235.3kB/s 00:01 
[11/23] Fetching py311-pytz-2024.2,1.pkg: 100% 173 KiB 177.4kB/s 00:01 
[12/23] Fetching py311-pysocks-1.7.1_1.pkg: 100% 32 KiB 32.8kB/s 00:01 
[13/23] Fetching py311-pyrfc3339-1.1_1.pkg: 100% 10 KiB 10.0kB/s 00:01 
[14/23] Fetching py311-six-1.16.0_1.pkg: 100% 27 KiB 27.4kB/s 00:01 
[15/23] Fetching py311-acme-2.11.0,1.pkg: 100% 184 KiB 188.5kB/s 00:01 
[16/23] Fetching py311-charset-normalizer-3.3.2_1.pkg: 100% 90 KiB 92.6kB/s 00:01 
[17/23] Fetching py311-requests-2.32.3.pkg: 100% 120 KiB 122.4kB/s 00:01 
[18/23] Fetching py311-certbot-2.11.0,1.pkg: 100% 907 KiB 928.6kB/s 00:01 
[19/23] Fetching py311-parsedatetime-2.6.pkg: 100% 76 KiB 77.8kB/s 00:01 
[20/23] Fetching py311-openssl-24.1.0,1.pkg: 100% 107 KiB 109.2kB/s 00:01 
[21/23] Fetching py311-josepy-1.14.0.pkg: 100% 67 KiB 68.2kB/s 00:01 
[22/23] Fetching py311-setuptools-63.1.0_1.pkg: 100% 1 MiB 1.5MB/s 00:01 
[23/23] Fetching py311-idna-3.10.pkg: 100% 104 KiB 106.7kB/s 00:01 
Checking integrity... done (0 conflicting)
[1/23] Installing py311-pycparser-2.22...
[1/23] Extracting py311-pycparser-2.22: 100%
[2/23] Installing py311-cffi-1.17.1...
[2/23] Extracting py311-cffi-1.17.1: 100%
[3/23] Installing py311-cryptography-42.0.8_3,1...
[3/23] Extracting py311-cryptography-42.0.8_3,1: 100%
[4/23] Installing py311-pysocks-1.7.1_1...
[4/23] Extracting py311-pysocks-1.7.1_1: 100%
[5/23] Installing py311-setuptools-63.1.0_1...
[5/23] Extracting py311-setuptools-63.1.0_1: 100%
[6/23] Installing py311-urllib3-1.26.20,1...
[6/23] Extracting py311-urllib3-1.26.20,1: 100%
[7/23] Installing py311-certifi-2024.8.30...
[7/23] Extracting py311-certifi-2024.8.30: 100%
[8/23] Installing py311-pytz-2024.2,1...
[8/23] Extracting py311-pytz-2024.2,1: 100%
[9/23] Installing py311-charset-normalizer-3.3.2_1...
[9/23] Extracting py311-charset-normalizer-3.3.2_1: 100%
[10/23] Installing py311-openssl-24.1.0,1...
[10/23] Extracting py311-openssl-24.1.0,1: 100%
[11/23] Installing py311-idna-3.10...
[11/23] Extracting py311-idna-3.10: 100%
[12/23] Installing py311-pyrfc3339-1.1_1...
[12/23] Extracting py311-pyrfc3339-1.1_1: 100%
[13/23] Installing py311-six-1.16.0_1...
[13/23] Extracting py311-six-1.16.0_1: 100%
[14/23] Installing py311-requests-2.32.3...
[14/23] Extracting py311-requests-2.32.3: 100%
[15/23] Installing py311-josepy-1.14.0...
[15/23] Extracting py311-josepy-1.14.0: 100%
[16/23] Installing py311-distro-1.9.0...
[16/23] Extracting py311-distro-1.9.0: 100%
[17/23] Installing py311-configobj-5.0.9...
[17/23] Extracting py311-configobj-5.0.9: 100%
[18/23] Installing py311-configargparse-1.5.3_1...
[18/23] Extracting py311-configargparse-1.5.3_1: 100%
[19/23] Installing py311-acme-2.11.0,1...
[19/23] Extracting py311-acme-2.11.0,1: 100%
[20/23] Installing py311-parsedatetime-2.6...
[20/23] Extracting py311-parsedatetime-2.6: 100%
[21/23] Installing py311-pyparsing-3.1.4...
[21/23] Extracting py311-pyparsing-3.1.4: 100%
[22/23] Installing py311-certbot-2.11.0,1...
[22/23] Extracting py311-certbot-2.11.0,1: 100%
[23/23] Installing py311-certbot-nginx-2.11.0...
[23/23] Extracting py311-certbot-nginx-2.11.0: 100%
=====
Message from py311-urllib3-1.26.20,1:

--
Since version 1.25 HTTPS connections are now verified by default which is done
via "cert_reqs = 'CERT_REQUIRED'". While certificate verification can be
disabled via "cert_reqs = 'CERT_NONE'", it's highly recommended to leave it on.

Various consumers of net/py-urllib3 already have implemented routines that
either explicitly enable or disable HTTPS certificate verification (e.g. via
configuration settings, CLI arguments, etc.).

Yet it may happen that there are still some consumers which don't explicitly
enable/disable certificate verification for HTTPS connections which could then
lead to errors (as is often the case with self-signed certificates).

In case of an error one should try first to temporarily disable certificate
verification of the problematic urllib3 consumer to see if that approach will
remedy the issue.
=====
Message from py311-certbot-2.11.0,1:

--
This port installs the "standalone" client only, which does not use and
is not the certbot-auto bootstrap/wrapper script.

The simplest form of usage to obtain certificates is:

# sudo certbot certonly --standalone -d <domain>, [domain2, ... domainN]>

NOTE:

The client requires the ability to bind on TCP port 80 or 443 (depending
on the --preferred-challenges option used). If a server is running on that
port, it will need to be temporarily stopped so that the standalone server
can listen on that port to complete the challenge authentication process.

For more information on the 'standalone' mode, see:

https://certbot.eff.org/docs/using.html#standalone

The certbot plugins to support apache and nginx certificate installation
will be made available in the following ports:

* Apache plugin: security/py-certbot-apache
* Nginx plugin: security/py-certbot-nginx

In order to automatically renew the certificates, add this line to
/etc/periodic.conf:

weekly_certbot_enable="YES"

More config details in the certbot periodic script:

/usr/local/etc/periodic/weekly/500.certbot-3.11
nobi@futro:~ % certbot --version
certbot 2.11.0
nobi@futro:~ %

certbot を使って証明書を取得する

スタンドアロンモードと呼ばれるモードで証明書を取得します。

スタンドアロンモードとは、certbot が一時的に小さな Web サーバーを起動 (ポート 80 を使用) し、Let’s Encrypt 側のサーバーがその Web サーバーにインターネット側からアクセスして所在確認 (アクセスができたことでドメイン所有者であることを Let’s Encrypt が認証できる) し、この確認が取れたら証明書が発行され、そのあと自動的に Web サーバーを停止してくれる仕組みです。

スタンドアロンモードを使うことと、取得する証明書のドメイン名を指定して certbot を実行する。

nobi@futro:~ % sudo certbot certonly --standalone -d monitoring.gadgets-today.net
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Enter email address (used for urgent renewal and security notices)
(Enter 'c' to cancel): kerama.islands@gmail.com

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Please read the Terms of Service at
https://letsencrypt.org/documents/LE-SA-v1.4-April-3-2024.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: Y
Account registered.
Requesting a certificate for monitoring.gadgets-today.net

Successfully received certificate.
Certificate is saved at: /usr/local/etc/letsencrypt/live/monitoring.gadgets-today.net/fullchain.pem
Key is saved at: /usr/local/etc/letsencrypt/live/monitoring.gadgets-today.net/privkey.pem
This certificate expires on 2025-02-04.
These files will be updated when the certificate renews.

NEXT STEPS:
- The certificate will need to be renewed before it expires. Certbot can automatically renew the certificate in the background, but you may need to take steps to enable that functionality. See https://certbot.org/renewal-setup for instructions.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
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
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
nobi@futro:~ %

証明書を取得できたことを確認する

まずは取得している証明書の一覧を表示させてみる。

nobi@futro:~ % sudo certbot certificates
Saving debug log to /var/log/letsencrypt/letsencrypt.log

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Found the following certs:
  Certificate Name: monitoring.gadgets-today.net
    Serial Number: 4c68277824573c66581117d1fc5d3e30b09
    Key Type: ECDSA
    Domains: monitoring.gadgets-today.net
    Expiry Date: 2025-02-04 13:51:02+00:00 (VALID: 89 days)
    Certificate Path: /usr/local/etc/letsencrypt/live/monitoring.gadgets-today.net/fullchain.pem
    Private Key Path: /usr/local/etc/letsencrypt/live/monitoring.gadgets-today.net/privkey.pem
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
nobi@futro:~ %

次に、証明書関連ファイルを確認する。

nobi@futro:~ % sudo ls -l /usr/local/etc/letsencrypt/live/monitoring.gadgets-today.net/
total 13
-rw-r--r-- 1 root wheel 692 Nov 6 23:49 README
lrwxr-xr-x 1 root wheel 52 Nov 6 23:49 cert.pem -> ../../archive/monitoring.gadgets-today.net/cert1.pem
lrwxr-xr-x 1 root wheel 53 Nov 6 23:49 chain.pem -> ../../archive/monitoring.gadgets-today.net/chain1.pem
lrwxr-xr-x 1 root wheel 57 Nov 6 23:49 fullchain.pem -> ../../archive/monitoring.gadgets-today.net/fullchain1.pem
lrwxr-xr-x 1 root wheel 55 Nov 6 23:49 privkey.pem -> ../../archive/monitoring.gadgets-today.net/privkey1.pem
nobi@futro:~ %

証明書を自動更新する設定

証明書を取得したら、証明書の期限が切れる前に自動更新してくれる設定までしておきたいところ。

以下のスクリプト (999.certbot-renew) を作った。

nobi@futro:~ % ls -l /usr/local/etc/periodic/daily/999.certbot-renew 
-rwxr-xr-x 1 root wheel 419 Nov 7 00:41 /usr/local/etc/periodic/daily/999.certbot-renew
nobi@futro:~ % cat /usr/local/etc/periodic/daily/999.certbot-renew
#!/bin/sh
#
# $FreeBSD$
#

# If there is a global system configuration file, suck it in.
#
if [ -r /etc/defaults/periodic.conf ]; then
    . /etc/defaults/periodic.conf
    source_periodic_confs
fi

case "$daily_certbot_enable" in
    [Yy][Ee][Ss])
        echo
        echo "Renewing Let's Encrypt certificates:"
        /usr/local/bin/certbot renew -q
        exit $?
        ;;
    *)
        exit 0
        ;;
esac
nobi@futro:~ %

このスクリプトは毎日実行されるスクリプトでここから certbot renew を実行しています。certbot renew が実行され、証明書の有効期限が 30 日を切っていることを検知したら証明書を自動更新する、という流れです。

このスクリプトが毎日実行される設定 (periodic 設定) を有効化するために、/etc/periodic.conf ファイルを作成して daily_certbot_enable=”YES” の 1 行を書き込みます。

nobi@futro:~ % echo 'daily_certbot_enable="YES"' | sudo tee -a /etc/periodic.conf
daily_certbot_enable="YES"
nobi@futro:~ % ls -l /etc/periodic.conf
-rw-r--r-- 1 root wheel 27 Nov 7 00:46 /etc/periodic.conf
nobi@futro:~ %

999.certbot-renew のスクリプトにより certbot renew が呼び出されると以下の設定を確認して証明書の自動実行が行われます。

nobi@futro:~ % sudo cat /usr/local/etc/letsencrypt/renewal/monitoring.gadgets-today.net.conf
Password:
# renew_before_expiry = 30 days
version = 2.11.0
archive_dir = /usr/local/etc/letsencrypt/archive/monitoring.gadgets-today.net
cert = /usr/local/etc/letsencrypt/live/monitoring.gadgets-today.net/cert.pem
privkey = /usr/local/etc/letsencrypt/live/monitoring.gadgets-today.net/privkey.pem
chain = /usr/local/etc/letsencrypt/live/monitoring.gadgets-today.net/chain.pem
fullchain = /usr/local/etc/letsencrypt/live/monitoring.gadgets-today.net/fullchain.pem

# Options used in the renewal process
[renewalparams]
account = ae2eef2876cb30c24981f4fb5262599e
authenticator = standalone
server = https://acme-v02.api.letsencrypt.org/directory
key_type = ecdsa
nobi@futro:~ %

# renew_before_expiry = 30 days により、証明書の期限切れとなる 30 日前から自動更新を試みる設定になっています。

その下に更新対象となる証明書関連ファイル (cert.pem など) が表示されています。

そして、# Options used in the renewal process の下に証明書を自動更新する際のパラメーターが記載されています。上記では authenticator = standalone となっていることから、証明書更新時においてもスタンドアロンモードを使う設定になっています。

証明書自動更新のシミュレーション

証明書がちゃんと自動更新されるかどうかが心配である場合はシミュレーションして確認する方法がある。以下のようにする。

nobi@futro:~ % sudo certbot renew --dry-run
Password:
Saving debug log to /var/log/letsencrypt/letsencrypt.log

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Processing /usr/local/etc/letsencrypt/renewal/monitoring.gadgets-today.net.conf
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Simulating renewal of an existing certificate for monitoring.gadgets-today.net

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Congratulations, all simulated renewals succeeded: 
/usr/local/etc/letsencrypt/live/monitoring.gadgets-today.net/fullchain.pem (success)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
nobi@futro:~ %

Congratulations, all simulated renewals succeeded: が表示されればオッケーだ。

シミュレーションはあくまでも自動更新できるかどうかをシミュレーションしているだけのため、シミュレーションでは証明書は更新されない。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください