Freenom ドメイン・Let's Encrypt 証明書の有効期限を確認・通知する仕組みを作った

最近、いくつかのサイトで Freenom で独自ドメインを取ったり、Let's Encrypt で証明書を取って HTTPS 化したりしている。

Freenom のドメインは12ヶ月ごとに更新手続きを行わないといけないのだが、Freenom API は通常ユーザは使えないらしく、手作業が必要になるので、この気付きを得たい。

上3つの Always Free IaaS で動かしているサイトは、cron で certbot の更新処理を定義して毎月動かしているが、ちゃんと証明書が更新できているか一応チェックしておきたいなーと思った。

そんなワケで、ドメインと証明書の有効期限をチェックして Slack 通知する仕組みを作り込むことにする。

証明書の更新状況を JSON ファイルに出力する

まずはサイトごとに、証明書の更新状況を JSON ファイルに出力する仕組みを作る。

cron で毎月証明書を更新している処理の最後に、シェルスクリプトを実行する設定を入れる。

$ crontab -l
00 03 01 * * /root/certbot/certbot-auto renew && systemctl restart nginx && /root/certbot/update-status.sh

スクリプトの内容は以下のとおり。

#!/bin/bash

cert_renew_date="$(date '+%Y-%m-%d')"
cert_expiry_date="$(/root/certbot/certbot-auto certificates 2>&1 | grep 'Expiry Date' | sed 's/^.*Date\: //' | sed 's/ .*$//')"

cat <<EOL > /var/www/html/status.json
{
  "global_ip"               : "140.238.56.203",
  "domain_name"             : "neos21-oci.cf",
  "domain_registration_date": "2020-08-22",
  "domain_expiry_date"      : "2021-08-22",
  "cert_renew_date"         : "${cert_renew_date}",
  "cert_expiry_date"        : "${cert_expiry_date}"
}
EOL

echo 'Update Status Finished'

Global IP とドメイン名はベタ書き。

ドメインの取得日、有効期限日もベタ書き。Freenom API が使えないので仕方ない。1年に1回手動で更新した時に、ココの内容を手で書き換える運用とする。

証明書の更新日は処理した日付、有効期限日は certbot から泥臭く取得している。

このような JSON を組み立てて、/var/www/html/ 配下に書き込んでいる。すなわち、

という URL で、ココで組み立てた JSON ファイルにアクセスできるようにするワケだ。

このようなスクリプトと cron 定義を、IaaS の3サイトでそれぞれ設定しておく。

XREA に関しては証明書更新が要らないので、次のようなベタ書きの JSON ファイルだけをただ置いておく。

{
  "global_ip"               : "neo.s21.xrea.com",
  "domain_name"             : "neos21.tk",
  "domain_registration_date": "2020-08-22",
  "domain_expiry_date"      : "2021-08-22",
  "cert_renew_date"         : "-",
  "cert_expiry_date"        : "-"
}

status.json を収集しヘルスチェックするスクリプトを組む

4つのサイトのルート直下に status.json が配備され、ドメインの有効期限や証明書の有効期限が確認できるようになった。

続いてはこれらを収集してヘルスチェックし、よき感じにステータス状況を組み上げるスクリプトを書く。

ということで、ステータスチェック用の GitHub リポジトリを作った。

実処理は以下の2つ。

実処理を持つ Node.js スクリプトは、愚直にコーディングした。外部パッケージをインストールしたくなかったので、お手製感が強い。

ドメインの期限切れまで30日を切った時、証明書の期限切れまで10日を切った時は「ヘルス異常」と見なして、Slack 通知するようにした。また、そもそも status.json がそのサイトから取得できなかった場合はサイトが落ちているものと見なし、通知するようにした。

GitHub リポジトリ直下の README.md を毎日書き換えるようなスクリプトになったので、

毎日このページさえ開けば、各サイトが落ちていないか、期限切れが迫っていないかを一覧で把握できる。

とりまコレでよきよき。