Symfony在Caddy中需显式配置php_fastcgi并设split .php,root必须指向public目录且路径绝对;须用handle分流静态资源与PHP请求,提前放行/.well-known/acme-challenge/路径以保障HTTPS自动续期;生产环境应关闭默认HTTP跳转,避免影响CLI及探针调用。

Symfony应用在Caddy里必须显式处理PHP-FPM
Caddy不内置PHP解析,php_fastcgi 是唯一可靠方式——不像Nginx能靠fastcgi_pass + fastcgi_params 组合灵活控制,Caddy的php_fastcgi 指令会自动注入标准FastCGI变量,但默认不包含SCRIPT_FILENAME 的完整路径推导逻辑,容易导致“File not found”错误。
常见错误现象:Primary script unknown 或 404;原因常是root路径没对齐PHP-FPM工作目录或php_fastcgi未配split参数。
-
root必须指向 Symfony 的public/目录(不是项目根),且路径需绝对、无符号链接歧义 - 必须加
split .php,否则 Caddy 不会把/app_dev.php/some/route正确拆解为脚本路径+查询路径 - 若用 Unix socket(推荐),确保 Caddy 进程用户(如
caddy)有读写权限,例如unix//run/php/php8.2-fpm.sock - 开发环境可加
env APP_ENV=dev,但生产环境务必设为prod并禁用调试工具栏
示例片段:
myapp.local {
root * /var/www/myapp/public
php_fastcgi unix//run/php/php8.2-fpm.sock {
split .php
env APP_ENV prod
}
file_server
}
Caddy的重写规则不能照搬Nginx的try_files
Symfony依赖前端控制器(index.php)统一入口,Nginx常用 try_files $uri $uri/ /index.php?$query_string,但Caddy没有等价的单行指令。你得用 uri 匹配 + reverse_proxy 或 php_fastcgi 配合 handle 块显式分流。
容易踩的坑:漏掉静态资源(CSS/JS/img)直出,导致所有请求都打到PHP,性能骤降;或未排除 .php 文件以外的PHP执行路径,引发安全风险。
- 优先用
handle处理 PHP 路由,再用handle_path或正则匹配静态后缀,最后 fallback 到php_fastcgi - 静态资源建议加
encode gzip和header Cache-Control,避免每次请求都走PHP - 不要用
rewrite把所有请求重写到index.php—— 这会让图片、字体等也进PHP,徒增开销
正确结构示意:
myapp.local {
root * /var/www/myapp/public
<pre class="brush:php;toolbar:false;"># 静态文件直出(带压缩和缓存)
handle_path *.css,*.js,*.png,*.jpg,*.svg {
encode gzip
header Cache-Control "public, max-age=31536000, immutable"
file_server
}
# PHP 请求交给 FPM
handle *.php {
php_fastcgi unix//run/php/php8.2-fpm.sock {
split .php
}
}
# 兜底:其他请求也走 index.php(Symfony 标准行为)
handle {
php_fastcgi unix//run/php/php8.2-fpm.sock {
split .php
}
}}
HTTPS自动续期在Symfony里要绕过ACME验证路径
Caddy 默认用 HTTP-01 挑战向 Let’s Encrypt 申请证书,会拦截 /.well-known/acme-challenge/ 路径并返回验证文件。但 Symfony 的路由或安全配置(如 security.yaml 中的 access_control)可能把它当成普通请求拦掉,导致证书申请失败,日志里反复出现 HTTP 403 or 404 for ACME challenge。
这不是Caddy的问题,而是 Symfony 的中间件或防火墙规则太“尽职”。你得在 Caddy 配置里提前劫持该路径,跳过所有 PHP 处理。
CAD通信网关公共库(装修设计扩展版)。提供统一CAD COM封装接口,支持AutoCAD/天正双模式,包含装修专业图层体系、材料图块、房间边界检测、弧形吊顶COM接口。复用建筑施工图方案Skill0公共库。
- 必须在
php_fastcgi或handle块之前,用handle_path /.well-known/acme-challenge/*显式放行 - 该路径下只用
file_server,不要加任何encode、header或认证逻辑 - 如果用了自定义域名前缀(如
symfony.myapp.com),确保 DNS 解析已生效且 80 端口开放——Caddy 申请证书时必须能从公网访问到这个路径
补丁式配置节选:
symfony.myapp.com {
root * /var/www/myapp/public
<pre class="brush:php;toolbar:false;"># ACME 验证路径必须最先处理,且完全绕过 PHP
handle_path /.well-known/acme-challenge/* {
file_server
}
# 后续才是 Symfony 的正常路由逻辑...
handle *.php { ... }
handle { ... }}
生产环境必须关掉Caddy的自动HTTP跳转
默认情况下,Caddy 对每个 HTTPS 站点自动监听 80 端口并 308 跳转,这对纯 API 或 CLI 调用场景很危险:某些 Symfony 命令(如 bin/console cache:warmup 或健康检查探针)若依赖 http:// 协议发起内网请求,会被 308 重定向卡住,甚至触发无限重试。
更隐蔽的问题是:Docker 容器间通信、Kubernetes readiness probe、或 CI/CD 部署脚本中硬编码的 HTTP 地址,都会因这个默认跳转失效。
- 显式关闭 80 端口监听:在站点块开头加
listen :443,并删掉所有未声明端口的裸域名写法 - 若真需要 HTTP→HTTPS 跳转,改用
redir指令做条件跳转,例如只对浏览器 User-Agent 才跳,避免影响自动化工具 - 检查
APP_URL环境变量是否设为https://开头——Symfony 的生成 URL(如邮件链接、asset 版本号)依赖它,设错会导致混合内容警告
安全收紧示例:
prod.symfony.myapp.com {
listen :443
tls admin@myapp.com
<pre class="brush:php;toolbar:false;">root * /var/www/myapp/public
php_fastcgi unix//run/php/php8.2-fpm.sock { split .php }
# 只对人类浏览器跳转,机器流量直通
@browser {
header User-Agent "*Chrome/*" "*Firefox/*" "*Safari/*"
}
redir @browser https://{host}{uri} 308}
真正麻烦的从来不是配置几行 Caddyfile,而是 Symfony 的运行时行为(比如路由缓存、OPcache 预热、日志轮转)和 Caddy 的生命周期(reload 不等于重启 PHP-FPM)之间那些不声不响的错位。部署后务必用 curl -I http://localhost 和 curl -I https://localhost 分别测状态码,再跑一次 bin/console debug:router 确认所有 route 都能被识别——很多 404 其实是 PHP 层没加载对路由缓存,跟 Caddy 无关。










