Syntax Error.

[Sy] Amazon Linux(2017.09 release) + Nginx の環境で Let's Encrypt の SSL/TLS 証明書を自動更新する設定

2017/10/21

前回は、無料SSL/TLS証明書 Let’s Encrypt を使って Amazon Linux + Nginx 環境でHTTPSの設定を行いました。今回は 自動更新 の設定について説明します。

前回の記事はこちら。

⇒ [Sy] Amazon Linux(2017.09 release) + Nginx の環境で Let's Encrypt の SSL/TLS 証明書を取得して HTTPS の設定をする手順

0. 更新前の証明書の状態を確認

まずは現状の確認 をしましょう。前回の記事で取得した証明書を見に行きます。

ec2-user として SSH でログインします。

証明書があるディレクトリ(/etc/letsencrypt)は root 権限がないと入れないので、

$ sudo su

で root に切り替えます。(以降#が頭についているのは root での操作を表します)

続けて、/etc/letsencrypt/archive/[対象のドメイン] というディレクトリがあるはずなので、そこへ移動してファイルを確認します。

例として、lets-test.utano.me の証明書であれば、ここにあります。

# cd /etc/letsencrypt/archive/lets-test.utano.me/
# ll
total 16
-rw-r--r-- 1 root root 1805 Oct 20 12:02 cert1.pem
-rw-r--r-- 1 root root 1647 Oct 20 12:02 chain1.pem
-rw-r--r-- 1 root root 3452 Oct 20 12:02 fullchain1.pem
-rw-r--r-- 1 root root 1704 Oct 20 12:02 privkey1.pem

さらに、ここにあるファイルは以下のとおり /etc/letsencrypt/live/[対象のドメイン] という別のディレクトリ内に、シンボリックリンクがつくられてます。

# cd /etc/letsencrypt/live/lets-test.utano.me/
# ll
total 4
lrwxrwxrwx 1 root root  42 Oct 20 12:02 cert.pem -> ../../archive/lets-test.utano.me/cert1.pem
lrwxrwxrwx 1 root root  43 Oct 20 12:02 chain.pem -> ../../archive/lets-test.utano.me/chain1.pem
lrwxrwxrwx 1 root root  47 Oct 20 12:02 fullchain.pem -> ../../archive/lets-test.utano.me/fullchain1.pem
lrwxrwxrwx 1 root root  45 Oct 20 12:02 privkey.pem -> ../../archive/lets-test.utano.me/privkey1.pem
-rw-r--r-- 1 root root 543 Oct 20 12:02 README

この live ディレクトリにある privkey1.pemfullchain.pemnginx の設定ファイルで指定してあげることで、HTTPS で通信できるようになっています。nginx の設定については、前回記事を参照してください)

確認が終わったので、一旦 ec2-user での操作に戻ります。

# exit

1. cron を使って自動更新のコマンドを実行する

ではいよいよ更新をしてみます。以下のコマンドで cron の設定を記述します。

$ crontab -e

vim と同じように操作できます。i を押すなりして、入力モードに切り替え、以下のように1行コマンドのスケジュールを記述します。

(「保存してください」と下に書いてるので、そこまでは保存はしないでそのまま読み進めてください)

*/5 * * * * sudo /home/ec2-user/certbot-auto renew --force-renew --debug --nginx && sudo service nginx restart

cron についての細かい説明は今回は省略しますが、この例だと、「分を5で割り切れる時」=「5,10,…,55分の時」に実行する、というスケジューリングになります。

設定したコマンドは2つに分かれていて、

$ sudo /home/ec2-user/certbot-auto renew --force-renew --debug --nginx
$ sudo service nginx restart

というコマンドを連続で実行することになります。

1つ目のコマンドの certbot-auto renew という部分が 自動更新 のための基本コマンドです。

その基本コマンドに、 前回の取得時と同様に --debug--nginx オプションを忘れずに付けます。

さらに、 通常更新日時が近づいてきてないと自動更新できないようになっているので、 強制的に更新するために --force-renew オプションを付けます。

ということで、1つ目のコマンドで 証明書の更新自体はできます。

ただ、更新された証明書を nginx に改めて読み込ませる必要があるので、2つ目のコマンドで nginx を再起動しているわけです。

この2つのコマンド(証明書の更新+ngins再起動)を組み合わせ、それを cron で自動で実行することで、証明書の定期的な自動更新ができるようになります。

では、 cron の設定を保存してください。

そしてすぐに以下のコマンドを入力して cron のログを監視しながら数分待ちます。

$ sudo tail -f /var/log/cron

