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

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

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

前提

  • すでにSSL証明書を取得済み
  • Nginx
  • Cloudflare
  • Ubuntu 16.04 LTS

新規の取得ではなく、既存証明書の更新作業。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

まとめ

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

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

*2: Certbot

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