というわけで、Let's Encryptの自動更新をcron化したわけなのですが、つぶやいているとおり地味に苦労した部分があったのでその際のメモです。
なお、自分の環境は
- CentOS 6.9
- Let’s Encryptを導入済み
standaloneプラグイン利用
となっております。
はじめに
まず今までの更新は以下の手順で行っていました。
$ sudo service httpd stop
$ /path/to/certbot/certbot-auto certonly --standalone -d shimabox.net -d blog.shimabox.net
$ sudo service httpd start※ certbot のパスは自身のもので読み替えてください
※ --webrootではなく、--standaloneを使っているので一旦apacheを止める必要があります
※ 最近サブドメのワイルドカードもいけるようになったっぽい
これを Let's Encrypt Expiry Bot から、もうそろそろ有効期限が切れますよ〜 というメールが届くたびに手動で行うのです。
最初は別になんとも思わなかったけど、さすがにもうめんどうくさいのと、今の時代決まりきっていることを手動で行うのはナンセンスすぎる。
という思考の末、自動化(cron)を決意した次第であります。
最初のつまずき
ひさびさに情報を漁ってみると、 更新には renew コマンドを使うのが正解のようです。
念のため、—dry-run と組み合わせて直接試してみます。
$ sudo /path/to/certbot/certbot-auto renew --dry-runこんなエラーでました
Problem binding to port 80: Could not bind to IPv4 or IPv6.. Skipping.
All renewal attempts failed. The following certs could not be renewedこれは、standalone プラグインが TCP Port 80 や TCP Port 443 をListenしているため。だそうです。
つまり、一旦apche(80)を止めないとだめ。
というか手動でやっていたとき httpd stop, httpd start をやってたやないの。
落ち着け。そしてありがとう、dry-run。
pre-hook, post-hook
手動作業どおりに更新処理の前と後で httpd をゴニョるにはどうすればいいのか調べると、
を使えばいいということがわかります。pre-hook で httpd stop、post-hook で httpd start をやればよさそうです。
$ sudo /path/to/certbot/certbot-auto renew --dry-run --pre-hook "sudo service httpd stop" --post-hook "sudo service httpd start"成功
Congratulations, all renewals succeeded. The following certs have been renewed:こんなメッセージが出れば成功です。
※ もちろんdry-runなので実際には更新されていません
さぁ、あとはこのコマンドをcronでの定期実行を設定すれば自動化が完成です。
cron
まずcronの設定を確認します。
起動確認
起動しているか確認します。
$ service crond status起動
起動していなければ起動します。
$ sudo service crond start設定
root になって作業します。
今回は、/etc/crontabに書くのではなく、/etc/cron.dにletsencrypt用として書くことにします。
# vi /etc/cron.d/letsencryptこの時点では木曜日だったので、とりあえず 金曜日(5) 午前4:00 に実行されるように指定しておきます。
※ 実際の運用では 土曜日(6) 午前4:00 とします
0 4 * * 5 root /your/path/certbot/certbot-auto renew --pre-hook "service httpd stop" --post-hook "service httpd start"wktkしながら次の日を待ちます。
次のつまずき
次の日、うんともすんともいっていない。。
ログ(/var/log/letsencrypt/letsencrypt.log)も確認したけど、起動すらされていない模様。これは悲しい。
こんなときはデバッグだ
こんな感じで、ログを仕込む && cronの実行時間をいじって確認してみます。
* * * * * root /your/path/certbot/certbot-auto renew --pre-hook "service httpd stop" --post-hook "service httpd start" >>/tmp/analog.log 2>>/tmp/analog-err.log参考: Let’s Encryptをcrontabで自動化した時に実行されない時の対処法
こんなんでました
# cat /tmp/analog-err.log
Unable to find pre-hook command service in the PATH.
(PATH is /usr/bin:/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin)わお、PATHが通っていない。。?だと??
実際の環境変数だとserviceは以下にPATHが通っています。
# which service
/sbin/serviceえ、なんで?どういうこと?むーわからん。
こんなときはデバッグだ!! というわけで、
cronジョブを作るのにいつものやり方でいいんですか?
を参考にcron実行時の環境変数を出力してみます。
* * * * * root env >/tmp/cron_env# cat /tmp/cron_env
SHELL=/bin/sh
USER=root
PATH=/usr/bin:/bin
PWD=/root
LANG=ja_JP.UTF-8
SHLVL=1
HOME=/root
LOGNAME=root
_=/usr/bin/envへぇ。/usr/bin, /bin にしか通っていないんやねぇ。。これは悲しい。
(この記事にもありますが)ちょっと調べてみると、
なんと、cronの各ジョブ実行時には,環境変数は最低限しかセットされていないとのことです。
なんと、cronの各ジョブ実行時には,環境変数は最低限しかセットされていないとのことです。
大事なことなので、2回書きました。
PATHを通す
では、上の 記事 を参考に/sbin を通してみます。
* * * * * root PATH="/sbin:$PATH" env >/tmp/cron_env確認。
# cat /tmp/cron_env
PATH=/sbin:/usr/bin:/bin
SHELL=/bin/sh
USER=root
PWD=/root
LANG=ja_JP.UTF-8
SHLVL=1
HOME=/root
LOGNAME=root
_=/usr/bin/env通った。
再度確認
再び実行時間をいじって実行してみます。
* * * * * root PATH="/sbin:$PATH" /your/path/certbot/certbot-auto renew --pre-hook "service httpd stop" --post-hook "service httpd start"結果
ログ(/var/log/letsencrypt/letsencrypt.log) にも
certbot.renewal:no renewal failuresこんな感じでエラーも出ていないようだし、実際のサイトも更新出来ている。
、、おし。できた。
最終設定
最後にきちんと設定(毎週土曜の午前4:00に実行される様に)して、完了です。
くぅ、無知は辛い。
/etc/cron.d/letsencrypt
0 4 * * 6 root PATH="/sbin:$PATH" /your/path/certbot/certbot-auto renew --pre-hook "service httpd stop" --post-hook "service httpd start"次の土曜と3ヶ月後にまた確認しよう。
追記
(確認するのを忘れていましたが、)きちんと更新されているようです。
おわりに
cronにはユーザの環境変数が引き継がれない ということを認識していなかったという無知が引き起こした無駄工数を体験出来ました。
しかし、こういう経験を経て人はまた強くなるのです。
参考にさせていただきました
- Let’s Encryptをcrontabで自動化した時に実行されない時の対処法
- cronジョブを作るのにいつものやり方でいいんですか?
- Let’sEncryptの取得&自動更新設定してみた(CentOS7.1&Apache2.4.6)
- Let’s Encryptを使ってSSL証明書を自動更新する(AWS/Amazon Linux/Apache)
- クーロン(cron)をさわってみるお
- 第25回 cron周りのベストプラクティス(1):Perl Hackers Hub|gihyo.jp … 技術評論社
- /etc/crontabと/etc/cron.d設定ファイルの書き方 | server-memo.net

