环境变量加密
服务使用的每个环境变量都存储在 services.env_json 列中。在写入之前,Pier 使用来自 /opt/pier/.env 的 32 字节密钥,以 AES-256-GCM 加密该 JSON:
PIER_SECRET=<32 bytes base64>加密后的值带有 ENC: 前缀,以便 Pier 能将其与遗留的明文行区分开来。
为什么密钥存放在数据库之外
Section titled “为什么密钥存放在数据库之外”如果攻击者仅窃取到 pier.db,他们将一无所获 —— 没有密钥,密文毫无用处。
如果攻击者仅窃取到 .env,则没有数据可供解密。
攻击者需要同时拥有两者才能读取密钥。
这与 Coolify 采用的模型相同(Laravel 的 APP_KEY + 加密类型转换)。它比 Vault 更简单,适合单租户的自托管工具。
首次启动引导
Section titled “首次启动引导”首次运行时,如果 /opt/pier/.env 不存在,Pier 会生成一个全新的 PIER_SECRET 并以 chmod 600 写入。同时会将数据库的一次性快照保存为 pier.db.pre-encryption,以备你需要回滚到明文模式进行调试。
轮换很少发生。需要时:
- 停止 Pier。
- 运行轮换辅助工具(计划中):
pier rotate-secret。 - 启动 Pier。
在 CLI 辅助工具发布之前,请通过 UI 导出环境变量,手动轮换 PIER_SECRET,然后重新导入。
不加密的内容
Section titled “不加密的内容”- 服务名称、镜像、端口和域名 —— 这些不是密钥。
- 部署元数据和日志 —— 它们是表层数据,而非凭据。
- Traefik 动态配置文件 —— 它们包含主机名,而非密钥。