こんな感じのログが表示され、リアルタイムで追記されていきます。

Oct 21 01:01:01 ip-10-0-0-153 run-parts(/etc/cron.hourly)[30266]: starting 0anacron
Oct 21 01:01:01 ip-10-0-0-153 anacron[30275]: Anacron started on 2017-10-21
Oct 21 01:01:01 ip-10-0-0-153 anacron[30275]: Jobs will be executed sequentially
Oct 21 01:01:01 ip-10-0-0-153 anacron[30275]: Normal exit (0 jobs run)
Oct 21 01:01:01 ip-10-0-0-153 run-parts(/etc/cron.hourly)[30277]: finished 0anacron
Oct 21 01:22:33 ip-10-0-0-153 crontab[30375]: (ec2-user) BEGIN EDIT (ec2-user)
Oct 21 01:23:30 ip-10-0-0-153 crontab[30375]: (ec2-user) REPLACE (ec2-user)
Oct 21 01:23:30 ip-10-0-0-153 crontab[30375]: (ec2-user) END EDIT (ec2-user)
Oct 21 01:23:37 ip-10-0-0-153 crontab[30378]: (ec2-user) BEGIN EDIT (ec2-user)
Oct 21 01:23:51 ip-10-0-0-153 crontab[30378]: (ec2-user) END EDIT (ec2-user)

しばらく待っていると、1行ログが追記されます。

Oct 21 01:25:01 ip-10-0-0-153 CROND[30384]: (ec2-user) CMD (sudo /home/ec2-user/certbot-auto renew --force-renew --debug --nginx && sudo service nginx restart)

cron によって先ほどのコマンドが実行されたことがわかります。

では処理がうまくいったのか確認しにいきましょう。

Ctrl + C でログの監視を終了します。

2. 自動更新処理の結果を確認

数分待っていると、以下のようなメッセージがターミナル上に表示されます。(出てこなくても気にしなくて良いです)

You have new mail in /var/spool/mail/ec2-user

これは、デフォルトだと cron の実行ログがそのユーザ宛にメールとして送られてくるという設定になっているので、先ほど実行された自動更新処理のログが送られてきたためです。

では中身を見てみましょう。

$ less /var/spool/mail/ec2-user

ファイルが開けたら、次のようなメール形式(From〜から始まる形)でのテキストが確認できるはずです。

ちょっと見づらいですが、まずチェックすべきなのは、 From〜の行末にある時間 です。

この例だと Sat Oct 21 01:25:13 2017 となっており、先ほど cron の処理が流れた時間と一致します。

一致する時間のメールが見つかれば、その本文(X-Cron-Env:という行の終わったあとあたりから)がログになるので、見てみます。

From root@ip-10-0-0-153.ap-northeast-1.compute.internal  Sat Oct 21 01:25:13 2017
Return-Path: <root@ip-10-0-0-153.ap-northeast-1.compute.internal>
Received: from ip-10-0-0-153.ap-northeast-1.compute.internal (localhost [127.0.0.1])
        by ip-10-0-0-153.ap-northeast-1.compute.internal (8.14.4/8.14.4) with ESMTP id v9L1PDQr030468
        for <ec2-user@ip-10-0-0-153.ap-northeast-1.compute.internal>; Sat, 21 Oct 2017 01:25:13 GMT
Received: (from ec2-user@localhost)
        by ip-10-0-0-153.ap-northeast-1.compute.internal (8.14.4/8.14.4/Submit) id v9L1P2Hh030430;
        Sat, 21 Oct 2017 01:25:02 GMT
Date: Sat, 21 Oct 2017 01:25:02 GMT
Message-Id: <201710210125.v9L1P2Hh030430@ip-10-0-0-153.ap-northeast-1.compute.internal>
X-Authentication-Warning: ip-10-0-0-153.ap-northeast-1.compute.internal: ec2-user set sender to root using -f
From: root@ip-10-0-0-153.ap-northeast-1.compute.internal (Cron Daemon)
To: ec2-user@ip-10-0-0-153.ap-northeast-1.compute.internal
Subject: Cron <ec2-user@ip-10-0-0-153> sudo /home/ec2-user/certbot-auto renew --force-renew --debug --nginx && sudo service nginx restart
Content-Type: text/plain; charset=UTF-8
Auto-Submitted: auto-generated
X-Cron-Env: <LANG=en_US.UTF-8>
X-Cron-Env: <SHELL=/bin/sh>
X-Cron-Env: <HOME=/home/ec2-user>
X-Cron-Env: <PATH=/usr/bin:/bin>
X-Cron-Env: <LOGNAME=ec2-user>
X-Cron-Env: <USER=ec2-user>

