本着不污染服务器环境的想法,想把acme.sh搬到docker中进行证书自动更新。而我的服务器统一由docker compose管理容器,因此需要将acme.sh用docker compose管理。
acme.sh官方教程中写出了如何使用docker-compose.yaml启动。写出的配置如下
1 | |
这样做会开启了一个daemon,随后可以docker exec acme.sh --issue -d example.com --standalone来签发证书。
但是这是使用standalone模式签发的,想要签发泛域名证书的话不能这么做,因此配置中有几项就没必要了,以下是我修改了的配置:
1 | |
可以看到我进行了以下修改:
network_mode项:默认的HTTP-01验证模式下,通过让容器使用host的网络栈来临时接受验证请求,但是泛域名签发采用DNS-01方式,不使用这种方法,因此删除即可。- 添加
CF_*的环境变量:我使用cloudflare作为DNS服务商。 - 将
restart修改为unless-stopped:经过检查容器内会启动crond和acme.sh daemon,且在新创建容器时似乎会创建定时任务。因此长期运行容器理论上(因启动时间较短而无法测试)可以实现自动签发,因此我将其修改为unless-stopped,确保服务器因意外停机后仍然可以启动。
对于新版acme.sh,由于默认采用zerossl,如果仍然需要let’s encrypt签发证书的可以通过执行docker compose exec acme.sh --issue --dns dns_cf -d "*.example.com" --server letsencrypt来签发。但是我不打算这么做,因为根据https://www.zhihu.com/question/646766797/answer/1970528780280893897得知,let’s encrypt证书不再配备ocsp uri导致苹果手机设备访问时加载时间过长,倒不如一步到位尝试zerossl。
先去https://zerossl.com注册一下账户,或者不注册可能也能继续进行?我没有尝试。
通过执行
1 | |
来申请zerossl的证书。如果不出意外的话,过几分钟就生成证书了。注意register-account这行命令是必备的。
我提一嘴我的证书的用途。我的证书用于内网网站的https功能,因为涉及了几个PWA应用(比如思源笔记web端),网站使用不被信任的证书没法被创建为PWA应用,因此不使用合法的证书很不方便。
原则上使用DNS-01方式签发的的服务器可以在无法被外网访问的情况下也签发成功,就像不启用network_mode: host配置的容器一样。
接下来,签发完的证书会被定期检查更新,并上传到私有的存储服务器上,以允许被多个服务器每日拉取证书检查更新并使用。
由于证书其实有多个来源,我目前有好几个地方需要签发泛域名证书,比如自动部署Caddy的TLS通配符域名证书到阿里云CDN,因此上传到单独的存储服务器上非常方便统一管理和下载。