🌊

Nginx+リバースプロキシ環境でWebサーバを停止させずに Let's Encrypt (Certbot) のSSL証明書を自動更新する

2021/02/21に公開

はじめに

Let's Encrypt の証明書を入手・更新するためのcertbotコマンドには以下のモードがあります。

  • webroot
  • standalone
  • apache
  • nginx
  • manual

Getting certificates (and chosing plugins)

証明書を入手・更新するときにはいずれかのモードを指定します。

webrootはそのドメインで稼働しているサイトのwebroot(サーバのパス)を指定します。例えば example.com/var/www/html 以下のHTMLファイルを配信しているとしたらwebroot/var/www/html になります。

standaloneはWebサーバを停止した状態で実行します。webrootを指定する必要はありませんが、サーバを一時的に停止させなければいけません。

apacheはWebサーバとしてApacheを使用している場合に使用できます。webrootを指定したりWebサーバを止めたりする必要がありません。

nginxapacheのNginx版です。apache同様にwebrootの指定やWebサーバの停止が不要です。

上記の中で、standaloneはなるべく避けたいです。なぜなら Let's Encrypt の証明書の有効期限は90日で、更新処理を行うたびにWebサーバを止めるのは可用性に問題があるからです。

そのためwebrootを使用するほうがいいですが、RailsやExpressなどのWebアプリケーションを稼働させていてリバースプロキシを使用している場合はこのモードは使用できません。webrootはあくまで静的ファイルを配信するときのサーバのパスなので、リバースプロキシを使用している場合はそのパスが存在しません。

そこでリバースプロキシを使用している場合でもWebサーバを止めずに更新処理を行う方法として apache, nginx モードがあります。WebサーバにApacheを使用している場合はこのモードを使用するのがベストでしょう。ところがNginxを使用している場合は少しだけ問題があります。

apacheは元々あったモードですが、nginxモードはCertbotのバージョンが0.9.0から導入されたもので、0.9.0がリリースされたのは2016年10月5日なのでつい1ヶ月前のことです。(Release v0.9.0 · certbot/certbot)

ソースはGitHubに公開されているので、ソースからビルドすればおそらくは使用できますが、OSのパッケージマネージャーからインストールした場合(正規のインストール方法の場合)はまだリポジトリに登録されておらず0.9.0以降のバージョンが使用できない場合があります。この記事を書いている時点でyumリポジトリはまだ更新されていませんでした。

なので今回は、Nginxを使用していて、リバースプロキシを使用している環境でもWebサーバを停止させずに更新処理を行う方法を紹介します。

Certbotのインストール

