跳至内容

密钥

Composia 使用 age 加密在期望状态仓库中管理加密的密钥文件。加密和解密在控制器上发生。Agent 永远不会访问 age 私钥。

配置

密钥需要一个 age 密钥对。在控制器配置中设置:

controller:
  secrets:
    provider: age
    identity_file: "/app/configs/age-identity.key"
类型必填描述
providerstring必须为 age
identity_filestringage 私钥文件的路径。
recipient_filestring包含 age 接收者(公钥)的文件路径。如果省略,接收者从私钥派生。
armorbool使用 ASCII 封装输出。默认为 true

生成密钥对:

age-keygen -o age-identity.key

可选:提取公钥作为接收者:

age-keygen -y age-identity.key > age-recipients.txt

密钥的存储方式

仓库中的密钥文件按惯例带有 .enc 扩展名。它们以 age 加密的密文形式存储:

my-app/
├── docker-compose.yaml
├── composia-meta.yaml
└── .secret.env.enc        (使用 age 加密)

控制器在写入时加密明文,在读取时解密。仓库中只包含密文。密钥从不会以明文形式出现在仓库、任务日志或传输给 agent 的数据中。

密钥如何到达 agent

在部署或更新任务的渲染步骤中,控制器:

  1. 从仓库中的服务目录读取加密文件。
  2. 使用 age 私钥解密每个文件。
  3. 去掉 .enc 后缀,并以运行时文件名注入解密内容。例如,.secret.env.enc 会变成 .secret.env

服务包通过 agent 报告连接流式传输到 agent。Agent 将包写入磁盘并继续执行 docker compose up。解密后的密钥环境变量可供 Compose 服务使用,而 agent 永远不会看到私钥。

composia-meta.yaml 中的文件引用使用仓库文件名,例如 .env.enc;Composia 在运行时使用前将其转换为 .env。Compose、Caddyfile、脚本等原生文件内部直接填写运行时文件名 .env

CLI 用法

写入加密的密钥文件:

composia service my-app edit .secret.env.enc

读取并解密密钥文件:

composia repo get my-app/.secret.env.enc

就地编辑密钥(打开编辑器):

composia repo update --file ./local-plain.env my-app/.secret.env.enc

所有密钥写入操作都包含基准版本检查,以防止与并发更改冲突。

文件路径规则

密钥文件路径必须:

  • 相对于服务目录(不能是绝对路径)。
  • 不包含路径穿越序列,如 ../
  • 指向服务目录内的文件。

控制器定位服务,相对于服务目录解析文件路径,并对仓库文件进行操作。

错误情况

  • 密钥未配置:当 controller.secrets 未设置时,Repo API 对 .enc 文件的读写返回 FailedPrecondition
  • 文件未找到GetRepoFile 返回 NotFound
  • 基准版本冲突UpdateRepoFile 使用 CAS(比较并交换)保护仓库 HEAD。
最后更新于 • alexma233