.env文件被直接下载是因为其位于caddy的web可达路径内,未做物理隔离;必须将其置于public/之外(如/app/.env),并确保root指向/public/、配合file_server hide指令及chmod 600权限控制。

为什么 .env 文件会被直接下载
FrankenPHP 本身不控制 Web 路径映射逻辑,它依赖 Caddy 的 file_server 或 reverse_proxy 行为。如果你的项目根目录(如 /app)被设为 Caddy 的 root 或 file_server 目录,而 .env 又放在该目录下,Caddy 就会把它当作静态文件直接返回 —— 不经过 PHP 解析,也不做任何拦截。
确保 .env 不在 Web 可达路径内
最根本的解决方式是让 Caddy 根本“看不见”这个文件。不是靠规则屏蔽,而是物理隔离:
-
.env必须放在项目 Web 根目录之外,例如:项目在/app,Web 入口是/app/public,那么.env应放在/app/.env(即与public/同级),而不是/app/public/.env - 检查 Caddy 配置中
root指向的是public/,不是/app;若用 Docker,确认挂载点没把整个/app暴露为静态服务 - 用
curl -I https://yoursite.tld/.env测试:应返回404或403,绝不能是200+text/plain
用 Caddy 的 file_server 隐式拒绝规则
即使物理位置正确,也建议加一层防御性配置。Caddy 的 file_server 支持 hide 指令,它不会返回文件,也不会报错,而是静默 404:
file_server {
root * /app/public
hide /.env /.env.local /composer.json /composer.lock
}
注意:hide 路径是相对于 root 的,所以写 /.env 表示“在 /app/public 下找”,这仅在你误把 .env 放进 public/ 时起作用;真正安全的做法仍是第一层物理隔离。
权限与运行用户也要匹配
FrankenPHP 进程若以非 Web 用户身份运行(比如 frankenphp 用户),而 .env 文件属主是 root:root 且权限为 644,虽然不会导致暴露,但可能引发加载失败 —— 这反而会让你误以为“没暴露”,实则变量根本没生效。务必同步检查:
-
ls -l /app/.env→ 应为-rw------- 1 www-data www-data(或你实际的 FrankenPHP 运行用户) -
chmod 600 /app/.env(644 是危险值,组/其他可读) - 不要依赖
open_basedir或deny from类 Apache 旧思路 —— Caddy 没有这类指令,且 FrankenPHP 不走 Apache 模块链
最容易被忽略的一点:Docker 容器里挂载 .env 时,如果用 bind mount 但宿主机文件权限是 644,容器内继承后仍可读;必须在宿主机先改权限,或用 docker run --user 显式指定 UID/GID 对齐。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











