筆者について
FreeBSDを通じてOSSにささかな貢献を。
- 日本xrdpユーザ会発起人
- xrdp developer
- FreeBSD developer
OSS活動をご支援いただける方を募集しています
2016-09-13
■ FreeBSD で letsencrypt.sh(dehydrated) を使って dns-01 方式で Let's Encrypt する
letsencrypt.sh は dehydrated に改名されました。このページ中のディレクトリ名やコマンド名に登場する letsencrypt.sh は dehydrated に適宜読み替えてください。
やること
FreeBSD で letsencrypt.sh を使って証明書を自動取得します。ドメイン認証には dns-01 を使います。DNS には Route 53 を使っているので、cli53 を使ってチャレンジ用のレコードを追加するところも自動化します。
使うもの
- FreeBSD
- Amazon Route 53
- letsencrypt.sh 0.3.0
- cli53 0.8.3
準備
最初に使うものをインストールします。
FreeBSD ports の dns/cli53 はこのエントリを書いている時点では、0.4.4と古く(最新は0.8.3)、また Python で書かれた版で Go 言語版ではありません。アップデートは投げていますが、まだコミットされていないので、拙作野良 ports からインストール。
$ git clone -b develop https://github.com/metalefty/freebsd-ports.git $ cd freebsd-ports/dns/cli53 # make install
letsencrypt.sh の方は ports からでも pkg からでもお好みで。今回は bash 版を使いました。
# pkg install letsencrypt.sh or # portmaster -d security/letsencrypt.sh or # make -C /usr/ports/securty/letsencrypt.sh install
letsencrypt.sh の設定
letsencrypt.sh の設定ファイルは /usr/local/etc/letsencrypt.sh/config です。設定を書き換えるのは2行だけ。デフォルトではサンプルしか存在しないため、サンプルをコピーしておきます。hook.sh も後で使うのでサンプルからコピーします。
# cd /usr/local/etc/letsencrypt.sh # cp -a config.sample config # cp -a hook.sh.sample hook.sh
最初はステージングサーバで実験するため、CAで始まる行のコメントアウトを解除し、以下のように書き換えます。これは後で元に戻します。
CA="https://acme-staging.api.letsencrypt.org/directory"
もうひとつは CONTACT_EMAIL で、これを自分のメールアドレスにします。
CONTACT_EMAIL=meta@example.com
hook.sh の書き換え
dns-01 というのは ssl.example.com の証明書を取得する際に、_acme-challenge.ssl.example.com という TXT レコードにチャレンジ文字列を作成して、ドメイン所有者の認証をする方式です。詳しくは説明してる他の記事を見てください。
簡単にいうと、Let's Encrypt の証明書発行手続き中に指定された DNS RR を登録しなければならないわけです。手続き中に DNS RR を登録するためのコマンドを、hook.sh 中に書くことで手続きを完全に自動化できます。
deploy_challenge の中で、チャレンジ文字列を含む TXT RR を登録し、clean_challenge の中で削除する、
こんな感じになりました。コメント部分は長くなるのでカットしてます。
書き換えたら忘れずに実行権をつけておきます。
AWS アクセスキーの設定
cli53 が Route 53 にアクセスするためのアクセスキーを設定します。今回は昨日の記事とは異なり、環境変数を使います。アクセスキーは例示用に予め無効化したものなのでご心配なく。
とりあえず、実行中のシェルに一時的に定義します。
$ export AWS_ACCESS_KEY_ID=AKIAINLJV4YYBZPML3CA $ export AWS_SECRET_ACCESS_KEY=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
証明書を取得してみる
以下のコマンドで ssl.vmeta.jp の証明書を取得してみます。sudo につけている -E オプションは環境変数に設定した AWS アクセスキーを root ユーザに引き継ぐためのものです。
うまくいくとこんな感じになります。
$ sudo -E letsencrypt.sh -c -d ssl.vmeta.jp --challenge dns-01 -k /usr/local/etc/letsencrypt.sh/hook.sh # INFO: Using main config file /usr/local/etc/letsencrypt.sh/config Processing ssl.vmeta.jp + Signing domains... + Generating private key... + Generating signing request... + Requesting challenge for ssl.vmeta.jp... Created record: '_acme-challenge.ssl.vmeta.jp. 10 IN TXT "8NG5kNiiJhSPC6abZrkqMTWWWiTp4flK-yfskyPj3U0"' Waiting for sync...................... Completed + Responding to challenge for ssl.vmeta.jp... 1 record sets deleted Waiting for sync..................... Completed + Challenge is valid! + Requesting certificate... + Checking certificate... + Done! + Creating fullchain.pem... + Done!
確認
証明書が取得できたら、/usr/local/etc/letsencrypt.sh/certs/$DOMAIN に書き出されるので、openssl で中身を見てみます。
# openssl x509 -text -in /usr/local/etc/letsencrypt.sh/certs/ssl.example.com/fullchain.pem | less
ここまでの作業で取得できたのはステージング用の証明書なので、/usr/local/etc/letsencrypt.sh の CA を元に戻して、本番用の証明書を取得します。
自動更新
letsencrypt.sh と cli53 は共に /usr/local/bin にインストールされているので、パスを通して cron で定期的に実行します。AWS のアクセスキーも crontab に書いておきます。
crontab はこんな感じになりました。毎月1日の1:47に実行します。証明書を更新したら、証明書を使っている Apache などのサーバで再読み込みする必要があると思いますが、それは今回触れません。
AWS_ACCESS_KEY_ID=AKIAINLJV4YYBZPML3CA AWS_SECRET_ACCESS_KEY=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 PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin 47 1 1 * * /usr/local/bin/letsencrypt.sh -c -d ssl.vmeta.jp --challenge dns-01 -k /usr/local/etc/letsencrypt.sh/hook.sh
periodic を使って実行する方法もあります。詳しくは
$ pkg info --pkg-message letsencrypt.sh
に手順が書いてあります。