证书申请失败需先查看终端最后一行stderr报错;caddy自动申请let's encrypt证书须同时满足dns解析正确、80端口开放、域名未被限速;内网环境必须手动提供证书并关闭caddy_auto_https。

证书申请失败时先看终端最后一行报错
FrankenPHP 启动后自动 HTTPS 失败,错误不会写进日志文件,全在终端 stderr 实时输出。关键线索就在最后那行,比如:failed to obtain certificate: acme: error: 400 :: POST :: https://acme-v02.api.letsencrypt.org/acme/new-order :: urn:ietf:params:acme:error:rejectedIdentifier :: Error creating new order :: Cannot issue for "example.com": Domain name does not resolve to this server——这说明 DNS 解析未指向当前服务器,不是证书配置问题。
Caddy 自动申请失败的三大硬性前提
Caddy(也就是 FrankenPHP)要成功申请 Let's Encrypt 证书,必须同时满足:
- DNS A/AAAA 记录已生效并解析到运行 FrankenPHP 的公网 IP(
dig example.com +short必须返回正确 IP) - 80 端口对外可访问(Caddy 需用 HTTP-01 挑战,防火墙、云厂商安全组、NAT 映射都得放行)
- 域名未被 Let's Encrypt 封禁(如 7 天内对同一域名失败超 5 次,会触发 rate limit,需换域名或等重置)
本地开发或内网环境不能依赖自动 HTTPS
如果你在 localhost、192.168.x.x 或公司内网部署,Let's Encrypt 根本不签发证书——它只认公网可验证域名。此时必须手动提供证书,且严格满足 FrankenPHP 的加载规则:
- 证书文件必须命名为
example.com.crt(含完整链,顺序:域名证书 + 中间 CA) - 私钥必须命名为
example.com.key,权限设为600 - 两个文件放进
./caddy_data/certificates/目录(Docker 默认挂载路径) - 必须关闭自动 HTTPS:
CADDY_AUTO_HTTPS=off(Docker Compose 中 environment 下设置)
证书加载成功与否,只信两处输出
别靠浏览器能不能打开来判断证书是否生效。启动后立刻确认:
- 终端日志里有没有
Using provided certificate或Loaded TLS certificate字样——没有就代表 FrankenPHP 根本没读到你放的文件 - 进容器执行:
ls -l /data/certificates/,确认文件存在、权限是-rw-------、属主能被运行用户(如www-data)读取
自动 HTTPS 失败本身不致命,但很多人误以为“只要能跑起来就行”,结果上线后前端请求因证书问题被浏览器拦截,而错误日志里又没明确提示——这才是最麻烦的盲点。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











