Edited at

環境を汚さずにDocker+certbotで手っ取り早くサーバ証明書を取得するメモ

最近は lego を使う方がトラブルが少なくてオススメ。特に dns-01 が使える環境だとWEBサーバも不要になるのでとても便利です。そしてlegoもDockerから利用すればインストールの手間がなく便利です。

↓は今や古い記事です。当時のアレコレの参考文献までに。


元記事

certbot は普通にインストールしようとすると色んなパッケージとかをローカル環境に入れ始めるので気持ち悪い。

証明書さえ手に入れば良いのでプログラムは Docker 内で実行させれば十分。

ドメイン確認に http を使うが /.well-known/acme-challenge/* のパスが通ればよいだけなのでそこだけ Proxy する形が外側の設定がクリーンに保てて楽ちんでよい。


手順

certbot の実行前にホストのWEBサーバに設定しておく。


httpd.conf

ProxyPass /.well-known/acme-challenge/ http://localhost:10080/.well-known/acme-challenge/


で、以下のスクリプトを作って


certonly.sh

#!/bin/bash

PORT=${PORT:-10080}
email=${1:-}
domains=("${@:1}")

if (( $# < 2 )); then
echo "Usage: $0 email domain [domains...]"
exit 1
fi

if [[ -n $email ]]; then
email_opts+=( --email "$email" )
else
email_opts+=( --register-unsafely-without-email )
fi

domains_opts=()
for domain in ${domains[@]}; do
domains_opts+=(-d "$domain" )
done

docker run \
--rm \
-p "$PORT:80" \
-v /etc/letsencrypt:/etc/letsencrypt \
-v /var/log/letsencrypt:/var/log/letsencrypt \
deliverous/certbot certonly \
--standalone \
--non-interactive \
--agree-tos \
--renew-by-default \
--preferred-challenges http \
"${email_opts[@]}" \
"${domains_opts[@]}"


↓こんな感じに実行する。

bash certonly.sh '' exmaple.jp secure.example.jp

上手く行けば /etc/letsencrypt/live/example.jp/*.pem に証明書と秘密鍵一式が出来るので、httpsのVirtualHostに以下のように証明書を読み込む設定を追記すればOK


httpd.conf

SSLEngine on

SSLCertificateKeyFile /etc/letsencrypt/live/example.jp/privkey.pem
SSLCertificateFile /etc/letsencrypt/live/example.jp/fullchain.pem

証明書の期限は3ヶ月なのでこれを簡単に更新できるよう以下のスクリプトを作って


renew.sh

#!/bin/bash

PORT=${PORT:-10080}
docker run \
--rm \
-p "$PORT:80" \
-v /etc/letsencrypt:/etc/letsencrypt \
-v /var/log/letsencrypt:/var/log/letsencrypt \
deliverous/certbot renew

crontab に以下のような感じに設定しておく。

# 毎週火曜日の午後に証明書を更新する

0 15 * * 2 bash /path/to/renew.sh >/dev/null

これで取得から更新までいい感じになるはず。


certbot メモ



  • --email は無しでも良い。その場合は --register-unsafely-without-email を付ける。メール登録しておくとメンテナンス通知や期限切れリマインダーメール等が受けられる。


  • --domains に指定するドメインリストの最初のFQDNが証明書のCN値と保存されるファイルのパス名に使われる。


  • --non-interactive とか --agree-tos とかは指定しないとインタラクティブにCUIのダイアログや確認が出てきて自動化出来ないので付けておく。

  • 同じドメインの証明書を一定期間で取得できる回数に制限があるので5回くらい試していると翌週にならないと再試験ができなくなったりするので気をつける。


  • certbot renew/etc/letsencrypt/renewal/*.conf から既存の証明書を探して前回取得時と同じやり方で証明書の更新をしてくれる。


    • 特に引数は不要で、non-interactive に動いてくれる。

    • renew はデフォルトでは30日以上期限が残ってる証明書の更新をスキップしてくれるので実際は何回実行してもかまわない。

    • 上述のcron設定は単に休みの日に自動更新されて障害になると嫌なので対応しやすい平日午後あたりにまとめてやっているだけである。