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: が表示されればオッケーだ。
シミュレーションはあくまでも自動更新できるかどうかをシミュレーションしているだけのため、シミュレーションでは証明書は更新されない。