Caddy 自动 HTTPS 不支持通配符证书,因其内置 ACME 客户端仅支持 HTTP-01/TLS-ALPN-01,而 Let’s Encrypt 强制要求 DNS-01 验证;需手动签发证书并显式配置 tls 指令。

能配,但必须走 DNS-01 验证 —— Caddy 自动 HTTPS 机制对 *.example.com 失效。
为什么 Caddy 的自动 HTTPS 对通配符证书没用
Caddy 默认的 ACME 流程只支持 HTTP-01 和 TLS-ALPN-01 验证方式。而 Let’s Encrypt 对 *.example.com 强制要求 DNS-01 验证,这是协议层限制,不是配置问题。
- 你写
yourdomain.com或www.yourdomain.com,Caddy 能自动申请、续期 - 你写
*.yourdomain.com,Caddy 会静默跳过或报错No authenticator found,根本不会触发 ACME 请求 - 即使你在 Caddyfile 里显式写了
*.yourdomain.com,它也不会调用 DNS 插件 —— 因为 Caddy 内置 ACME 客户端不带任何 DNS 插件
怎么让 FrankenPHP 用上通配符证书
核心思路:绕过 Caddy 的自动流程,手动把证书文件放进去,再在 Caddyfile 中显式引用。
- 用
certbot或acme.sh配合 DNS 插件(如certbot-dns-cloudflare)签出*.yourdomain.com的 PEM 文件 - 确保证书文件路径固定,比如
/etc/letsencrypt/live/yourdomain.com/fullchain.pem和/etc/letsencrypt/live/yourdomain.com/privkey.pem - 在 Caddyfile 的站点块中禁用自动 HTTPS,并手动指定证书:
*.yourdomain.com { tls /etc/letsencrypt/live/yourdomain.com/fullchain.pem /etc/letsencrypt/live/yourdomain.com/privkey.pem php_server } - 注意:Caddy 不校验域名匹配逻辑是否“合理”,
*.yourdomain.com这个 host 名只是路由标识,真正起作用的是tls指令加载的证书
续期时 FrankenPHP 会自动 reload 吗
不会。FrankenPHP 本身不监听证书文件变化,Caddy 也不自动 reload —— 你得自己加一层触发逻辑。
立即学习“PHP免费学习笔记(深入)”;
- certbot 续期后默认不会通知 Caddy,需用
--deploy-hook调用frankenphp reload或发 SIGHUP - 推荐方案:用
systemd管理 FrankenPHP 进程,并在 certbot 的 renew hook 里执行systemctl reload frankenphp - 如果用 Docker,建议把证书卷挂载进容器,并在 entrypoint 中监听文件变更(如 inotifywait),或干脆每次续期后重建容器
- 别依赖
frankenphp run的热重载 —— 它只响应 Caddyfile 变更,不 watch 证书文件
最易被忽略的一点:DNS-01 是通配符证书的硬性门槛,没有例外;而 FrankenPHP 的角色只是“证书消费者”,它不参与验证过程,所有验证动作必须在外部完成并交付 PEM 文件。你配错的从来不是 FrankenPHP,而是误以为它能接管 ACME 全流程。



















