CentOS8.2でSSL証明書（Let's Encrypt）をセットアップする手順

| [../](https://qiita.com/taconana/items/e45f19e83c825a9ba75e) |
---
VPSサーバー（CentOS8.2）にSSLサーバー証明書をセットアップした。Let's Encryptを利用した。その手順をメモしておく。


## 無料SSL証明書（Let's Encrypt）作成手順

SSLサーバー証明書であるLet's Encryptは無料であり、有効期限は3か月と短いが、有効期限が切れる前に証明書を自動的に更新してくれるcronジョブを自動設定してくれる。インストールや証明書の発行などの操作には、CertbotというCLIのツールを使う。

Certbotをインストールするには、SnapというCLIツールも必要である。さらに、SnapやCertbotをインストールするにはepelというyumリポジトリの追加が必要がある。

手順は、https://certbot.eff.org/lets-encrypt/centosrhel8-apache にわかりやすく示されている。まず、HTTPサイトをどの環境に構築したいかを選択する。私は、Apache + CentOS/RHEL8を選択した。

タブに「default」と「wildcard」があるが、単一ホストの場合は「default」を選ぶ。「ワイルドカード証明書は、アスタリスクで始まる1つ以上の名前を含む証明書である。ブラウザは、アスタリスクの代わりに任意のラベルを受け入れる。たとえば、*.example.comの証明書は、www.example.com、mail.example.com、hello.example.com、goodbye.example.comに対して有効である」といった説明がある。まずは「default」の手順で進めることにする。

## epelリポジトリの設定

yumリポジトリにepelが既存かどうかを確認し、なければ、以下のようにリポジトリを取り込む。SnapやCertbotのインストール時に参照される。

```bash

$ yum repolist epel
$ yum install https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm -y
```

## Snapのインストールとサービス起動

Snap（サービスはsnapd）をインストールし、サービスを起動する。 snapdサービスは自動実行されるように設定しておく。

```bash

# Snapdをインストールする。
$ yum install snapd

# snapdサービスを自動実行に設定する。
$ systemctl enable --now snapd.socket
Created symlink /etc/systemd/system/sockets.target.wants/snapd.socket → /usr/lib/systemd/system/snapd.socket.
$ ln -s /var/lib/snapd/snap /snap

# snapdサービスを起動する。
$ snap install core
2020-12-01T17:51:01+09:00 INFO Waiting for automatic snapd restart...
Warning: /var/lib/snapd/snap/bin was not found in your $PATH. If youve not restarted your session
         since you installed snapd, try doing that. Please see https://forum.snapcraft.io/t/9469
         for more details.
core 16-2.47.1 from Canonical? installed
$ snap refresh core			# updateがあるかもしれないのでrefreshする。
snap "core" has no updates available
```

## Certbotのインストール

Snapを使って、Certbotをインストールする。

```bash

$ snap install --classic certbot
certbot 1.9.0 from Certbot Project (certbot-eff?) installed
$ ln -s /snap/bin/certbot /usr/bin/certbot

# バージョンを確認しておく。
$ httpd -version
Server version: Apache/2.4.37 (centos)
Server built:   Sep 15 2020 15:41:16
$ certbot --version
certbot 1.10.1
```

## バーチャルホストの設定
certbot を実行する前に、httpd.conf でバーチャルホストとして80ポートを定義しておく必要がある。設定せずにcertbot を実行すると、以下のような警告が出る。

```

Unable to find a virtual host listening on port 80 which is currently 
needed for Certbot to prove to the CA that you control your domain. 
Please add a virtual host for port 80.
```

/etc/httpd/conf/httpd.conf を開いてみると、末尾でconf.d/*.conf をインクルードするようになっている。SSLに関する設定は、/etc/httpd/conf.d/ssl.conf で行い、バーチャルホストに関する設定は、/etc/httpd/conf.d/vhost-xxx.conf のようなファイルで行うのが一般的なようだ。私は、ネームベースでバーチャルホストをいくつか追加したいので、以下のネーミングで作成してみた。

- ssl.conf（default:443用／これは当面、既存のものを使う）
- vhost-00.conf（default:80用／手作業で作成）
- vhost-01-xxx.conf（xxx.jp:80用／手作業で作成）
- vhost-02-kankeri.conf（kankeri.com:80用／手作業で作成）
- vhost-02-kankeri-le-ssl.conf（kankeri.com:443用／Certbotが自動生成）

```bash

$ cd /etc/httpd/conf.d/
$ touch vhost-00.conf 
$ touch vhost-01-xxx.conf
$ touch vhost-02-kankeri.conf
```

## vhost-00.confの記述（_default_:80）

```bash

$ vi /etc/httpd/conf.d/vhost-00.conf
<VirtualHost _default_:80>
    ServerName any
    <Location />
         Require all denied
    </Location>
</VirtualHost>
```

## SSLを使用したいドメインの記述（kankeri.com:80）

たとえば、kankeri.com:443のバーチャルホストを作成したいなら、事前にkankeri.com:80のバーチャルホストを定義しておく必要がある。/etc/httpd/conf.d/vhost-02-kankeri.conf に以下の感じで記述しておく。

```bash
$ vi /etc/httpd/conf.d/vhost-02-kankeri.conf
<VirtualHost kankeri.com:80>
ServerName kankeri.com
ServerAlias www.kankeri.com
ServerAdmin webmaster@kankeri.com
DocumentRoot "/var/www/html/kankeri"
 
<Directory "/var/www/html/kankeri">
    Options FollowSymLinks
    AllowOverride All
#   Order deny,allow
#   Allow from all
    Require all granted
</Directory>

ErrorLog logs/kankeri-error_log
CustomLog logs/kankeri-access_log combined
</VirtualHost>
```
DocumentRootを /var/www/html/kankeriにしたので、そこにダミーのHTMLを配置しておく。

```bash
$ cd /var/www/html
$ mkdir -p kankeri
$ cp /var/www/html/index.html kankeri
$ vi kankeri/index.html					# 適当に編集
$ chown -R apache.apache /var/www/html/kankeri
```
 
バーチャルホストを定義し、適当なHTMLを配置したら、httpdを再起動する。

```bash
$ httpd -t
$ systemctl restart httpd
```

## httpsサービスの追加

Firewallにhttpsサービス（ポート443）がまだ追加されていないなら、対応しておくこと。mod_sslもインストールしておく。

```bash
$ yum install mod_ssl
$ firewall-cmd --add-service=https --zone=public --permanent
$ firewall-cmd --reload
```

## certbotの実行

では、certbotに戻って手順を進める。--apacheを引数に与えてcertbotを実行するだけである。

```bash
$ certbot --apache
Saving debug log to /var/log/letsencrypt/letsencrypt.log
```

初回の実行のときのみ以下の確認が出る。2回目以降は出ない。

```
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator apache, Installer apache
Enter email address (used for urgent renewal and security notices)
 (Enter 'c' to cancel): staff@kankeri.com
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Please read the Terms of Service at
https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf. You must
agree in order to register with the ACME server at
https://acme-v02.api.letsencrypt.org/directory
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(A)gree/(C)ancel: A

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

続けて、ドメインを選択する。エリアスが記述されているとそれも候補に並ぶようだ。私は「kankeri.com」を選んだ。バーチャルホストとして /etc/httpd/conf.d/vhost-02-kankeri.conf に定義済みである。
 
```
Which names would you like to activate HTTPS for?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: xxx.jp
2: www.xxx.jp
3: kankeri.com
4: www.kankeri.com
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Select the appropriate numbers separated by commas and/or spaces, or leave input
blank to select all options shown (Enter 'c' to cancel): 3
Requesting a certificate for kankeri.com
Performing the following challenges:
http-01 challenge for kankeri.com
Waiting for verification...
Cleaning up challenges
Created an SSL vhost at /etc/httpd/conf.d/vhost-02-kankeri-le-ssl.conf
Deploying Certificate to VirtualHost /etc/httpd/conf.d/vhost-02-kankeri-le-ssl.conf
Redirecting vhost in /etc/httpd/conf.d/vhost-02-kankeri.conf to ssl vhost in /etc/httpd/conf.d/vhost-02-kankeri-le-ssl.conf

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Congratulations! You have successfully enabled https://kankeri.com
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Subscribe to the EFF mailing list (email: staff@kankeri.com).

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:
   /etc/letsencrypt/live/kankeri.com/fullchain.pem
   Your key file has been saved at:
   /etc/letsencrypt/live/kankeri.com/privkey.pem
   Your cert will expire on 2021-03-02. To obtain a new or tweaked
   version of this certificate in the future, simply run certbot again
   with the "certonly" option. To non-interactively renew *all* of
   your certificates, run "certbot renew"
 - 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
```

証明書(公開鍵を含む)とチェーンは、/etc/letsencrypt/live/kankeri.com/fullchain.pem に生成され、秘密鍵は、/etc/letsencrypt/live/kankeri.com/privkey.pem に生成されている。有効期限が3か月である。将来、この証明書の新しいバージョンを取得するには 「certbot certonly」を実行せよ、すべてを更新するなら「certbot renew」を実行せよ、と教えてくれる。

Certbotパッケージには、有効期限が切れる前に証明書を自動的に更新するcronジョブまたはsystemdタイマーが付属していて、構成を変更しない限り、Certbotを再度実行する必要はないそうだ。以下のようにスケジュールされていた。

```bash
$ systemctl list-timers
NEXT                                  LEFT LAST  PASSED UNIT                      ACTIVATES
Wed 2020-12-02 19:31:00 JST  3h 57min left n/a   n/a    snap.certbot.renew.timer  snap.certbot.renew.service
```
 
## バーチャルホストの確認

選択したドメイン「kankeri.com」のバーチャルホストを定義していた /etc/httpd/conf.d/vhost-02-kankeri.conf に対して、/etc/httpd/conf.d/vhost-02-kankeri-le-ssl.conf が生成されている。中身は、以下のようになる。80ポートの記述を443ポートにコピーして、末尾に証明書と秘密鍵の所在を SSLCertificateFile と SSLCertificateKeyFile で追記している。options-ssl-apache.conf も読み込むようになっている。

```

<IfModule mod_ssl.c>
<VirtualHost kankeri.com:443>
ServerName kankeri.com
ServerAlias www.kankeri.com
ServerAdmin webmaster@kankeri.com
DocumentRoot "var/www/html/kankeri"

<Directory "/var/www/html/kankeri">
    Options FollowSymLinks
    AllowOverride All
#   Order deny,allow
#   Allow from all
    Require all granted
</Directory>

ErrorLog logs/kankeri-error_log
CustomLog logs/kankeri-access_log combined

SSLCertificateFile /etc/letsencrypt/live/kankeri.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/kankeri.com/privkey.pem
Include /etc/letsencrypt/options-ssl-apache.conf
</VirtualHost>
</IfModule>
```

また、/etc/httpd/conf.d/vhost-02-kankeri.conf の方も書き換わっている。Rewriteの4行は、http:/でアクセスされたときにhttps:/にリダイレクトするための設定である。

```

<VirtualHost kankeri.com:80>
ServerName kankeri.com
ServerAlias www.kankeri.com
ServerAdmin webmaster@kankeri.com
DocumentRoot "/var/www/html/kankeri"

<Directory "/var/www/html/kankeri">
    Options FollowSymLinks
    AllowOverride All
#   Order deny,allow
#   Allow from all
    Require all granted
</Directory>

ErrorLog logs/kankeri-error_log
CustomLog logs/kankeri-access_log combined
RewriteEngine on
RewriteCond %{SERVER_NAME} =kankeri.com[OR]
RewriteCond %{SERVER_NAME} =www.kankeri.com
RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
</VirtualHost>
```
 
生成された証明書(公開鍵を含む)と秘密鍵は、/etc/letsencrypt/live/kankeri.comに作成されている。リンクになっていて、実体は /etc/letsencrypt/archive/kankeri.comにある。

```bash

$ ls -la /etc/letsencrypt/live/kankeri.com
lrwxrwxrwx 1 root root 34  2 13:37 cert.pem -> ../../archive/kankeri.com/cert1.pem
lrwxrwxrwx 1 root root 35  2 13:37 chain.pem -> ../../archive/kankeri.com/chain1.pem
lrwxrwxrwx 1 root root 39  2 13:37 fullchain.pem -> ../../archive/kankeri.com/fullchain1.pem
lrwxrwxrwx 1 root root 37  2 13:37 privkey.pem -> ../../archive/kankeri.com/privkey1.pem
```

## 動作確認

httpdサービスを再起動し、ブラウザからアクセスして確認してみる。

```bash

$ httpd -t
$ systemctl restart httpd
```
以下のssltestというサイトにアクセスして診断してもらえる。ドメイン名(私の場合、kankeri.com)を指定してsubmitする。おそらく、エラーがあれば指摘してくれるはず。
https://www.ssllabs.com/ssltest/analyze.html

また、https://kankeri.com/ にアクセスして、鍵マークになり、証明書が参照できることを確認する。私の場合、DST Root CSX3 →R3 →Kankeri.comといった証明のパスになっていた。

しかし、https://www.kankeri.com/ にアクセスすると、保護されていない通信となる。バーチャルホストの記述でエイリアスとして指定しただけでは足らないようだ。ドメイン選択時に複数を指定すればよかったのかもしれない。

```
Select the appropriate numbers separated by commas and/or spaces, or leave input
blank to select all options shown (Enter 'c' to cancel):
```

## 複数ドメインへの対応（certbotの再実行）

certbotを再実行して、複数ドメイン（エリアスを含めて）を選択してみた。

```bash

$ certbot certonly --apache
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator apache, Installer apache

Which names would you like to activate HTTPS for?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: xxx.jp
2: www.xxx.jp
3: kankeri.com
4: www.kankeri.com
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Select the appropriate numbers separated by commas and/or spaces, or leave input
blank to select all options shown (Enter 'c' to cancel): 3,4

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
You have an existing certificate that contains a portion of the domains you
requested (ref: /etc/letsencrypt/renewal/kankeri.com.conf)

It contains these names: kankeri.com

You requested these names for the new certificate: kankeri.com, www.kankeri.com.

Do you want to expand and replace this existing certificate with the new
certificate?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(E)xpand/(C)ancel: E

Renewing an existing certificate for kankeri.com and www.kankeri.com
Performing the following challenges:
http-01 challenge for www.kankeri.com
Waiting for verification...
Cleaning up challenges

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:
   /etc/letsencrypt/live/kankeri.com/fullchain.pem
   Your key file has been saved at:
   /etc/letsencrypt/live/kankeri.com/privkey.pem
   Your cert will expire on 2021-03-03. To obtain a new or tweaked
   version of this certificate in the future, simply run certbot
   again. To non-interactively renew *all* of your certificates, run
   "certbot renew"
 - If you like Certbot, please consider supporting our work by:

   Donating to ISRG / Lets Encrypt:   https://letsencrypt.org/donate
   Donating to EFF:                   https://eff.org/donate-le

$ systemctl restart httpd
```
これにより、https://kankeri.com/ にアクセスしても、https://www.kankeri.com/ にアクセスしても保護された通信になってくれた。/etc/letsencrypt/archive/kankeri.comの配下には、以下のようにインクリメントされたファイルで証明書と秘密鍵が生成されている。

```bash
$ ls -la /etc/letsencrypt/archive/kankeri.com
-rw-r--r-- 1 root root 1830 12月  2 13:37 cert1.pem
-rw-r--r-- 1 root root 1850 12月  3 13:03 cert2.pem
-rw-r--r-- 1 root root 1586 12月  2 13:37 chain1.pem
-rw-r--r-- 1 root root 1586 12月  3 13:03 chain2.pem
-rw-r--r-- 1 root root 3416 12月  2 13:37 fullchain1.pem
-rw-r--r-- 1 root root 3436 12月  3 13:03 fullchain2.pem
-rw------- 1 root root 1704 12月  2 13:37 privkey1.pem
-rw------- 1 root root 1704 12月  3 13:03 privkey2.pem
```

## 補足1：ForbiddenやAH01630のエラー対応

CentOS8.2では、Apache2.4に上がっていた。そのため、/ete/httpd/conf.d/*.conf のDirectoryタグの記述では、Require all granted に変更する必要がある。以下の感じである。古い記述のままだと、画面に「Forbidden: You don't have permission to access /var/www/html/xxx on this server.」が出たり、/var/log/httpd/ 内のログファイルに「AH01630: client denied by server configuration: xxx」のようなエラーが出る。

```
<Directory "/var/www/html/kankeri">
    Options FollowSymLinks
    AllowOverride All
#   Order deny,allow
#   Allow from all
    Require all granted
</Directory>
```

以上

| [../](https://qiita.com/taconana/items/e45f19e83c825a9ba75e) |
---