宝塔面板自动续签失败主因是验证方式与配置不匹配:通配符证书必须用DNS-01,HTTP-01易因屏蔽.well-known、CDN拦截、强制HTTPS重定向或环境变量缺失而假性失败。

宝塔面板自动续签失败,八成不是 DNS 解析或 80 端口本身的问题,而是验证方式与配置不匹配导致的“假性失败”。 尤其当你用的是通配符证书(*.example.com)或网站无法直接暴露 80 端口时,HTTP-01 验证必然卡住——这不是你 DNS 没配好,也不是防火墙没开 80,是 Let’s Encrypt 根本不接受 HTTP 方式验证通配符域名。
HTTP-01 验证失败时,先别改 DNS 或开 80 端口
HTTP-01 要求 Let’s Encrypt 服务器能访问 http://example.com/.well-known/acme-challenge/xxx。常见现象包括:
- 浏览器能打开网站,但
curl -I http://example.com/.well-known/acme-challenge/test返回 404 或超时 - 宝塔日志里出现
Verification failed、Invalid response from http://... - 证书列表显示“已过期”,但手动点击【续签】按钮却成功了
这时真正的问题往往是:
- 网站根目录下
.well-known被 Nginx/Apache 规则屏蔽(比如加了location ~ /\. { deny all; }) - CDN(如 Cloudflare)开启“仅 HTTPS”或“Web 应用防火墙”,拦截了
.well-known路径 - 宝塔站点设置了“强制 HTTPS”,导致 HTTP-01 的明文请求被 301 重定向到 HTTPS,而 Let’s Encrypt 不跟随重定向
DNS-01 是通配符证书唯一可行的自动续签路径
如果你的证书含 *.example.com,acme.sh 必须走 DNS-01,否则会直接跳过或报错 dns-01 challenge is required。关键点不在 DNS 解析是否生效,而在 acme.sh 是否能写入 _acme-challenge.example.com TXT 记录:
- 必须在宝塔服务器上显式设置 DNS API 凭据,例如阿里云:
export ALIYUN_ACCESS_KEY_ID="xxx"export ALIYUN_ACCESS_KEY_SECRET="yyy" - 对应 DNS 提供商需授予足够权限(阿里云要
AliyunDNSFullAccess,Cloudflare 要Zone:Edit) - 验证是否生效,别看域名解析,直接查记录:
dig _acme-challenge.example.com txt +short,应返回一串随机值 - 宝塔内置的「批量续签」按钮默认不触发 DNS-01,必须弃用,改用命令行:
acme.sh --renew -d example.com -d *.example.com --dns dns_aliyun --force
80 端口开着也不代表 HTTP-01 能过
即使 netstat -tlnp | grep :80 显示 Nginx 正常监听,仍可能失败:
- 宝塔站点绑定了多个域名,但只有主域名配置了反向代理或伪静态,子域名未正确继承
.well-known路径 - 使用了 IPv6,而 Let’s Encrypt 验证服务器只走 IPv4,你的 DNS A 记录正常,但 AAAA 记录指向了一个不可达地址,导致部分验证请求失败
- 服务器启用了
iptables或ufw,放行了 80 端口,但限制了特定 User-Agent(acme.sh 默认 UA 是acme.sh/3.x),被误拦 - 宝塔「网站」→「设置」→「SSL」里勾选了「强制 HTTPS」,且「HTTP 跳转 HTTPS」开关为「是」,这会让所有 HTTP 请求 301,破坏 ACME 协议要求的明文响应
真正容易被忽略的,是宝塔计划任务执行时的环境隔离——它用的是自己的 Python 虚拟环境,但 crontab 默认不加载 ~/.bashrc 或环境变量。哪怕你本地 export 了 DNS 密钥,计划任务里依然拿不到。所以 DNS-01 续签必须把密钥写进脚本开头,或通过 acme.json 配置固化,不能依赖交互式终端的临时变量。


