(↓ここから本文)
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator nginx, Installer nginx
Renewing an existing certificate
Performing the following challenges:
tls-sni-01 challenge for lets-test.utano.me
Waiting for verification...
Cleaning up challenges

-------------------------------------------------------------------------------
Processing /etc/letsencrypt/renewal/lets-test.utano.me.conf
-------------------------------------------------------------------------------

-------------------------------------------------------------------------------
new certificate deployed with reload of nginx server; fullchain is
/etc/letsencrypt/live/lets-test.utano.me/fullchain.pem
-------------------------------------------------------------------------------

-------------------------------------------------------------------------------

Congratulations, all renewals succeeded. The following certs have been renewed:
  /etc/letsencrypt/live/lets-test.utano.me/fullchain.pem (success)
-------------------------------------------------------------------------------
Stopping nginx: [  OK  ]
Starting nginx: [  OK  ]

前回の証明書取得のときと同じようなログが確認できます。Congratulations, ... とあるように、成功したようです。

そして最後の2行で、nginx の再起動を行ってるのも確認できます。

続いて、この記事の最初に確認した /etc/letsencrypt/ ディレクトリの下のファイルはどうなっているか見てみます。

先ほどと同じように、 root に切り替えてから、

$ sudo su

まずは archive ディレクトリの方を見てみます。

# cd /etc/letsencrypt/archive/lets-test.utano.me/
# ll
total 32
-rw-r--r-- 1 root root 1805 Oct 20 12:02 cert1.pem
-rw-r--r-- 1 root root 1805 Oct 21 01:25 cert2.pem
-rw-r--r-- 1 root root 1647 Oct 20 12:02 chain1.pem
-rw-r--r-- 1 root root 1647 Oct 21 01:25 chain2.pem
-rw-r--r-- 1 root root 3452 Oct 20 12:02 fullchain1.pem
-rw-r--r-- 1 root root 3452 Oct 21 01:25 fullchain2.pem
-rw-r--r-- 1 root root 1704 Oct 20 12:02 privkey1.pem
-rw-r--r-- 1 root root 1704 Oct 21 01:25 privkey2.pem

cron が実行された時間でそれぞれ xxxx2.pem というファイルが新しく作成されているのがわかります。これが更新された証明書たちになります。

続いて、 live ディレクトリの方を見てみます。

# cd /etc/letsencrypt/live/lets-test.utano.me/
# ll
total 4
lrwxrwxrwx 1 root root  42 Oct 21 01:25 cert.pem -> ../../archive/lets-test.utano.me/cert2.pem
lrwxrwxrwx 1 root root  43 Oct 21 01:25 chain.pem -> ../../archive/lets-test.utano.me/chain2.pem
lrwxrwxrwx 1 root root  47 Oct 21 01:25 fullchain.pem -> ../../archive/lets-test.utano.me/fullchain2.pem
lrwxrwxrwx 1 root root  45 Oct 21 01:25 privkey.pem -> ../../archive/lets-test.utano.me/privkey2.pem
-rw-r--r-- 1 root root 543 Oct 20 12:02 README

見事に、更新前は xxxx1.pem というファイルを参照していたのが、 xxxx2.pem というファイルに切り替わっています。

このようにシンボリックリンクの自動切り替えをしてくれているため、 nginx の設定ファイルはまったく触る必要がないわけです。

では最後にブラウザ上(Chrome)でも証明書の有効期限が更新されていることを確認します。

Developer Tools を起動し、「Security」タブを開き「View certificate」ボタンをクリックします。

すると Expires(有効期限)が更新した時間の3ヶ月後くらいになっているかと思います。

(本来ちゃんと3ヶ月後になるはずですが、タイムゾーンの設定次第でちょっとずれて見えます)

certbot(Let's Encrypt) 自動更新

以上で確認まで終了です。

ターミナルに戻り、 root から抜けておいてください。

# exit

3. cron のスケジューリングを本来やりたい間隔に変更する

先ほどはテストのために5分間隔で更新処理をスケジューリングしましたが、実際はそんなに細かくする必要はないので、例えば1ヶ月ごと(UTCで毎月1日の0時5分)に更新するなど、適切な間隔にしておきましょう。

以下のコマンドで設定を編集します。

$ crontab -e

「毎月1日の0時5分」であれば、このように書けばOKです。

05 00 01 * * sudo /home/ec2-user/certbot-auto renew --force-renew --debug --nginx && sudo service nginx restart

念のため、最初の1,2ヶ月は更新時間の直後にチェックすると良いでしょう。