← 返回笔记列表

遇到的问题

域名刚拿到、备案还在流程里的时候,我想先把 HTTPS 配起来。 按最常规的方式跑 acme.sh 的 HTTP-01 验证,结果一直卡在校验失败: 验证方要访问 /.well-known/acme-challenge/ 下的文件, 但这个路径在备案完成前被上游拦掉了,本机能访问、外网访问不到。

排查思路很简单——先确认到底是我配错了,还是根本进不来。 在服务器本地 curl 自己的挑战文件是 200,换外网访问就不对, 那就不是 Nginx 配置的问题,是链路的问题。

解决办法:换 DNS-01

DNS-01 验证不需要 80 端口,只要能在域名解析里加一条 TXT 记录就行。 我的域名在 DNSPod,用 API Token 让 acme.sh 自动加记录、自动清理,全程不用手动点后台。

# 提供 DNS 服务商凭据(示意,实际值放环境变量里,不要写进脚本)
export DP_Id="<your-id>"
export DP_Key="<your-key>"

# 用 DNS-01 申请证书
acme.sh --issue --dns dns_dp -d example.com -d www.example.com

这里有个小坑:凭据千万不要硬编码到仓库里的脚本。 我的做法是放在服务器上一个受限权限的文件里,脚本运行时再读。

别忘了续期后的 reload

证书拿到只是第一步。90 天后自动续期时,如果 Nginx 不重新加载, 浏览器看到的还是旧证书。所以要给 acme.sh 挂一个 reload 钩子:

acme.sh --install-cert -d example.com \
  --key-file       /etc/nginx/ssl/example.com.key \
  --fullchain-file /etc/nginx/ssl/example.com.crt \
  --reloadcmd      "sudo /usr/local/sbin/deploy-cert.sh"

钩子脚本只做两件事:把证书拷到 Nginx 读取的位置,然后 nginx -t && nginx -s reload。 nginx -t 这一步不能省——配置有问题时宁可不 reload,也别把线上服务弄挂。

小结