acme.sh 配 DNS 校验签证书,续签交给 cron

2026-10-02

我的两个子域 jz.jhfyl.xyz / mc.jhfyl.xyz 共用一张多域名证书,装在 nginx 上 (/etc/nginx/ssl/jhfyl.crt 和 .key,SAN 含两个域名),由 acme.sh v3.1.5 签发和续签, 配置目录 /root/.acme.sh/。服务器是我自己的 120.26.91.35,上面跑几个自用小服务。

一、先确认"到底是谁在管证书"

这台机器上 certbot 2.9.0 也装着,但 certbot certificates 是空的 —— 别被它误导。判断真实管理者靠两条:

crontab -l | grep acme      # 有 acme.sh 的 --cron 任务
ls /root/.acme.sh/          # 每个域名一个目录,里面有签好的证书

二、签:DNS 校验 + 明确写死 CA 和密钥类型

acme.sh --issue -d mc.jhfyl.xyz -d jz.jhfyl.xyz --dns dns_ali \
         --keylength 2048 --server letsencrypt

三、装:让续签之后自动 reload

acme.sh --install-cert -d mc.jhfyl.xyz \
         --key-file /etc/nginx/ssl/jhfyl.key \
         --fullchain-file /etc/nginx/ssl/jhfyl.crt \
         --reloadcmd "systemctl reload nginx"

关键是 --install-cert 会把 reloadcmd 记住:以后每次自动续签都会自己把新证书拷到 nginx 的路径并 reload,不需要人工。我一开始是手动 cp 再 reload,那等于给未来埋一个"证书过期没人知道"的雷。

四、把续签交给 cron,再加两条自查

26 3,9,15,21 * * *  ~/.acme.sh/acme.sh --cron --home ~/.acme.sh > /dev/null

每 6 小时问一次"到期了没",没到期它什么都不做。平时自查这两条够用:

openssl x509 -in /etc/nginx/ssl/jhfyl.crt -noout -dates   # notBefore / notAfter
acme.sh --list                                            # 管着哪几张、上次何时续

五、补记(2026-10-06):老设备打不开,根因是链上的根

那天出现"手机 Chrome 能进、平板和别的浏览器全进不去"。查下来不是 TLS 拦截,而是证书:原先签的是 ECC,链走到 ISRG Root X2(2020 年的新根),老设备证书库里没有 X2 就直接判证书无效, 手机是新系统所以认。改签 RSA + LE 之后链变成 leaf ← YR2 ← Root YR ← ISRG Root X1 (2015 年的根,普及度最好),fullchain 从 3 段补到 4 段,旧 ECC 那份留了备份 /etc/nginx/ssl/jhfyl.crt.ecc-bak-20261006。

echo | openssl s_client -connect 120.26.91.35:443 -servername mc.jhfyl.xyz \
     -showcerts | grep -o 'CN=[^,/]*' | sort -u     # 看最后一节是不是 ISRG Root X1

选 CA 不只看"是不是免费",要看根证书的年龄和普及度:ISRG Root X1 比 X2(2020)、Sectigo R46(2021)都老。遇到"有的设备能进、有的不能", 第一反应就该查链的根。

六、两件没做成的事,记下来免得再试

一是想用 IP 当应急入口(https://120.26.91.35:8443/),证书是签给域名的,浏览器必然提示 不受信;要消掉得给 IP 单签一张,acme.sh v3.1.5 不支持 IP 证书,得升版本或换 lego。 二是 80 端口那段 ACME 目录我照旧留着 (location ^~ /.well-known/acme-challenge/ { root /var/www/html; }),虽然我用 DNS 校验用不上,但哪天换回 HTTP 校验或换 CA,80 上得有这条路,别把它一起 301 跳走了。

返回首页