ACME续签失败主因是80端口被占或防火墙拦截,非证书过期;需检查端口占用、放行安全组、切换DNS验证、重装Let's Encrypt插件、修正Nginx证书路径并重载配置、调整计划任务执行用户为root。

宝塔续签报错:ACME 调用失败,提示 “Failed to bind 80 port”
本质是 ACME 协议在验证域名所有权时,需要临时监听 80 端口(HTTP-01 方式),如果被占用或无法访问,就会直接失败。不是证书过期问题,而是验证通道不通。
常见错误现象:ACME server returned an error: urn:ietf:params:acme:error:connection,或者日志里明确出现 bind: address already in use。
- 先用
netstat -tuln | grep :80看谁占着80—— 宝塔自身 Nginx 通常不占(它走的是反向代理),但可能有其他进程如python -m http.server 80、nginx(非宝塔安装的)、apache2或 Docker 容器映射了80 - 检查是否开了防火墙:宝塔面板的「安全」页面里,
80和443必须放行;云服务器(阿里云/腾讯云)控制台的安全组也得同步放开 - 如果用的是 DNS-01 验证(比如你手动配置了 DNS API),就不用开
80,但在宝塔里必须主动切换:续签前点证书右侧「设置」→ 把验证方式从「HTTP 验证」改成「DNS 验证」,并填好对应 DNS 提供商的 API 密钥
宝塔 SSL 续签卡在 “正在验证域名” 且无日志输出
大概率是 ACME 客户端(acme.sh)被宝塔调用时权限或路径异常,尤其出现在升级宝塔或手动改过 Nginx 配置后。
关键判断点:进终端执行 /www/server/panel/acme.sh --version,如果报 command not found 或版本极老(如 v2.7.x),说明 acme.sh 损坏或未正确部署。
- 不要手动下载 acme.sh 覆盖 —— 宝塔依赖定制版,路径和 hook 脚本都绑死了
- 正确做法:在宝塔「软件商店」→ 找到「Let's Encrypt」→ 点「设置」→ 底部点「重装 Let's Encrypt 插件」
- 重装后,再进网站 → SSL → 「续签」按钮旁会出现小刷新图标,点它触发一次强制重试,比等自动任务更可靠
- 如果仍卡住,看
/www/wwwlogs/ssl.log,里面每一步都有时间戳,重点找含http-01或dns-01的那行失败记录
用 DNS 验证续签成功,但浏览器仍提示证书过期
不是续签没生效,而是旧证书还在 Nginx 配置里挂着,新证书没 reload 进去。
典型场景:你手动改过网站的 Nginx 配置文件(比如加了自定义 ssl_certificate 路径),导致宝塔后续续签时只更新了证书文件,却没更新配置里的引用路径。
- 检查网站配置文件:
/www/server/panel/vhost/nginx/你的域名.conf,确认ssl_certificate和ssl_certificate_key指向的是宝塔管理的路径,例如:/www/wwwroot/你的域名/fullchain.pem和/www/wwwroot/你的域名/privkey.pem - 别写死成
/etc/letsencrypt/live/...这类 acme.sh 原生路径,宝塔不认 - 改完配置后,必须点宝塔面板右上角「重载配置」,或执行
nginx -s reload,光重启 Nginx 服务不一定生效 - 顺便检查证书文件权限:
ls -l /www/wwwroot/你的域名/*.pem,确保是root:root且权限为600,否则 Nginx 启动会静默失败
自动续签失败但手动点「续签」能成功
说明定时任务本身出了问题,不是证书逻辑问题。宝塔的自动续签靠的是系统级 cron + 面板内部的钩子脚本,两者断一个就失效。
最常被忽略的是:宝塔面板运行用户是 www,但系统 cron 默认以 root 身份跑,而 acme.sh 初始化时绑定的是当前用户环境(比如你当初是用 root 装的 acme.sh,但面板调用时是 www 用户)。
- 进宝塔「计划任务」→ 找到名为「Let’s Encrypt 自动续签」的任务 → 点编辑 → 「执行用户」选
root(不是 www) - 同时检查该任务的命令是否还是默认的:
/www/server/panel/pyenv/bin/python /www/server/panel/class/acme_v2.py --renew=your-domain.com—— 如果域名变了,这里不会自动更新,得手动改 - 另一个坑:某些低配机器(512MB 内存)在凌晨自动续签时因内存不足,
acme.shfork 失败,日志里只有OOM killed process。可临时加个 swap:dd if=/dev/zero of=/swap bs=1M count=512 && mkswap /swap && swapon /swap


















