let's encrypt で複数ホスト名対応な証明書を作る
タイトル通りですが、割と簡単に複数のホスト名に対応した証明書が取得できるので、やってみました。
今回は ansible playbook のおまけ付きです。
let's encrypt の困った問題
let's encrypt ではワイルドカード証明書が無いので、複数のホスト名を1台のサーバでホスティングできないため、ちょっと困っていました。
ググって調べてみたら、let's encrypt は SAN 対応の証明書だったら発行できる、と言うことだったので実際にやってみました。
その前に、SAN って何よ?
ワイルドカード証明書だと良く聞くと思うのですが、 SAN って何よ?と思う人も多いと思います。
SAN とは Subject Alternative Name の略称で、サブジェクトの別名です。
ん?サブジェクトってなに? サブジェクトは証明書に設定された Common Name です。
要は、 san01.tnamao.net を Common Name として証明書を作って、その時に別名としての san02.tnamao.net は SAN として登録される形になります。
SAN とワイルドカードの違い
SAN があったら、ワイルドカードいらなくない?要らない子じゃない?となりがちですが、何が違うのか?
ワイルドカードの場合は *.tnamao.net で取得したら、 abc.tnamao.net も def.tnamao.net も xyz.tnamao.net も利用可能です。
しかし、SAN の場合は abc.tnamao.net も def.tnamao.net も xyz.tnamao.net も証明書を発行する時に指定する必要があります。
ワイルドカードはサブドメインが増えても、同一の証明書で対応できますが、SAN の場合は必要になる別名が増えた段階で証明書の再発行が必要なります。
技術的な側面は置いといて、利用する上ではここが一番大きい差だと思います。
今回使うサーバ
最近は前払い方式のクラウドサーバ (VPS に近い) の Vultr を使ってます。
時間払いも選べるので、グローバル IP が欲しいときに、さっとサーバ立てて実験してサーバを破棄すれば経済的でおすすめです。
実験をだらだらやってるとお金が減ってくのも集中しなきゃ、という気になるので精神面からも良い感じです。
let's encrypt での SAN 対応証明書の作成
では、本題の let's encrypt での複数ホスト対応証明書の作り方です
certbot のインストール方法などは省略するので、過去のブログエントリを参照してください。
では、証明書を発行します。コマンドは次のようにします。
$ ./certbot-auto certonly \ --no-self-upgrade \ -n \ --webroot \ --agree-tos \ --email tnamao@yourdomain.com \ -w /var/www/letsencrypt_webroot/ \ -d abc.yourdomain.com \ -d xyz.yourdomain.com
こんな感じで、-d で指定するドメインを複数並べます。一番先に指定したドメインが Common Name として使用されるようです。
自分の場合は、san.tnamao.net と san2.tnamao.net の置き換えて、コマンドが無事に実行できたら、Web サーバの再読込を行って、ブラウザでアクセス
出来た\(^o^)/
証明書は san.tnamao.net だけど、サブジェクト代替名として san.tnamao.net と san2.tnamao.net が登録されています。 この状態であれば、 https://san.tnamao.net/ と https://san2.tnamao.net/ のどちらでアクセスしても正常な証明書としてブラウザが認識してくれます。
この方法は古いサーバを集約したい、なんて時に非常に便利だと思います。
以前に証明書発行済みのサブドメインを新しい証明書の SAN として組み込む
使い捨ての時代なのでドメインも使い捨てに… と言うわけにもいかず、一般に向けて何かを公開すると終息させるまでの面倒を見る必要も出てきます。
昔証明書を取って、https を使っちゃってるからサーバだけ残さないといけないんだよなぁ。お金かかってやだなぁ…
そんなときも SAN を設定した証明書を活用することでマイグレーションできます。
上で使った san.tnamao.net ですが、別の証明書の SAN として設定してみます。
$ ./certbot-auto certonly \ --no-self-upgrade \ -n \ --webroot \ --agree-tos \ --email tnamao@yourdomain.com \ -w /var/www/letsencrypt_webroot/ \ -d san3.tnamao.net \ -d san.tnamao.net
新しいサーバ上に環境を作って、上記のコマンドを流してみました。DNS は切り替え済みです。 今度は、san3.tnamao.net の代替名として san.tnamao.net を設定してみました。
nginx を再読込させて
できた\(^o^)/ 証明書の Common Name が san3.tnamao.net になって、代替名もさっきとは変わってますよね。
まとめ
let's encrypt でワイルドカード証明書は対応してないから、単一 IP アドレスのサーバでマルチドメインのホスティングは難しいかと思っていましたが、SAN を使うことで可能でした。
ワイルドカード証明書に比べると自由度は下がります。でも、ホスティングするドメインが決まっていれば有効な方法だと思いました。
おまけ (ansible playbook)
今回の実験するときに、何度か環境作るのが分かってたので、 ansible playbook を書きました。
Ubuntu 16.04 にしか対応してないけど、証明書の取得を簡単に試したい人はどうぞ。 Vultr と組み合わせる時は非常に楽ちんだと思うので、使ってみてください。