«前の日記(2016-09-12) 最新 次の日記(2016-09-14)» 編集

meta's blog - The Power To Serve

筆者について

FreeBSDを通じてOSSにささかな貢献を。

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 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

に手順が書いてあります。