名称: fnox-configuration 用户可调用: false 描述: 当使用 fnox.toml 配置 Fnox 秘密管理时使用。涵盖文件结构、秘密定义、配置文件和层次化配置。 允许的工具:
- 读取
- 写入
- 编辑
- Bash
- Grep
- Glob
Fnox - 配置
使用 fnox.toml 文件配置 Fnox 秘密管理,实现安全、版本控制的秘密存储。
基本配置
初始化项目
# 在当前目录创建 fnox.toml
fnox init
# 使用特定提供商初始化
fnox init --provider age
基本 fnox.toml 结构
# fnox.toml
[providers.age]
type = "age"
public_keys = ["age1ql3z7hjy54pw3hyww5ayyfg7zqgvc7w3j2elw8zmrj2kg5sfn9aqmcac8p"]
[secrets]
DATABASE_URL = { provider = "age", value = "age[...]" }
API_KEY = { provider = "age", value = "age[...]", description = "生产 API 密钥" }
秘密定义
简单秘密
[secrets]
DATABASE_URL = "postgresql://localhost/myapp" # 纯文本(仅用于开发)
加密秘密
[secrets]
DATABASE_URL = {
provider = "age",
value = "age1encrypted-value-here",
description = "生产数据库连接字符串"
}
带默认值的秘密
[secrets]
DEBUG_MODE = {
provider = "age",
value = "age[...]",
default = "false",
description = "启用调试日志"
}
秘密行为选项
[secrets]
OPTIONAL_API_KEY = {
provider = "age",
value = "age[...]",
if_missing = "warn" # 选项: "error", "warn", "ignore"
}
REQUIRED_SECRET = {
provider = "age",
value = "age[...]",
if_missing = "error" # 如果缺失则失败(默认)
}
配置层次结构
文件位置(优先级顺序)
fnox.local.toml- 本地覆盖(gitignored)fnox.$FNOX_PROFILE.toml- 配置文件特定fnox.toml- 项目配置- 父目录
fnox.toml文件(递归) ~/.config/fnox/config.toml- 全局配置
全局配置
# ~/.config/fnox/config.toml
[providers.age]
type = "age"
identity = "~/.config/fnox/keys/identity.txt"
[settings]
if_missing = "warn" # 缺失秘密的全局默认值
项目配置
# project/fnox.toml
[providers.age]
public_keys = ["age1ql3z7hjy54pw3hyww5ayyfg7zqgvc7w3j2elw8zmrj2kg5sfn9aqmcac8p"]
[secrets]
DATABASE_URL = { provider = "age", value = "age[...]" }
APP_NAME = "myapp"
本地覆盖
# project/fnox.local.toml (gitignored)
[secrets]
DATABASE_URL = "postgresql://localhost/myapp_dev" # 本地开发覆盖
DEBUG = "true"
配置文件
定义配置文件
# fnox.toml
[secrets]
DATABASE_URL = "postgresql://localhost/myapp" # 默认
[profiles.production]
[profiles.production.secrets]
DATABASE_URL = { provider = "aws-sm", value = "prod/database-url" }
[profiles.staging]
[profiles.staging.secrets]
DATABASE_URL = { provider = "aws-sm", value = "staging/database-url" }
使用配置文件
# 通过环境变量设置配置文件
export FNOX_PROFILE=production
fnox get DATABASE_URL
# 或使用标志
fnox --profile staging get DATABASE_URL
fnox -p production exec -- node app.js
配置文件特定文件
# fnox.production.toml
[providers.aws-sm]
type = "aws-sm"
region = "us-east-1"
[secrets]
DATABASE_URL = { provider = "aws-sm", value = "prod/database-url" }
API_KEY = { provider = "aws-sm", value = "prod/api-key" }
# 使用配置文件特定文件
export FNOX_PROFILE=production
fnox get DATABASE_URL # 从 fnox.production.toml 加载
配置导入
导入其他配置
# fnox.toml
import = ["shared-secrets.toml", "../common/fnox.toml"]
[secrets]
APP_SPECIFIC_SECRET = { provider = "age", value = "age[...]" }
共享配置
# shared-secrets.toml
[providers.age]
public_keys = ["age1ql3z7hjy54pw3hyww5ayyfg7zqgvc7w3j2elw8zmrj2kg5sfn9aqmcac8p"]
[secrets]
SHARED_API_KEY = { provider = "age", value = "age[...]" }
验证
检查配置
# 显示诊断信息
fnox doctor
# 验证可以检索秘密
fnox get DATABASE_URL
# 列出所有配置的秘密
fnox list
# 测试特定提供商
fnox provider test age
常见验证错误
# 错误: 缺少提供商定义
[secrets]
API_KEY = { provider = "nonexistent", value = "..." }
# 错误: 无效提供商配置
[providers.age]
# 缺少必需字段
# 错误: 循环导入
import = ["other.toml"] # other.toml 导入此文件
最佳实践
分离公共和私有配置
# fnox.toml (已提交)
[providers.age]
public_keys = ["age1ql3z..."] # 公共密钥可安全提交
[secrets]
DATABASE_URL = { provider = "age", value = "age[...]" }
API_KEY = { provider = "age", value = "age[...]" }
# fnox.local.toml (gitignored)
[providers.age]
identity = "~/.ssh/age-identity.txt" # 私有密钥,绝不提交
[secrets]
DATABASE_URL = "postgresql://localhost/dev" # 本地覆盖
记录秘密
[secrets]
DATABASE_URL = {
provider = "age",
value = "age[...]",
description = "生产数据库的 PostgreSQL 连接字符串"
}
STRIPE_API_KEY = {
provider = "age",
value = "age[...]",
description = "用于支付处理的 Stripe 秘密密钥"
}
SENDGRID_API_KEY = {
provider = "age",
value = "age[...]",
description = "用于事务性电子邮件的 SendGrid API 密钥"
}
使用有意义的名称
# 好: 清晰、描述性名称
[secrets]
POSTGRES_CONNECTION_STRING = { provider = "age", value = "age[...]" }
STRIPE_SECRET_KEY = { provider = "age", value = "age[...]" }
JWT_SIGNING_SECRET = { provider = "age", value = "age[...]" }
# 避免: 模糊名称
[secrets]
DB = { provider = "age", value = "age[...]" }
KEY1 = { provider = "age", value = "age[...]" }
SECRET = { provider = "age", value = "age[...]" }
设置适当的默认值
[secrets]
# 好: 非敏感配置的合理默认值
LOG_LEVEL = { default = "info" }
CACHE_TTL = { default = "3600" }
# 避免: 敏感数据的默认值
API_KEY = { default = "unsafe-default-key" } # 不好!
常见模式
多环境设置
# fnox.toml - 基础配置
[providers.age]
public_keys = ["age1ql3z..."]
[secrets]
APP_NAME = "myapp"
# fnox.development.toml
[secrets]
DATABASE_URL = "postgresql://localhost/myapp_dev"
DEBUG = "true"
# fnox.production.toml
[providers.aws-sm]
type = "aws-sm"
region = "us-east-1"
[secrets]
DATABASE_URL = { provider = "aws-sm", value = "prod/db-url" }
DEBUG = "false"
功能标志
[secrets]
FEATURE_NEW_DASHBOARD = { default = "false" }
FEATURE_BETA_API = { default = "false" }
FEATURE_ROLLOUT_PERCENTAGE = { default = "0" }
服务配置
[secrets]
# 数据库
DATABASE_HOST = { provider = "age", value = "age[...]" }
DATABASE_PORT = { default = "5432" }
DATABASE_NAME = { default = "myapp" }
DATABASE_USER = { provider = "age", value = "age[...]" }
DATABASE_PASSWORD = { provider = "age", value = "age[...]" }
# Redis
REDIS_HOST = { provider = "age", value = "age[...]" }
REDIS_PORT = { default = "6379" }
REDIS_PASSWORD = { provider = "age", value = "age[...]" }
反模式
不要提交私有密钥
# 不好: 提交的配置中包含私有密钥
[providers.age]
identity = "AGE-SECRET-KEY-..." # 绝不要这样做
# 好: 引用 gitignored 位置
[providers.age]
identity = "~/.config/fnox/keys/identity.txt"
不要对敏感数据使用纯文本
# 不好: 纯文本中的敏感数据
[secrets]
DATABASE_PASSWORD = "super-secret-password" # 提交到 git!
# 好: 加密
[secrets]
DATABASE_PASSWORD = { provider = "age", value = "age[...]" }
不要重复秘密
# 不好: 同一秘密定义多次
[secrets]
API_KEY = { provider = "age", value = "age[...]" }
STRIPE_KEY = { provider = "age", value = "age[...]" } # 与 API_KEY 相同
# 好: 使用一个秘密,从代码中引用
[secrets]
STRIPE_API_KEY = { provider = "age", value = "age[...]" }
不要混合关注点
# 不好: 秘密与非秘密配置混合
[secrets]
DATABASE_PASSWORD = { provider = "age", value = "age[...]" }
APP_NAME = "myapp" # 不是秘密!
LOG_LEVEL = "info" # 不是秘密!
# 好: 只在 fnox.toml 中放秘密
[secrets]
DATABASE_PASSWORD = { provider = "age", value = "age[...]" }
# 对非秘密使用单独的配置文件
# app.config.toml
APP_NAME = "myapp"
LOG_LEVEL = "info"
高级模式
模板值
[secrets]
DATABASE_HOST = { provider = "age", value = "age[...]" }
DATABASE_NAME = { default = "myapp" }
DATABASE_USER = { provider = "age", value = "age[...]" }
DATABASE_PASSWORD = { provider = "age", value = "age[...]" }
# 在应用程序代码中从上述组件构造
# DATABASE_URL = postgresql://{USER}:{PASSWORD}@{HOST}/{NAME}
条件秘密
[secrets]
# 始终加载的基础秘密
API_KEY = { provider = "age", value = "age[...]" }
[profiles.ci]
[profiles.ci.secrets]
# 仅用于 CI 的额外秘密
CI_TOKEN = { provider = "age", value = "age[...]" }
DEPLOY_KEY = { provider = "age", value = "age[...]" }
相关技能
- 提供商: 配置加密和秘密存储提供商
- 安全最佳实践: 秘密管理的安全指南