Certbotをインストールしていない場合(はじめて Let's Encrypt で証明書を発行してもらう場合)はCertbotをインストールしてください。

公式サイトにアクセスして、使用しているWebサーバとOSを選択してください。WebサーバとOSを選択するとページが切り替わります。表示されたページの一番はじめにInstallという項目があるので、その項目中に書かれているコマンドを実行します。

Webサーバ、OSごとにインストールコマンドが異なるのでここではすべては列挙できませんが、例として、CentOS 7Ubuntu 16.10 (yakkety) では以下の通りです。

CentOS7
$ sudo yum -y install certbot
Ubuntu16.10
$ sudo apt-get -y install certbot

それ以外のOSを使用している場合は各自で調べてください。また今回はNginxについての記事ですが、Apacheを使用する場合はまた違うコマンドになるので注意してください。

設定方法

今回行う方法は、リバースプロキシを使用している場合でも仮想的にwebrootを作り出して、webrootモードで更新処理を行う、という方法です。

この設定方法に関しては、以下のサイトを大いに参考にさせていただきました:pray:
Let's Encrypt Auto-Renewal for Nginx Reverse Proxies

webrootの生成

まずは仮想webrootとなるディレクトリ(パス)を生成します。

$ sudo mkdir -p /var/www/ssl-proof/rancher/.well-known

次に確認用のHTMLを生成します。

$ sudo touch /var/www/ssl-proof/rancher/.well-known/test.html

生成されたtest.htmltestと書いて保存します。testではなくてもいいです。書いた内容があとで確認できればOKです。

webrootの設定

Nginxに先ほど作成した仮想webrootの設定をします。Nginxの設定ファイルを開いて以下の内容を追加します。Nginxの設定ファイルのパスは適宜読み替えてください。

/etc/nginx/conf.d/nginx.conf
http {
    server {
        # listenやserver_name

        location /.well-known {
            root  /var/www/ssl-proof/rancher/;
        }

        # リバースプロキシの設定
        # SSLの設定 (まだ証明書の発行をしていない場合はあとで記述してください。詳細は省略)
        # エラーページの設定
    }
}

webrootに関係ない設定は省略していますが、locationに先ほどのパスを設定します。

設定が終わったら、Nginxを再起動します。

$ sudo systemctl restart nginx

# または

$ sudo nginx -s reload

設定の確認

正しくwebrootが設定されたことを確認します。http://example.com/.well-known/test.html にアクセスしてtestと表示されていればOKです。example.com は自分のドメインを入力してください。

確認が完了したらtest.htmlは削除してください。削除するファイルを間違えないように注意してください。

$ sudo rm /var/www/ssl-proof/rancher/.well-known/test.html

証明書の発行

Let's Encrypt から証明書の発行をしてもらいます。すでに発行済みの場合でも、前回に違うモードで入手・更新した場合は同様です。

$ sudo certbot certonly --webroot -w /var/www/ssl-proof/rancher/ -d example.com

example.comには証明書を発行してもらいたい自分のドメインを入力してください。

証明書の発行に成功すると以下のように表示されます。

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at
   /etc/letsencrypt/live/example.com/fullchain.pem. Your cert
   will expire on 2016-11-05. To obtain a new version of the
   certificate in the future, simply run Certbot again.
 - If you lose your account credentials, you can recover through
   e-mails sent to admin@example.com.
 - Your account credentials have been saved in your Certbot
   configuration directory at /etc/letsencrypt. You should make a
   secure backup of this folder now. This configuration directory will
   also contain certificates and private keys obtained by Certbot so
   making regular backups of this folder is ideal.
 - 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

証明書が発行されたらNginxを再起動する必要があります。

$ sudo systemctl restart nginx

# または

$ sudo nginx -s reload

これで、リバースプロキシを使用しているNginxでもwebrootモードで証明書の更新を行うことができました!

次回以降の証明書の更新

一度、上記のモードで更新した場合は、次回以降はrenewコマンドで前回の設定と全く同じ条件で証明書の更新を行うことができます。

$ sudo certbot renew

あとはcronなどを使用して定期的に実行するように設定すればOKです。

ただし、証明書の更新は、現在有効の証明書の有効期限が30日を切らないと更新できないようになっています。30日を切っていないときでも強制的に更新処理を行いたい場合はオプションをつけます。

$ sudo certbot renew --force-renew

上記コマンドの実行は一つ注意しなければいけません。Let's Encrypt では証明書を更新できる回数に制限を設けています。公式サイトを確認すると、1ドメインにつき、1週間に20回まで、と記述されています。

Rate Limits - Let's Encrypt

ふつうに使っている分にはこの制限に引っかかることはまずないですが、制限があることは覚えておいてください。

ちなみに更新できるかどうかを確かめたいだけなら以下のオプションをつければOKです。

$ sudo certbot renew --dry-run

--dry-runオプションは現在の設定でrenewコマンドを実行したときにちゃんと更新できるかどうかを確認できます。確認するだけなので実際の更新処理は行いません。つまり更新制限に引っかかる心配もありません。なので、強制的に更新しなければいけないとき以外は--force-renewはつけないことをおすすめします。

繰り返しになりますが、証明書の取得、更新後はNginxの再起動を忘れずに行ってください。

結論だけを完結にまとめると、2回目以降に行わなければいけないコマンドは

$ sudo certbot renew
$ sudo nginx -s reload

の2つだけです。

参考サイト

GitHubで編集を提案

Discussion