Certbot で証明書発行をしてサイトを TLS 化させる（nginx, AlmaLinux9）

自宅サーバー内のサービスや API で使っている HTTP 通信の TLS 化ってよくしますよね（？）
忘れがちなのでメモを残します。（執筆日：2024/04/20）

## 環境

- AlmaLinux 9（proxmox VE上の仮想マシン）
- nginx

## 始める前に

今回は nginx を TLS 化させようとしていますが、前提として以下の状態になっている必要があります。[^1]

- nginx ホストのポートの 80 と 443 が開いている
- firewall で http と https の通信が許可されている
- .well-known ディレクトリにパブリックからのアクセス許可がある
- SELinux が無効、あるいは適切に設定されている
- ルーターの設定で nginx ホストがインターネットから到達できるようになっている

上記の手順はここでは省きます。

## 手順

### 1. EPEL のインストール

epel をインストールして、OSパッケージ一覧を更新します。

```sh
sudo dnf install epel-release
sudo dnf upgrade
```

### 2. snap のインストール

まずは以下を実行してバイナリをインストールします。

```sh
sudo dnf install snapd
```

結果↓

```
[sudo] password for nissie:
Extra Packages for Enterprise Linux 9 openh264 (From Cisco) - x86_64                                                                                               1.5 kB/s | 2.5 kB     00:01
Dependencies resolved.
===================================================================================================================================================================================================
 Package                                                      Architecture                           Version                                       Repository                                 Size
===================================================================================================================================================================================================
Installing:
 snapd                                                        x86_64                                 2.61.2-0.el9                                  epel                                       16 M
Installing dependencies:
 bash-completion                                              noarch                                 1:2.11-4.el9                                  baseos                                    291 k
 checkpolicy                                                  x86_64                                 3.5-1.el9                                     appstream                                 345 k
 libpkgconf                                                   x86_64                                 1.7.3-10.el9                                  baseos                                     35 k
 pkgconf                                                      x86_64                                 1.7.3-10.el9                                  baseos                                     40 k
 pkgconf-m4                                                   noarch                                 1.7.3-10.el9                                  baseos                                     14 k
 pkgconf-pkg-config                                           x86_64                                 1.7.3-10.el9                                  baseos                                    9.9 k
 policycoreutils-python-utils                                 noarch                                 3.5-3.el9_3                                   appstream                                  71 k
 python3-audit                                                x86_64                                 3.0.7-104.el9                                 appstream                                  82 k
 python3-distro                                               noarch                                 1.5.0-7.el9                                   appstream                                  36 k
 python3-libsemanage                                          x86_64                                 3.5-2.el9                                     appstream                                  79 k
 python3-policycoreutils                                      noarch                                 3.5-3.el9_3                                   appstream                                 2.0 M
 python3-setools                                              x86_64                                 4.4.3-1.el9                                   baseos                                    551 k
 python3-setuptools                                           noarch                                 53.0.0-12.el9                                 baseos                                    839 k
 snap-confine                                                 x86_64                                 2.61.2-0.el9                                  epel                                      2.6 M
 snapd-selinux                                                noarch                                 2.61.2-0.el9                                  epel                                      114 k
 xdelta                                                       x86_64                                 3.1.0-16.el9                                  epel                                       88 k

Transaction Summary
===================================================================================================================================================================================================
Install  17 Packages

Total download size: 23 M
Installed size: 78 M
```

（依存多いな）

次に以下を実行して snapd を有効化させます。

```sh
sudo systemctl enable --now snapd.socket
```

certbot を入れるにはクラシックな snap を利用する必要があるみたいなので？以下を実行してシンボリックを張ります。

```sh
sudo ln -s /var/lib/snapd/snap /snap
```

シンボリックリンクを張るステップをスキップすると次の certbot のインストールで以下のエラーがでますので注意しましょう。（横着してスキップした私が遭遇したエラーでもあります（？））

```sh
$ sudo snap install --classic certbot
error: cannot install "certbot": classic confinement requires snaps under /snap or symlink from /snap to /var/lib/snapd/snap
```

シンボリックリンクを張ったら、サーバーに再ログインします。

### 3. certbot のインストール

以下のコマンドでインストールします。（私の環境では体感で30分ほど待ちました。長かったです。。）

```sh
sudo snap install --classic certbot
```

以下を実行してシンボリックリンクを作成します。

```sh
sudo ln -s /snap/bin/certbot /usr/bin/certbot
```

### 4. 証明書のインストール

以下を実行し、インタラクティブなプログラムの質問に答えていくと作成されます。

```sh
sudo certbot --nginx
```

結果

```
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.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: N（Let's Encrypt プロジェクトの最新のニュースやキャンペーン広告を受け取りたいか。私は要らないかな）
Account registered.

Which names would you like to activate HTTPS for?
We recommend selecting either all domains, or all domains in a VirtualHost/server block.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: hoge.example.com（NGINX にあらかじめ設定したserverのserver_name。すでに80と443が疎通できている状態）
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Select the appropriate numbers separated by commas and/or spaces, or leave input
blank to select all options shown (Enter 'c' to cancel): 1（上の表で証明書を発行したいserverを選択）
Requesting a certificate for hoge.example.com

Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/hoge.example.com/fullchain.pem
Key is saved at:         /etc/letsencrypt/live/hoge.example.com/privkey.pem
This certificate expires on 2024-07-19.
These files will be updated when the certificate renews.
Certbot has set up a scheduled task to automatically renew this certificate in the background.

Deploying certificate
Successfully deployed certificate for hoge.example.com to /etc/nginx/conf.d/example.conf
Congratulations! You have successfully enabled HTTPS on https://hoge.example.com

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
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
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 

```

エラーなくプロンプトが返ってきたら作成完了です！ TLS 化されたのではないでしょうか？

## うっかりポイントと解決方法

### 1. firewall が https を許可していない

証明書発行までいけたのにアクセスできない！と思ったら firewall でポート 443 番を塞いでたんだな〜〜。
ということで以下を実行します。

```sh
sudo firewall-cmd --add-service=https --permanent
sudo firewall-cmd --reload
```

## 学び

今回使った割と新しい　Certbot（2.10.0） では、証明書再発行の自動化がされているらしく、わざわざ renew コマンドを cron に登録しなくていいらしい！最高！

## 参考

- https://certbot.eff.org/instructions?ws=nginx&os=arch
- https://snapcraft.io/docs/installing-snap-on-almalinux
- https://qiita.com/kenjjiijjii/items/1057af2dddc34022b09e

[^1]:自分で書いてて「前提条件多すぎwww」ってなったのでどこかで詳細を書く（かもしれない）