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 吧。

类似文章

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注