symfony secrets 的核心是“加密存储 + 环境解密”,即用 app_secret 加密密钥后存入 config/secrets/ 目录,部署时仅暴露 app_secret 一把钥匙,其他密钥可安全提交 git;初始化、设置和读取密钥均须显式指定 --env=prod,且密钥名不能含点号或斜杠,引用时必须用 %env(resolve:key)% 语法,全程依赖 app_secret 一致性。

Symfony secrets 的核心是“加密存储 + 环境解密”,不是把密钥藏进文件,而是用 APP_SECRET 加密后存进 config/secrets/ 目录,部署时只暴露 APP_SECRET 这一把钥匙——其他密钥可随代码一起提交 Git,安全又省事。
初始化 secrets 目录必须用 APP_ENV=prod
运行 php bin/console secrets:set APP_SECRET 前,必须确保当前环境是 prod。否则命令会默认写入 dev 子目录,而生产环境启动时根本不会读那里。
- CLI 下执行前先设环境:
APP_ENV=prod php bin/console secrets:set APP_SECRET - Web 服务器(如 Nginx/Apache)也得提前设置
APP_ENV=prod,否则secrets:decrypt-to-local等命令会找不到目标环境目录 - 如果误初始化在
dev,删掉config/secrets/dev/并清缓存:php bin/console cache:clear --env=prod
设置密钥时别漏掉 --env=prod 参数
往生产环境加新密钥(比如数据库密码、API 秘钥),必须显式指定 --env=prod,否则它会写进 dev 目录,上线后读不到。
- 正确:
php bin/console secrets:set DATABASE_PASSWORD --env=prod - 错误:
php bin/console secrets:set DATABASE_PASSWORD(默认写dev) - 验证是否写对:
ls config/secrets/prod/应看到类似0123456789abcdef.s3的加密文件 - 密钥名不能含点号或斜杠,
DATABASE_PASSWORD可以,db.password会报错
配置里引用密钥必须用 %env(resolve:KEY)% 语法
直接写 %env(DATABASE_PASSWORD)% 是无效的——它只是字符串替换;要用 resolve 才能触发解密流程。
- Doctrine 配置示例:
doctrine:dbal:url: 'mysql://user:%env(resolve:DATABASE_PASSWORD)%@host/db' -
resolve还支持默认值和嵌套,比如%env(resolve:MAILER_DSN:-'smtp://null')% - 如果解密失败(比如
APP_SECRET不匹配),应用启动会直接报错:Invalid encrypted secret "DATABASE_PASSWORD",而不是静默忽略 - 开发时想绕过 secrets 用 .env?可以,但得关掉自动加载:在
config/bootstrap.php里注释掉Dotenv::createUnsafeImmutable(...)->loadEnv(...)
最常被忽略的一点:secrets 机制完全依赖 APP_SECRET 的一致性。它既用于加密新密钥,也用于解密已有密钥。如果你在不同环境用了不同 APP_SECRET 值,或者部署时覆盖错了系统级环境变量,所有密钥都会解密失败——而且错误信息非常简短,容易误判成路径或权限问题。











