今日も微速転進

ここではないどこかへ

Let's encrypt の証明書の更新( Cloudflare/DNS-01 )


スポンサーリンク

CDNとしてCloudflareを利用している環境で、Let's Encrypt の証明書を更新した際のメモ。

証明書を取得した際にはCloudflareは利用していなかった。

前提

新規の取得ではなく、既存証明書の更新作業。Cloudflare のCDNを一時的に無効化するのはなんか負けた気がするので認証方法を変更する。

通常の認証方式ではなく、DNSのtxtレコードを利用するDNS-01方式を使う。

Let's Encrypt のサーバーに証明書の発行を依頼すると、一時的に有効なトークン文字列が送られてくるので、これをDNSのtxtレコードに記載するという方式。 Webサーバーがなくても利用できるし、今回のようなCDN環境やNAT利用時にも証明書の取得・更新が可能。

DNSの設定変更は面倒であるが、Cloudflare の場合はプラグインがややこしい作業はやってくれる。このプラグインとLet's Encrypt のコマンドさえインストールすればいい。

セットアップ

Ubuntu 16.04 標準のletsencryptパッケージを諦めて、新しくcertbot*1をインストールする。

選択肢は下記の4つ。

  1. certbot の公式パッケージリポジトリ
  2. github から入手する
  3. 自動インストールスクリプト*2
  4. pipコマンド経由でインストール

Let's Encrypt の公式リポジトリのパッケージは微妙に古いうえにCloudFlare用のプラグインパッケージを含まない。本来であればOSのお作法に従うべきなので 1. が最有力だが肝心の Cloudflare用のプラグインを別途入れる必要がある。管理の手間が増えるのは好ましくない。

妥協案として4. のpipコマンド経由でインストールする。

$ sudo apt install python-pip
$ pip install certbot-dns-cloudflare

インストール先がpipコマンドを実行したユーザーのホームディレクトリ配下である点に注意する。

Credential ファイルの作成

API キーを記載したクレデンシャル(Credential : 信任状)ファイルを作成する。

$ vi /etc/letscrypt/cloudflare.ini 

書式は以下のとおり。

dns_cloudflare_email = cloudflare@example.com
dns_cloudflare_api_key = 0123456789abcdef0123456789abcdef01234567

Cloudflare に登録したメールアドレスと、Global API Key を記載する。APIキーはCloudflareにログインして右上のメールアドレスをクリックするとメニューが表示されるのでそこから”My Profile"を選択すると表示される。

誰でも読み取れるのは好ましくないので、パーミッションを変更しておく。

$ sudo chmod 600 /etc/letscrypt/cloudflare.ini 

パーミッションが不適切だと下記の警告メッセージが表示される。

Unsafe permissions on credentials configuration file: /etc/letsencrypt/cloudflare.ini

参考:certbot/init.py at master · certbot/certbot · GitHub

テスト

$ sudo /path/to/certbot renew --dry-run --dns-cloudflare --dns-cloudflare-credentials /etc/letsencrypt/cloudflare.ini

/path/to/の箇所は環境に応じて変更。

テストに成功すると以下のようなメッセージが表示される。

-------------------------------------------------------------------------------
** DRY RUN: simulating 'certbot renew' close to cert expiry
**          (The test certificates below have not been saved.)

Congratulations, all renewals succeeded. The following certs have been renewed:
  /etc/letsencrypt/live/www.example.com/fullchain.pem (success)
** DRY RUN: simulating 'certbot renew' close to cert expiry
**          (The test certificates above have not been saved.)
-------------------------------------------------------------------------------

更新

--dry-runオプションを外して実行。

$ sudo /path/to/certbot renew  --dns-cloudflare --dns-cloudflare-credentials /etc/let
sencrypt/cloudflare.ini

成功時のメッセージは以下のようになる*3

-------------------------------------------------------------------------------
new certificate deployed without reload, fullchain is
/etc/letsencrypt/live/www.example.com/fullchain.pem
-------------------------------------------------------------------------------

-------------------------------------------------------------------------------

Congratulations, all renewals succeeded. The following certs have been renewed:
  /etc/letsencrypt/live/www.example.com/fullchain.pem (success)
-------------------------------------------------------------------------------

あとはwebブラウザに設定をリロードさせておく。

$ sudo systemctl reload nginx

次回以降の更新

一度証明書の更新に成功すると設定ファイルも自動的に更新されるのでややこしいオプション指定は不要になる。

$ sudo /path/to/certbot renew

cronによる自動更新

証明書の有効期限は90日。一ヶ月前から更新できるはず。

月に一回のチェックでは心もとないので週に一回実行する。更新可能期間に入ると残り日数にかかわらず更新する。

/etc/cron.weekly/に、letsencryptというファイルを作成する。

$ sudo vim  /etc/cron.weekly/letsencrypt

更新スクリプトの例。

#! /bin/bash
if [ ! -d /tmp/letsencrypt-auto ] ; then
    mkdir -p /tmp/letsencrypt-auto
fi
cd /tmp/letsencrypt-auto

/usr/local/bin/certbot renew && systemctl reload nginx

chmod +xで実行権限を付与しておく。

更新されなかったときのメッセージ

ドメイン名は実際のものとは別。あまり役に立つかはわかりませんが一応。Ubuntu側の設定を変更していなければ管理者宛にメールで結果を送信されるはず。

Saving debug log to /var/log/letsencrypt/letsencrypt.log

-------------------------------------------------------------------------------
Processing /etc/letsencrypt/renewal/www.example.com.conf
-------------------------------------------------------------------------------
Cert not yet due for renewal

-------------------------------------------------------------------------------

The following certs are not due for renewal yet:
  /etc/letsencrypt/live/www.example.com/fullchain.pem (skipped)
No renewals were attempted.
-------------------------------------------------------------------------------

更新に成功したとき

更新に成功したときの出力。

Saving debug log to /var/log/letsencrypt/letsencrypt.log

-------------------------------------------------------------------------------
Processing /etc/letsencrypt/renewal/www.example.com.conf
-------------------------------------------------------------------------------
Cert is due for renewal, auto-renewing...
Plugins selected: Authenticator dns-cloudflare, Installer None
Starting new HTTPS connection (1): acme-v01.api.letsencrypt.org
Renewing an existing certificate
Performing the following challenges:
dns-01 challenge for www.example.com
dns-01 challenge for support.example.com
dns-01 challenge for text.example.com
Starting new HTTPS connection (1): api.cloudflare.com
Starting new HTTPS connection (1): api.cloudflare.com
Starting new HTTPS connection (1): api.cloudflare.com
Waiting 10 seconds for DNS changes to propagate
Waiting for verification...
Cleaning up challenges
Starting new HTTPS connection (1): api.cloudflare.com
Starting new HTTPS connection (1): api.cloudflare.com
Starting new HTTPS connection (1): api.cloudflare.com

-------------------------------------------------------------------------------
new certificate deployed without reload, fullchain is
/etc/letsencrypt/live/www.example.com/fullchain.pem
-------------------------------------------------------------------------------

-------------------------------------------------------------------------------

Congratulations, all renewals succeeded. The following certs have been renewed:
  /etc/letsencrypt/live/www.example.com/fullchain.pem (success)
-------------------------------------------------------------------------------

まとめ

初回からDNS-01 方式で証明書を取得しておくと面倒がなくていいと思う。

*1:コマンドの名称が変わっているが基本的な使い方は変わらない

*2: Certbot

*3:ドメイン名は実際のものとは別

広告