acme.sh 泛域名证书自动化实战:DNS 校验签发通配符证书,Nginx 自动续期一条龙
上回聊 Caddy 反向代理时我说过,它的自…
上回聊 Caddy 反向代理时我说过,它的自动 HTTPS 很香——装上就能拿证书,零配置。但 Caddy 用的是 HTTP-01 校验,有个硬伤:签不了泛域名证书。所谓泛域名,就是一张 *.vpnt.top 证书覆盖所有子域名,不用每个子域名单独签一张。想签泛域名,必须走 DNS-01 校验,也就是往 DNS 里加一条 TXT 记录,向 Let’s Encrypt 证明这个域名确实是你的。今天的主角 acme.sh,就是干这事最顺手的工具。
先回答一个老问题:证书到底为啥要折腾?现在浏览器对没有 HTTPS 的站点直接标”不安全”,自建服务一旦暴露到公网,没证书基本没法用。Let’s Encrypt 免费发证书,但有效期只有 90 天,靠手工续期不现实,必须自动化。acme.sh 是一个纯 shell 写的 ACME 客户端,不依赖 Python 环境,装完一条命令就能签证书,还能自动挂 cron 续期,到期前无缝续上,全程不用你操心。
第一步:安装
安装就一条命令,需要 curl:
curl https://get.acme.sh | sh -s email=you@example.com
装完它会自动帮你加一条 crontab 定时任务,每天凌晨检查证书是否要续期。重新加载一下 shell(source ~/.bashrc),acme.sh 就进 PATH 了。整个过程不改系统包,全部塞在 ~/.acme.sh/ 目录里,干净可控。
第二步:签发证书(两种方式)
acme.sh 支持两种主流校验方式,按场景选就行。
方式一:HTTP-01,适合站点已经跑在 80 端口。用 webroot 模式,它会在网站根目录写一个临时文件让 CA 来访问验证:
~/.acme.sh/acme.sh --issue -d vpnt.top -d www.vpnt.top --webroot /var/www/html
这种方式不用改 DNS,最简单,但签不了泛域名。
方式二:DNS-01,适合签泛域名,或者 80 端口根本不对外(纯内网服务)。它需要调用域名服务商的 API 自动加 TXT 记录。以 Cloudflare 为例,先到后台拿到 API Token,然后:
export CF_Token="你的 API Token"
export CF_Account_ID="你的账户 ID"
~/.acme.sh/acme.sh --issue --dns dns_cf -d vpnt.top -d '*.vpnt.top'
acme.sh 内置了 100 多家 DNS 服务商的 API,阿里云、腾讯云、DNSPod、Cloudflare 都在列,用 --dns dns_cf 这样的名字指定即可。签完它还会自动把 TXT 记录删掉,不留垃圾。
第三步:部署到 Nginx
签完的证书默认躺在 ~/.acme.sh/ 里,但那是 acme.sh 内部用的目录,别直接让 Nginx 引用。正确做法是用 --install-cert 部署到指定位置:
~/.acme.sh/acme.sh --install-cert -d vpnt.top \
--key-file /etc/nginx/ssl/vpnt.top.key \
--fullchain-file /etc/nginx/ssl/vpnt.top.cer \
--reloadcmd "systemctl reload nginx"
这里的 --reloadcmd 是精髓:每次证书续期成功后,acme.sh 会自动执行这条命令让 Nginx 重载新证书,真正做到无人值守。Nginx 配置里这样引用即可:
server {
listen 443 ssl;
server_name vpnt.top www.vpnt.top;
ssl_certificate /etc/nginx/ssl/vpnt.top.cer;
ssl_certificate_key /etc/nginx/ssl/vpnt.top.key;
}
第四步:自动续期
续期其实不用你管,安装时已经偷偷塞了 cron。想确认的话:
crontab -l | grep acme
能看到类似这样的一行:
0 0 * * * "/home/you/.acme.sh"/acme.sh --cron --home "/home/you/.acme.sh" > /dev/null
每天凌晨跑一次 --cron,acme.sh 会检查所有证书,快到期(默认 60 天内)就自动续,续完自动执行你设的 --reloadcmd。
几个我踩过的坑
- DNS 生效有延迟:acme.sh 默认等 120 秒,域名解析慢就加
--dnssleep 600多等会儿,否则容易验证失败。 - Key 别泄露:
export的环境变量别明文写进脚本提交到仓库,建议放受权限保护的独立文件里source进来。 - 别手贱删
~/.acme.sh/里的东西:证书续期后会重新生成,你部署出去的副本才是真正该用的。
一句话总结:证书这事,装一次 acme.sh,后面基本就忘了它。泛域名、自动续期、自动重载,三件事一条龙搞定。家里跑了一堆自建服务的朋友,赶紧把那些还在裸奔的 HTTP 站点都换上 HTTPS 吧。
