さて当サイトはLet’s Encryptの認証を得ていて、毎週月曜日のバッチで更新チェックをやっている。Let’s Encryptの認証は3か月で切れてしまうので、期限のチェックと更新は大事なルーチンなのだ。だが、お約束というかなんというか、当サイトは3か月目の最初の更新に失敗し5時間ほど不通だった。
Let’s Encryptの更新バッチは割にシンプルで、失敗する要素はあまりない。なんで失敗するのかよく分からないので原因を突き詰めることにした。まずはログを調べてみよう。certbotは/var/log/letsencrypt
ディレクトリにログを残してくれるので、これをチェックすればよい。見てみるとこんな記述があった。
2019-07-29 09:17:54,215:DEBUG:certbot.plugins.selection:Requested authenticator nginx and installer nginx 2019-07-29 09:17:54,218:DEBUG:certbot.plugins.disco:No installation (PluginEntryPoint#nginx): Could not find a usable 'nginx' binary. Ensure nginx exists, the binary is executable, and your PATH is set correctly. 2019-07-29 09:17:54,220:INFO:certbot.main:Could not choose appropriate plugin: The nginx plugin is not working; there may be problems with your existing configuration. The error was: NoInstallationError("Could not find a usable 'nginx' binary. Ensure nginx exists, the binary is executable, and your PATH is set correctly.",) 2019-07-29 09:17:54,220:WARNING:certbot.renewal:Attempting to renew cert (north.thco.mp) from /etc/letsencrypt/renewal/north.thco.mp.conf produced an unexpected error: The nginx plugin is not working; there may be problems with your existing configuration. The error was: NoInstallationError("Could not find a usable 'nginx' binary. Ensure nginx exists, the binary is executable, and your PATH is set correctly.",). Skipping.
なんか、nginxが見つからないと文句を言っている。
実はcertbotは、コマンドラインから起動すると問題なく動く。期限が切れてしまったので再取得しようとしたときも問題ないし、そのあとのrenewのテストをやろうと思って
certbot --dry-run renew
と起動してもちゃんと動く。もしかして環境の問題かな? と思って、起動スクリプトの方を見直すことにした。certbotの起動時には、/etc/cron.d/certbot-renew
というファイルからこんな風に起動している。
MAILTO= 13 9 * * mon root /usr/bin/certbot renew --post-hook "systemctl restart nginx" | logger -t certbot-renew -p local0.info
ここでは環境変数PATH
には何も指定していないので、おそらくデフォルトの非常に短いPATHしか通っていないのだろう。実際に確認してみると /usr/bin:/bin
というひどいありさまだった。これではどうしようもないので、nginxにPATHが通るように次のように指定してみた。
PATH=/usr/sbin:/usr/bin:/bin MAILTO= 13 9 * * mon root /usr/bin/certbot renew --post-hook "systemctl restart nginx" | logger -t certbot-renew -p local0.info
--dry-run
をつけてテストしたところ問題なく動作したので、これでOKのようだ。
Apacheはどうなの?
さて環境変数の問題となると、これまで運用してきた他のサイトはどうやねん、というのが気になる。「失敗する要素はあまりない」と冒頭に書いたが、Let’s Encryptで運用しているHTTPSサイトは他にもあり、そちらでは問題なく更新できているからだ。ただ、違いと言えばそちらはApacheで運用しているということぐらいだ。
というわけでそちらのサイトのログもチェックしてみよう。
2019-07-22 09:30:18,304:DEBUG:certbot.plugins.selection:Requested authenticator apache and installer apache 2019-07-22 09:30:18,333:DEBUG:certbot.plugins.util:Can't find apachectl, attempting PATH mitigation by adding /usr/sbin:/usr/local/bin:/usr/local/sbin
というわけでApacheも似たようなエラーを出していた。だが、Apacheのプラグインはapachectl
なしでも認証を続けてくれるようで、証明書の更新自体はちゃんと終わっていた。そうだったのかcertbot。ということでこちらにもちゃんとPATHを設定しておくことにした。
もうひとつ、今回certbotのログを読んでわかったのがこれ。
2019-07-22 09:29:02,229:INFO:certbot.renewal:Non-interactive renewal: random delay of 76 seconds
これまで、管理しているサイトごとに色々工夫してランダムな時刻を設定していたのだが、意味がないことが発覚したので、管理の意味も込めてなるべく統一コードで済ませるようにしていきたいと思う。
あと、本来ならrenewに失敗したときにうまくhookしたいのだが、今のところいい知恵が浮かばないので、別の機会にネタにしたい。