TraefikでDNSチャレンジな証明書(ワイルドカード証明書)を発行/更新しよう!
始めに
レジストラで独自ドメインを取得してサーバーを公開するとき、SSL証明書を発行したり更新したりすると思います。
今まではCertbotでSSL証明書の発行/更新をして、TraefikでSSL証明書の管理をしていましたが、Traefikの公式ドキュメントを眺めていると、TraefikだけでSSL証明書の発行/更新を行えることに気付いたので、やってみました。
複数のサービスのリバースプロキシとしてTraefikを使用していて、SSL証明書は1枚にまとめたい、という方の参考になれば嬉しいです。
Let's Encrypt!
・レジストラで独自ドメインを取得する方法
・DNSサービスを設定する方法
については記述していません。
また、TraefikをDocker Composeで動作させることを前提としています。
1. Traefikのコンテナを作成する
1.1. compose.ymlを作成する
Traefikを起動するために、compose.ymlを作成します。
services:
traefik:
image: traefik:3.1.0
container_name: rp-traefik
restart: always
networks:
- reverse-proxy
ports:
- 80:80
- 443:443
- 8080:8080
labels:
- traefik.enable=true
- traefik.http.routers.traefik-reverse-proxy.tls=true
- traefik.http.routers.traefik-reverse-proxy.tls.certresolver=mydnsjp
- traefik.http.routers.traefik-reverse-proxy.tls.domains[0].main=*.<domain-name>
environment:
- MYDNSJP_MASTER_ID=<mydnsjp-master-id>
- MYDNSJP_PASSWORD=<mydnsjp-password>
volumes:
- ./traefik/volume/etc/traefik:/etc/traefik
- ${XDG_RUNTIME_DIR}/docker.sock:/var/run/docker.sock:ro
- /usr/share/zoneinfo/Asia/Tokyo:/etc/localtime:ro
networks:
reverse-proxy:
name: reverse-proxy
コンテナやネットワークの名称、ポート番号などは適宜読み替えてください。
要点は下記の通りです。
・certresolverにmydnsjpを指定する
自分はDNSサービスとしてMyDNSを使用しています。
後述するtraefik.ymlで設定を記述します。
・domains[0].mainに*.<domain-name>を指定する
SSL証明書のCNに指定するドメインの名称です。
自分はSSL証明書について十分な知識を持っていなかったため、下記のWebサイトを参考にしました。
Traefikでワイルドカード証明書を発行する方法を検索すると、domains[0].main=<domain-name>とCNを指定して、別途domains[0].sans=*.<domain-name>とSANsを指定するWebサイトが多く見られますが、正確にはそれはマルチドメインワイルドカード証明書に該当するのでは、と思いCNにのみワイルドカードなドメインを指定しました。
自分の環境では、どちらの方法でもワイルドカード証明書として使用できました。
また、環境変数は使用するDNSサービスによって異なりますので、公式ドキュメントを参考に適宜読み替えてください。
1.2. traefik.ymlを作成する
Traefikの設定ファイルを作成します。
api:
insecure: true
dashboard: true
providers:
docker:
exposedByDefault: false
network: reverse-proxy
entryPoints:
web:
address: :80
http:
redirections:
entryPoint:
to: websecure
scheme: https
websecure:
address: :443
certificatesResolvers:
mydnsjp:
acme:
dnsChallenge:
provider: mydnsjp
email: <email>
storage: /etc/traefik/certificate/wildcard/acme.json
# caServer: https://acme-staging-v02.api.letsencrypt.org/directory
ネットワークの名称、ポート番号、ストレージのパスなどは適宜読み替えてください。
要点は下記の通りです。
・certificatesResolversにmydnsjpを作成する
compose.ymlで指定したcertresolverのことです。
・providerにmydnsjpを指定する
自分はDNSサービスとしてMyDNSを使用しています。
その他のDNSサービスを使用する場合は、公式ドキュメントを参考にしてください。
また、動作が確認できるまではcaServerにステージングのAPIを指定することをおすすめします。
1.3. Traefikのコンテナを起動する
ここまでできたら、Traefikのコンテナを起動します。
起動してしばらく待った後、下記のようなacme.jsonが作成されたら成功です!
{
"mydnsjp": {
"Account": {
"Email": "<email>",
"Registration": {
"body": {
"status": "valid",
"contact": [
"mailto:<email>"
]
},
"uri": "https://acme-v02.api.letsencrypt.org/acme/acct/xxx"
},
"PrivateKey": "<private-key>",
"KeyType": "4096"
},
"Certificates": [
{
"domain": {
"main": "*.<domain-name>"
},
"certificate": "<certificate>",
"key": "<key>",
"Store": "default"
}
]
}
}
2. 任意のサービスのコンテナを作成する
Traefikで発行したSSL証明書を使用する任意のサービスのコンテナを作成します。
PhotoPrismの例は下記の通りです。
<省略>
labels:
- traefik.enable=true
- traefik.http.routers.photoprism.tls=true
- traefik.http.routers.photoprism.tls.certresolver=mydnsjp
- traefik.http.routers.photoprism.rule=Host(`photoprism.<domain-name>`)
- traefik.http.routers.photoprism.entrypoints=websecure
- traefik.http.routers.photoprism.service=photoprism
- traefik.http.services.photoprism.loadbalancer.server.port=2342
<省略>
サービスで使用したいドメインの名称と、Webサーバーのポート番号を指定することで、Traefikで発行したSSL証明書を使用できます。
サービスが増えても同じ要領でlabelsを指定すれば良く、SSL証明書は1枚で済むので便利ですね。
終わりに
目論見通りTraefikでSSL証明書を発行できました。
公式ドキュメントを読む限りでは、SSL証明書の更新も自動で実行してくれそうなので、3か月後どうなるか、楽しみです。
記事の内容が間違っていたり、質問がある場合は、気軽にコメントしていただけるとありがたいです🙇🏻♂️
Discussion