【发布时间】:2018-11-07 14:19:10
【问题描述】:
是否可以在 Traefik 中使用现有的 LetsEncrypt 证书(.pem 格式)?
我已设置 Traefik/Docker 以生成 acme.json - 我可以为一组域导入现有证书吗?
【问题讨论】:
标签: lets-encrypt traefik
是否可以在 Traefik 中使用现有的 LetsEncrypt 证书(.pem 格式)?
我已设置 Traefik/Docker 以生成 acme.json - 我可以为一组域导入现有证书吗?
【问题讨论】:
标签: lets-encrypt traefik
尽管可能有人想知道你为什么真的想要/需要这个,并且任何人都会建议你不要这样做,因为 traefik 很好地处理了自动重新挑战,这就是 acme.json 的样子:
{
"Account": {
"Email": "acme@example.com",
"Registration": {
"body": {
"status": "valid",
"contact": [
"mailto:acme@example.com"
]
},
"uri": "https://acme-v02.api.letsencrypt.org/acme/acct/12345678"
},
"PrivateKey": "ABCD...EFG="
},
"Certificates": [
{
"Domain": {
"Main": "example.com",
"SANs": null
},
"Certificate": "ABC...DEF=",
"Key": "ABC...DEF"
},
{
"Domain": {
"Main": "anotherexample.com",
"SANs": null
},
"Certificate": "ABC...DEF==",
"Key": "ABC...DEF=="
}
],
"HTTPChallenges": {}
}
现在由您来编写导入脚本或模板解析器来遍历您的证书/密钥并将内容放入括号中,或者只生成您自己的该格式的 json 文件。
请注意,它的格式与经典 pem 样式略有不同(即没有换行符)。
【讨论】:
最终我找到了正确的解决方案——不使用 Traefik 的 ACME 集成,而是简单地挂载一个包含 certbot 在手动模式下颁发的证书的网络卷 (EFS)。
为什么这是我选择的方法?因为我在 两个 服务器(蓝色和绿色)上安装了持有证书的 NFS 卷。这些服务器是 Web 服务器的实时和登台服务器。在任何时候,一个都将处于“实时”状态,另一个可以运行候选版本或以其他方式处于“热备用”角色。
因此,最好分离关注点并让第三台服务器作为专用的“证书管理器”运行。这台 t2.nano 服务器基本上不会被触动,它只负责每周运行一次 certbot,将证书写入一个 NFS 挂载,由两个 Web 服务器共享(以只读模式)。
通过这种方式,Traefik 在蓝色和绿色服务器上运行,以处理代理 Web 流量的主要问题,并简单地指向 certbot 颁发的证书文件。对于那些发现此页面并可以从相同解决方案中受益的人,以下是我的 traefik.toml 文件中的相关摘录:
defaultEntryPoints = ["https","http"]
[docker]
watch = true
exposedbydefault = false
swarmMode = true
[entryPoints]
[entryPoints.http]
address = ":80"
[entryPoints.http.redirect]
entryPoint = "https"
[entryPoints.https]
address = ":443"
[entryPoints.https.tls]
[[entryPoints.https.tls.certificates]]
certFile = "/cert.pem"
keyFile = "/privkey.pem"
这是我的 Docker swarm 堆栈文件中的相关部分:
version: '3.2'
volumes:
composer:
networks:
traefik:
external: true
services:
proxy:
image: traefik:latest
command: --docker --web --docker.swarmmode --logLevel=DEBUG
ports:
- "80:80"
- "443:443"
- "8080:8080"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ./traefik.toml:/traefik.toml
- "./certs/live/example.com/fullchain.pem:/cert.pem"
- "./certs/live/example.com/privkey.pem:/privkey.pem"
networks:
- traefik
最后是 cron 在专用证书服务器上每周运行一次的命令,配置为使用 ACME v2 进行通配符证书和 Route 53 集成以实现挑战自动化:
sudo docker run -it --rm --name certbot \
-v `pwd`/certs:/etc/letsencrypt \
-v `pwd`/lib:/var/lib/letsencrypt \
-v `pwd`/log:/var/log/letsencrypt \
--env-file ./env \
certbot/dns-route53 \
certonly --dns-route53 \
--server https://acme-v02.api.letsencrypt.org/directory \
-d example.com \
-d example.net \
-d *.example.com \
-d *.example.net \
--non-interactive \
-m me@example.org \
--agree-tos
文件夹certs是三台服务器共享的NFS卷。
【讨论】:
我只想补充一点,我在需要使用 HAProxy 的同时找到了另一种方法:
acl acme path_beg -i /.well-known/acme-challenge/
use_backend acme if acme
【讨论】:
完成sgohl回复:
重要提示:确保私钥长度为 4096 位。 2048 位将不工作,并且 traefik 将尝试向 Letsencrypt 请求新证书。
/etc/letsencrypt/live
├── example.com
│ ├── cert.pem -> ../../archive/example.com/cert6.pem
│ ├── chain.pem -> ../../archive/example.com/chain6.pem
│ ├── fullchain.pem -> ../../archive/example.com/fullchain6.pem
│ ├── privkey.pem -> ../../archive/example.com/privkey6.pem
│ └── README
openssl rsa -text -in privkey.pem | grep bit
预期结果类似于:
writing RSA key
RSA Private-Key: (4096 bit, 2 primes)
3.1。证书
_IN=/etc/letsencrypt/live/example.com/fullchain.pem
_OUT=~/traefik_certificate
cat $_IN | base64 | tr '\n' ' ' | sed --expression='s/\ //g' > $_OUT
3.2。私钥
_IN=/etc/letsencrypt/live/example.com/privkey.pem
_OUT=~/traefik_key
cat $_IN | base64 | tr '\n' ' ' | sed --expression='s/\ //g' > $_OUT
...
"Certificates": [
{
"domain": {
"main": "example.com"
},
"certificate": "CONTENT_OF_traefik_certificate",
"key": "CONTENT_OF_certificate",
"Store": "default"
},
...
acme.json 文件中的正确位置(在“证书”JSON 键下方):vim /path/to/acme.json
无需重启 traefik 容器即可选择新证书。
【讨论】: