Discourse 的安装或重建可能会拒绝有效的 Let’s Encrypt 证书,并出现以下错误:
C=US, O=Let's Encrypt, CN=YR2
error 2 at 1 depth lookup: unable to get issuer certificate
error fullchain.cer: verification failed
我在 RSA 证书成功签发后立即复现了此问题。失败的检查会触发不必要的 --force 请求,这可能导致 HTTP 429 / rateLimited / “too many certificates”(证书过多)错误。在我的安装环境中,随后 ECDSA 证书的签发被阻止,HTTPS 未能启动。
对于受影响的证书链,每次重建或容器重启都可能触发 RSA 和 ECDSA 证书的不必要强制重新签发,即使这些证书仍然有效。成功的重新签发会消耗 Let’s Encrypt 的配额,因此反复重建或重启可能会迅速达到速率限制。
如果 HTTPS 继续使用已安装的证书正常工作,这种情况可能未被察觉。删除并使用相同主机名重新安装实例并不会重置该配额。如果新安装中缺少所需的证书,受速率限制的签发可能会阻止 HTTPS 启动。
修复方案
在 templates/web.letsencrypt.ssl.template.yml 文件中,cert_exists() 函数内部,请替换以下内容:
- openssl verify -CAfile <(openssl x509 -in ca.cer) fullchain.cer
+ openssl verify -untrusted ca.cer fullchain.cer
保持该函数的其余部分不变。修正后的模板必须包含在下一次容器重建中,以更新 /usr/local/bin/letsencrypt。
如果您已经受到速率限制,补丁不会重置配额。请应用此修复,并尊重 retry after(重试后)时间,然后再尝试进一步的签发。
确认证书链验证问题
在容器内受影响的证书目录中(/shared/letsencrypt/<hostname> 或 <hostname>_ecc),请比较以下命令的输出:
openssl verify -CAfile <(openssl x509 -in ca.cer) fullchain.cer
openssl verify -untrusted ca.cer fullchain.cer
在复现的案例中,第一个命令以错误 2 失败;第二个命令返回:
fullchain.cer: OK
原因与验证
openssl x509 -in ca.cer 仅从颁发者捆绑包中读取第一个证书。在观察到的 YR2 链中,它丢弃了到达 ISRG Root X1 所需的交叉签名 Root YR。
-untrusted ca.cer 提供了完整的颁发者捆绑包,同时将信任锚保留在系统存储中,从而保留了 2021 年修复 (#576) 的初衷。
我在容器内验证了实际的 RSA 和 ECDSA 证书链。使用补丁进行完全重建后,复用了两个现有证书:出现两条 Skip 消息,两个证书链均已安装,且 nginx -t 测试通过。