泛域名证书(*.example.com)必须用DNS-01验证,因HTTP-01仅能验证单个精确域名,无法证明对所有子域名的控制权;Let’s Encrypt强制要求通配符证书通过DNS方式验证所有权。

泛域名证书(*.example.com)必须用 DNS 验证,HTTP 模式完全无效;acme.sh 能自动调用 DNS API 完成验证和续签,但前提是 DNS 服务商支持、API 凭据配置正确、权限足够。
为什么泛域名证书不能走 HTTP 验证
Let’s Encrypt 和 ZeroSSL 的 ACME 协议明确规定:通配符域名(*.example.com)只允许通过 dns-01 挑战方式验证所有权。HTTP 验证(http-01)只能覆盖精确域名(如 example.com 或 www.example.com),无法证明你控制所有子域名。
- 执行
acme.sh --issue -d example.com -d *.example.com --webroot /var/www会失败,报错类似:Cannot issue for "*.example.com": Domain is not valid for http-01 challenge - 即使命令看似跑通,最终也只会为
example.com颁发证书,*.example.com被忽略 - 除非你有公网 80/443 端口且能部署 standalone 服务,否则别尝试绕过 DNS 验证
DNS API 配置最容易出错的三个地方
acme.sh 支持 50+ 家 DNS 提供商,但腾讯云(DNSPod)、阿里云、Cloudflare 最常用。配置失败往往卡在这三步:
-
环境变量名写错:腾讯云要用
DP_Id和DP_Key(不是Tencent_SecretId),阿里云是Ali_Key+Ali_Secret,Cloudflare 是CF_Key+CF_Email—— 必须严格匹配dnsapi/目录下对应脚本里定义的变量名 -
权限不足:比如腾讯云子账号没授予
dnspod:CreateRecord和dnspod:DeleteRecord,会导致申请时卡在 “Adding TXT record” 后无响应 -
没 source 环境变量:写完
~/.bashrc后忘了运行source ~/.bashrc,或者用 root 安装 acme.sh 却在普通用户 shell 下执行命令,导致变量不可见
申请 + 自动部署到 Nginx 的完整命令链
以腾讯云 DNSPod 为例,假设域名为 example.com,目标 Nginx 配置路径为 /etc/nginx/conf.d/example.conf:
acme.sh --issue --dns dns_dp -d example.com -d *.example.com acme.sh --install-cert -d example.com \ --key-file /etc/nginx/ssl/example.key \ --fullchain-file /etc/nginx/ssl/example.pem \ --reloadcmd "nginx -s reload"
- 第一行触发 DNS 记录自动添加、等待验证、删除记录,成功后证书存入
~/.acme.sh/example.com/ - 第二行把证书拷贝到指定位置,并注册续签后自动重载 Nginx —— 这步不能省,否则下次续签不会更新线上文件
-
--reloadcmd中不要用systemctl restart nginx,它可能阻塞 cronjob;nginx -s reload是轻量、原子、无中断的
续签是否真能全自动?关键看这三点
acme.sh 默认每天凌晨 0:00 执行 --cron,但它只负责“更新证书文件”,不保证“生效”。真正全自动需满足:
- 证书必须用
--install-cert安装过,且--reloadcmd有效(可手动执行测试) - Nginx 配置中引用的路径必须和
--fullchain-file/--key-file一致,不能硬编码~/.acme.sh/下的路径 - 确保 crontab 没被系统级限制(如 CentOS 的
/etc/cron.deny屏蔽了 root);可用crontab -l查看 acme.sh 是否已写入定时任务
最常被忽略的是:证书安装后,Nginx 的 ssl_certificate 和 ssl_certificate_key 指令必须指向 --install-cert 指定的绝对路径,而不是 ~/.acme.sh/ 下的原始文件 —— 后者每次续签后内容会变,但软链接或路径引用不会自动更新。











