Nginx Proxy Manager 使用 Let’s Encrypt 获取 SSL 证书报错 Internal Error

最近在用 Nginx Proxy Manager 申请 Let’s Encrypt 证书时,我遇到了一个很烦人的问题:前端界面里看起来一切正常,但点击申请证书后,最后只得到一个模糊的 Internal Error

这种报错的难点在于:信息量太少。如果你不去容器里进一步排查,很难知道到底是 DNS、80 端口、邮箱、ACME 验证,还是 Nginx Proxy Manager 自己的状态出了问题。

我这次遇到的情况,最终定位到的是 certbot 的锁文件没有被正确清理。下面把现象、原因和解决方法整理一下。

现象

在 Nginx Proxy Manager 中为某个域名申请 Let’s Encrypt 证书时,界面弹出 Internal Error,证书无法签发。

image-20250912225248118

如果你也遇到了类似情况,建议不要一上来就反复重试。因为这类问题经常不是“再点一次就好”,而是某个内部状态已经卡住了。

先确认不是更常见的问题

在处理锁文件之前,可以先快速排除几类更常见的原因:

  1. 域名是否正确解析到了服务器
    确认 A 记录或 CNAME 没配错,而且已经生效。

  2. 80 / 443 端口是否对公网开放
    Let’s Encrypt 的 HTTP-01 验证通常依赖 80 端口,如果端口被拦截,申请就会失败。

  3. Nginx Proxy Manager 是否已经正常代理该域名
    至少要保证域名能正确打到当前这台机器。

  4. 是否频繁重复申请,触发了速率限制
    如果刚刚失败过很多次,也要考虑是不是碰到了 Let’s Encrypt 的限流。

如果这些都没问题,但报错仍然只是 Internal Error,就很可能需要进容器排查内部状态了。

问题原因

Nginx Proxy Manager 底层会调用 certbot 去申请和续签证书。certbot 在执行过程中会创建锁文件,避免多个证书任务并发执行时互相干扰。

正常情况下,任务结束后这些锁文件会被自动清理;但如果容器异常中断、任务执行失败,或者某次申请流程没有完整收尾,就可能留下残余的 .certbot.lock 文件。

这时新的证书申请任务会认为“已经有别的 certbot 任务在运行”,从而直接失败。但 Nginx Proxy Manager 前端并不会把这个底层细节明确展示出来,于是你最终看到的就只是一个笼统的 Internal Error

解决方案

进入 Nginx Proxy Manager 容器,删除遗留的 .certbot.lock 文件:

1
find / -type f -name ".certbot.lock" -exec rm {} \;

执行完成后,再回到 Nginx Proxy Manager 界面重新申请证书。

如何进入容器

如果你是通过 Docker 部署的,可以先查看容器名:

1
docker ps

然后进入对应容器:

1
docker exec -it <容器名> sh

如果镜像里带的是 bash,也可以使用:

1
docker exec -it <容器名> bash

进入后再执行上面的 find 命令。

这个做法为什么有效?

本质上,这不是“修复证书问题本身”,而是清理 certbot 的异常运行状态

也就是说,如果你真正的问题是 DNS 配置错误、端口未开放、Cloudflare 代理影响验证、或者域名根本没有指向当前服务器,那么删掉锁文件之后依然会失败。

所以更准确地说,这个方法适用于下面这种情况:

  • 之前证书申请流程被异常打断;
  • certbot 锁文件没有被正常清理;
  • 后续申请被残留锁文件卡住。

一点风险提示

直接删除锁文件之前,最好确认当前没有真正正在执行的证书申请或续签任务。

如果容器里确实还有 certbot 进程在运行,强行删除锁文件可能会让并发任务状态变得更混乱。虽然在个人部署环境里,这种情况不算常见,但还是建议先确认一下,再做清理。

比如可以先简单看一下相关进程:

1
ps aux | grep certbot

如果只是历史遗留锁文件,这个清理动作通常是安全的。

我的建议

以后再遇到 Nginx Proxy Manager 的证书签发问题,可以按下面这个顺序排查:

  1. 检查域名解析;
  2. 检查 80 / 443 端口;
  3. 检查是否被 Cloudflare 代理或其他 CDN 干扰验证;
  4. 查看容器日志;
  5. 检查并清理遗留的 .certbot.lock 文件。

这样比直接盲目重试更高效。

参考

这个方案参考自 GitHub issue:

https://github.com/NginxProxyManager/nginx-proxy-manager/issues/918