Nginx+Let’sEncryptで証明書の更新にハマった時の備忘録

VPS
この投稿は最終更新から6年以上経過しているため、内容が古くなっている可能性があります。

無料で使用できるSSL証明書「Let’s Encript」を導入して早2ヶ月。
Cronで自動更新するように設定していたのですが、とある日期限を知らせるメールが届きました。

Hello,
Your certificate (or certificates) for the names listed below will expire in
19 days (on 06 Jul 17 14:52 +0000). Please make sure to renew
your certificate before then, or visitors to your website will encounter errors.

「あと19日で期限が切れるよ」とのことで自動更新に失敗したんだなーと思いつつ、それなら手動でやればいいかと軽く考えたものの、これが結構ハマりました。

Webrootで更新

Let’s Encriptの更新にはざっくり言うとスタンドアローンウェブルートの2種類があります。

更新時に80番ポートを使用するので、スタンドアローンで更新する場合にはサーバを一度止める必要があります。
サーバが稼働した公開状態だと衝突してしまうからです。

一方、サーバを動かしたまま更新したい時にはウェブルートという方法を使用します。
ルートディレクトリに「.well-known」というフォルダを作っておいてその中で更新を行う事でポートの衝突を防ぐことができます。サーバを止めなくて良いので、こちらがオススメということになります。

更新は「/etc/letsencrypt/renewal/ドメイン名.conf」の中身を参照するので、その中身が「authenticator = webroot」となっていれば下記のコマンドを打った時にWebrootで更新してくれます。

./certbot-auto renew

しかしこれを打つと、下記のようなエラーが出ました。

To fix these errors, please make sure that your domain name was entered correctly and the DNS A record(s) for that domain contain(s) the right IP address.

検索して調べてみると、IPアドレスとDNSレコードが一致していない可能性があるとのこと。しかし、何年も前から稼働しているサーバとブログなのでそれは有り得ません。

SSL化した時にリダイレクトしたせいかなとか考えたものの80番も443番もちゃんと外部からアクセスできるし、ドキュメントルートのパスも間違えていない。どうしてかなーと色々試しながら調べていくこと数日。やっと原因っぽいものに辿り着きました。「.well-knownフォルダ」以下にアクセスできない状態になっているようです。

試しにテスト用のHTMLファイルを作成してアップロードし「https://mndangler.net/.well-known/test.html」を叩いてみると403が返ってきました。サーバがアクセスを拒否しています。

そこでやっと気が付きました。自分でやったNginxのセキュリティ設定のせいだ、と。

Nginxのdrop.confの設定で「.」から始まるファイルやフォルダへのアクセスを拒否していたのです。
そりゃ更新もできません。

Nginxの設定を見直す

drop.confの以下をコメントアウトしました。

drop.conf
# .から始まるファイルの場合アクセスを拒否し、アクセスログ、Not foundログを無効にする
#location ~ /\. {
# deny all;
# access_log off;
# log_not_found off;
#}

続いて、server用の設定を書いているconfファイルに以下を追記しました。
参考にされる場合は、/your/webroot/pathの部分を各自のドキュメントルートにしてください。

○○.conf
server {
listen 80;

~ 略 ~

# cerbotのwebroot用
location ^~ /.well-known/acme-challenge/ {
root /your/webroot/path;
}

}

構文チェックをしてから、OKが出たらNginxをリロード。

nginx -t
service nginx reload

Cerbotのディレクトリに移動して、いざ更新。

./certbot-auto renew

ドキドキしながら数秒待つと、やっと成功!

Congratulations, all renewals succeeded. The following certs have been renewed:

ここで終わってはいけません。サーバをリロードしないと反映されません。

service nginx reload

これでブログを開いて証明書を確認すると、有効期限がちゃんと3ヶ月先になっていました。

結論

自分でやった、たいして意味のないセキュリティ強化が首を締める羽目になってしまいました。

今後はちゃんと自動更新できるように、今回いじった設定はそのまま残しておいて、2ヶ月後の更新を見守りたいと思います。