frankenphp 的 let’s encrypt 申请被限流,是因为 caddy 默认高频重试失败验证(每小时最多5次),触发 let’s encrypt 的 ratelimited 错误;应禁用自动重试、改用 staging 环境、清理 acme 缓存,并优先采用 dns-01 验证规避 http-01 限制。

FrankenPHP 的 Let’s Encrypt 申请被限流,是因为 Caddy 自动重试太猛
FrankenPHP 内置的 Caddy 默认会在证书失败时高频重试,而 Let’s Encrypt 对同一域名的失败验证有严格速率限制(比如每小时最多 5 次失败)。一旦你反复改配置、删证书、重启服务,很容易触发 urn:ietf:params:acme:error:rateLimited 或 too many failed authorizations 错误,导致后续申请直接被拒。
Caddyfile 里必须关掉自动重试 + 手动指定 staging 环境
别等报错后再处理,初始化阶段就该预防。Caddy 默认走生产 ACME 端点,但开发/测试时应该强制用 Let’s Encrypt 的 staging 环境(无速率限制,证书无效但能验证流程):
- 在 Caddyfile 全局块加
acme_ca https://acme-staging-v02.api.letsencrypt.org/directory - 同时禁用失败后自动重试:
acme_dns_timeout 10s和acme_http_port 8080(避免端口冲突导致验证失败) - 如果已触发限流,必须清空 Caddy 的 ACME 账户缓存:
rm -rf ~/.local/share/caddy/authorizations和rm -rf ~/.local/share/caddy/certificates
本地调试别走 HTTPS,用 HTTP + Host 头绕过证书环节
FrankenPHP 本身完全支持纯 HTTP 启动,且不影响 PHP 逻辑。很多团队卡在“不配 HTTPS 就不敢上线”,其实大可先用 HTTP 跑通 worker 模式、路由、静态文件服务,再单独切 HTTPS:
- 启动命令加
-http-port 8080,比如:frankenphp php-server -http-port 8080 -r public/ - 用
curl -H "Host: example.com" http://localhost:8080/模拟真实域名请求,Caddy 的路由规则照样生效 - 这样既跳过 ACME 全流程,又能验证所有业务逻辑和 FrankenPHP 的常驻内存行为
生产环境真要上 HTTPS,得换 DNS 验证方式
HTTP-01 验证依赖 80 端口可达,内网、NAT、防火墙场景下极易失败并反复重试。换成 DNS-01 可彻底规避:
- 在 Caddyfile 里启用 DNS 插件,例如 Cloudflare:
tls { dns cloudflare API_TOKEN } - DNS 验证是异步的,一次提交、后台轮询,失败也不会计入 Let’s Encrypt 的失败计数
- 注意:DNS 插件需额外安装(
caddy install tls.dns.cloudflare),且 API_TOKEN 必须有 Zone:Edit 权限
真正麻烦的不是证书本身,而是 Caddy 把“自动”做得太尽职——它不会区分你是刚建站还是修配置,只要域名解析没到位,就会一遍遍撞墙。手动接管验证方式,才是稳住生产环境的第一步。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











