Raspberry Pi 2 web server 更新(certbot renew)

Let’s EncryptのSSL証明書更新がエラーを吐いて更新できなくなってしまいました。debian 11 bullseyeのリリースも間もなくとあって安定版のRasPiOS(May 7th 2021)で再構築してみました。

Timeout during connect

これまではgitのcertbotスクリプトで更新していたのですがなにか仕様変更があるとやはりエラーを吐いて更新に失敗します。それでも修正をしながらなんとか更新できていたのですが今回はどうもうまくいきません。

Timeout during connect (likely firewall problem)

検索するとよくあるようですがパスもfirewallも特に問題ない。

Raspberry Pi2 web server nginx

Raspberry Pi OS Lite May 7th 2021
nginx   1.21.1-1~buster(コンパイル)
php7.3   7.3.29-1~deb10u1
mariadb  1:10.3.29-0+deb10u1
各設定ファイルはそのまま移行

certbot

現在のRasPiOSではパッケージとしてcertbotがあります。python3-certbot-nginxをインストールすることでwebrootで実行可

# apt install certbot python3-certbot-nginx

基本の設定が出来たところで–dry-run 実行。ssh clientはpi zero 母艦のPi4とはvnc接続

# certbot renew –dry-run

特に問題ないようです。続いて本番

# certbot renew

無事更新できました。gitのcertbotスクリプトに比べて断然早い、またLet’s Encryptの仕様変更に対してもcertbotのupgradeで対応することが期待できます。

python3-certbot-nginx

python3-certbot-nginxを導入することでcertbot.timer(自動更新)がデーモンとして起動します。

$ systemctl status certbot.timer


/etc/cron.d/certbotには以下の記載があります。毎日0時と12時にcertbot -q renewを実行しています
/var/log/syslogではcronの実行を確認できますがletsencrypt.logには記載されないようです。

0 */12 * * * root test -x /usr/bin/certbot -a \! -d /run/systemd/system && perl -e 'sleep int(rand(43200))' && certbot -q renew

certbot certificates

今までは週に1回cronを回してrenewを実行、結果をメールで確認していたのですがcertbot.timerによる自動更新が正常かどうか注意して見ようと思います。
もし更新エラーがあれば早めに把握していれば対策も立てやすいと思います。
有効期限の確認方法はいろいろありますがcertbot certificatesコマンドがシンプル

xterm + ssh

サーバー側で実行するためssh公開鍵認証(空パスワード)を設定、毎回コマンドを打つのも面倒なのでxdotoolに代打ちをお願いします
メニューに登録実行
~bin/app_menu/letsencrypt/certificates.sh

#!/bin/sh
xterm -g 80x25+1124+25 -e ssh xyz81 &
sleep 1
xdotool mousemove 1500 100
xdotool type --delay 70 'sudo certbot certificates'
xdotool key Return

python3(tkinter)
上記で実行した結果を母艦のPi4に取り込めればもっと見やすく加工できます。
サーバー側でスクリプトを1日1回適当な時間に実行(cronを回す)

~/bin/certbot_certificates.sh (chmod 755)
#!/bin/sh
rm ~/*certbot
sudo certbot certificates > $(date +%Y%m%d_%H%M%S).certbot
$ crontab -e
35 06 * * * ~/bin/certbot_certificates.sh

user hogeのホームディレクトリに日付時間.certbotを作成
20210719_063001.certbot
母艦のPi4はこのファイルをプログラム起動時にscpして表示(起動は5秒位かかる)

ラベル欄に読み込んだファイル名表示 daysボタンで終了
通常は1日1回確認でOKですが敢えて最新の情報が必要な時はRETRYボタンを実行
xtermが起動してスクリプトを実行、サーバーのcertbot_certificates.shを実行 pythonプログラムを再起動


プログラムのボタン欄で赤ボタンにするdaysを変更(当サイトは31に設定)30日を切って更新エラーがあると緊迫感がより一層高まるものです。

参考 certificates.py

xdotool実行中はxtermからフォーカスが外れると打ち込みに失敗するのでそっと待ちます(起動まで約10秒)
sleepは環境によって調整

~/bin/app_menu/letsencrypt/certificates_save.sh
#!/bin/sh
xterm -g 80x12+1124+205 &
xdotool key Return
sleep 0.4
xdotool mousemove 1300 300
xdotool type --delay 70 'ssh xyz81'
xdotool key Return
sleep 1
xdotool type --delay 70 '~/bin/certbot_certificates.sh'
xdotool key Return
sleep 5
xdotool type --delay 70 'exit'
xdotool key Return
sleep 0.4
xdotool type --delay 70 '~/bin/app_menu/letsencrypt/certificates.py &'
xdotool key Return
sleep 5
xdotool mousemove 1300 300
xdotool click 1
xdotool key Return
xdotool type --delay 70 'exit'
xdotool key Return

次回の更新は9月14日 6:28(JST)以降からrenew実行可、certbot.timer12時に自動実行される予定です。気を付けて置きたいと思います。

追記 7月23日
更新開始(renew)の期日が気になっていたのでdateコマンドで確認してみました。

$ date -d '2021-10-12 21:28:23 UTC 30 day ago'
2021年  9月 13日 月曜日 06:28:23 JST


多分9月 13日が正解と思います。
終了時messageboxに表示するようにしました。

# quit
def quit_click():
    # renew days
    with open(save_dir+r_file, 'r') as f:
        certificates = f.read()
        d = certificates.find('Date')
        d = (certificates[d+6:d+25])
        cert_renew = ("date -d '" + d + " UTC 30 days ago'")
        cert_renew = (subprocess.Popen(cert_renew, stdout=subprocess.PIPE, shell=True).communicate()[0]).decode('utf-8')
        cert_renew = cert_renew.strip()
    # renew days
    if days_renew >= str(30):
        root.option_add('*Dialog.msg.font', 'Helvetica 11')
        messagebox.showinfo('certbot certificates', 'certbot renew \n\n' + cert_renew)
    root.quit()