YewSeal 是一个围绕 SOPS + age 构建的 CLI 工具,用清晰的配置文件定义批量加密/解密工作流。
它不重复造加密轮子,而是把项目初始化、文件映射登记、批量加密/解密和 age 私钥管理整合进一个友好的 CLI。
由于 TOML 需要先转换为 YAML 再交给 SOPS 处理,因此 TOML 注释不会被保留。如果需要保留说明性内容,建议搭配
*.example.toml使用。
- 🔐 基于 SOPS + age,兼容原生
.sops.yaml和 age 密钥工作流 - 🗂️ 使用直观的 TOML 配置文件,统一管理项目中的
plaintext/encrypted文件映射 - 🚀
init快速初始化,自动生成密钥、配置和推荐的项目文件 - 🔄 提供简洁的
yews e/yews d别名,可按配置处理所有文件,并支持目录扫描与并行处理 - 📦 支持 TOML、YAML、JSON、ENV、INI;其中 TOML 通过格式转换接入 SOPS 工作流
- 🔑 支持从环境变量、文件或配置文件读取密钥
- 🔐 可选将私钥同步到密钥管理服务(Infisical)
- 📝 加密/解密后保持原始数据结构
Age 和 SOPS 已内嵌为 Go 库,无需单独安装。
仅在使用 TOML 格式时需要安装格式转换工具:
- Remarshal - TOML/YAML 格式转换工具(仅 TOML 格式需要)
pipx install remarshal# 使用 mise 引入工具
mise use github:YewFence/YewSeal
# 交互式初始化项目
# 生成 age 密钥、.yewseal.toml,并登记需要处理的文件
yews init
# 之后也可以手动编辑 [[encryption.files]]
# 按配置批量加密所有登记过的文件
yews e
# 按同一份配置批量解密
yews d初始化完成后,建议将加密后的文件提交到版本控制,并妥善备份 .age/keys.txt。它包含 age 密钥对,一旦丢失就无法解密文件。
不想增加额外的配置文件? 完全可以只用命令行参数运行:
# 所有参数都可以通过命令行指定
yews encrypt -i config.toml -o config.enc.yaml -k .age/keys.txt -p "age1..."
yews decrypt -i config.enc.yaml -o config.toml -k .age/keys.txtgo install github.com/YewFence/YewSeal/cmd/yews@latest安装完成后可直接在任意目录使用 yews 命令(需要 $GOPATH/bin 在 $PATH 中)。
通过 mise 的 github backend 直接下载 release 中的预构建可执行文件并安装:
需要 mise activate 才可以使用
mise use github:YewFence/YewSeal
# 也可以使用 -g 参数安装到全局
yews --version发布包里的可执行文件名固定为 yews(Windows 下为 yews.exe),所以安装后直接使用 yews 即可。
git clone https://github.com/YewFence/YewSeal
cd YewSeal
# 使用 mise task(推荐)
mise run install # 安装到 $GOPATH/bin,可全局使用
# 或手动安装
go install -ldflags "-s -w -X main.Version=$(git describe --tags --always --dirty 2>/dev/null || echo dev)" ./cmd/yews安装完成后可直接在任意目录使用 yews 命令。
如果只需要本地构建而不安装到全局:
mise run build # 生产构建 → build/yews(Windows 下为 .exe)
mise run build -- --all # 构建 linux/windows/darwin × amd64/arm64
mise run build -- --target linux/amd64 # 构建指定平台
mise run dev # 开发构建 → test/yews(Windows 下为 .exe)从 Releases 页面下载适合你系统的预编译二进制文件。
如果你的环境里已经有 Docker,但不想额外安装 yews,可以直接跑容器镜像。
镜像现在分成两个变体:
ghcr.io/yewfence/yew-seal:latest:完整镜像,内置remarshal与它依赖的 Python 环境,体积更大,支持 TOML 和其他格式的加密解密ghcr.io/yewfence/yew-seal:lite:精简镜像,不带 Python 和remarshal,体积更小,不支持 TOML 格式
可以根据需要自行替换下方示例命令的镜像标签
稳定标签说明
latest:当前最新稳定版的完整镜像lite:当前最新稳定版的精简镜像如果需要指定镜像版本号:
- 完整镜像:
ghcr.io/yewfence/yew-seal:v1.0.0(也会同步发布:1.0.0)- 精简镜像:
ghcr.io/yewfence/yew-seal:v1.0.0-lite(也会同步发布:1.0.0-lite)
docker run --rm -it \
--user "$(id -u):$(id -g)" \
-v "$PWD:/work" \
ghcr.io/yewfence/yew-seal:latest initLinux/macOS 下,所有会写入挂载目录 /work 的命令(例如 init、encrypt、decrypt)都建议显式传入宿主用户 ID,避免生成的文件属于 root。Windows 一般可以省略 --user:
docker run --rm -it \
--user "$(id -u):$(id -g)" \
-v "$PWD:/work" \
ghcr.io/yewfence/yew-seal:latest init# 加密
docker run --rm \
--user "$(id -u):$(id -g)" \
-v "$PWD:/work" \
ghcr.io/yewfence/yew-seal:latest encrypt
# 解密
docker run --rm \
--user "$(id -u):$(id -g)" \
-v "$PWD:/work" \
ghcr.io/yewfence/yew-seal:latest decrypt手动使用 infisical cli 导出私钥至本地的参考命令如下
mkdir .age && infisical secrets get AGE_KEY_FILE --plain > ./.age/keys.txt或者直接设置 SOPS_AGE_KEY 环境变量:
docker run --rm \
-e SOPS_AGE_KEY="$(infisical secrets get AGE_KEY_FILE --plain)" \
--user "$(id -u):$(id -g)" \
-v "$PWD:/work" \
-w /work \
ghcr.io/yewfence/yew-seal:latest decrypt
edit和sync更适合本机直接运行:前者依赖宿主编辑器,后者依赖宿主机上的infisicalCLI 和登录状态
scoop bucket add YewNursery https://github.com/YewFence/YewNursery
scoop install YewSeal首次使用时,在项目根目录运行:
yews init直接运行 yews init 将进入交互式模式,程序会逐步询问:
-
原始配置文件名(默认:
wrangler.toml)- 输入您需要加密的配置文件名
-
加密文件名
- TOML 默认:
wrangler.enc.toml.yaml - 其他格式默认:在原扩展名前插入
.enc - 直接回车即可使用按文件类型推断出的默认值
- TOML 默认:
-
是否为当前文件创建示例文件(默认:否)
- 每录入一个文件都会单独询问一次
- 建议只给需要保留结构说明或注释的配置文件创建 example
-
是否继续添加下一个文件
- 可以连续录入多组
plaintext/encrypted文件映射
- 可以连续录入多组
-
是否创建 .sops.yaml(默认:是)
- 非必需,但便于直接使用
sops命令
- 非必需,但便于直接使用
初始化结束后,生成的 .yewseal.toml 会统一使用 [[encryption.files]] 数组配置。
每一项都用 plaintext 表示明文文件、encrypted 表示加密文件。
使用命令行参数跳过交互提示:
# 完全自定义配置
yews init --input app.toml --output app.secret.toml.yaml --create-example --skip-sops-config
# 仅指定文件名
yews init -i myapp.toml -o myapp.enc.toml.yaml
# 强制覆盖已有配置
yews init --force.age/keys.txt- Age 密钥对(私钥 + 公钥).yewseal.toml- YewSeal 配置文件(包含公钥和[[encryption.files]]数组).sops.yaml- SOPS 配置文件(如果选择创建).gitignore- 自动添加需要忽略的文件*.example.toml- 示例配置文件(如果选择创建)
如果选择创建了示例配置文件,记得在将其提交到版本控制系统前删除其中的敏感内容
📝 关于
.sops.yaml:虽然yews工具本身不强制要求此配置文件(通过环境变量传递密钥),但仍强烈推荐创建它,原因如下:
- 🤝 便于团队协作,确保使用统一的加密配置
- 🔧 支持直接使用原生
sops命令操作加密文件- 📋 符合 SOPS 官方最佳实践
- 🎯 明确定义哪些文件应该被加密
现在如果你是通过
.yewseal.toml里的[[encryption.files]]运行yews encrypt,工具会在加密前自动把.sops.yaml同步成当前配置对应的规则。
.age/keys.txt 私钥文件,丢失后无法恢复!
支持单文件和批量模式:
# 单文件模式
yews encrypt
yews e # 简写
# 批量模式(扫描目录)
yews encrypt --dir ./configs --pattern "*.toml"
yews e --dir ./configs --pattern "*.yaml" --parallel 4 # 并行处理支持的选项:
yews encrypt --input custom.toml --output custom.enc.toml.yaml
yews encrypt -i custom.toml -o custom.enc.toml.yaml --public-key "age1..."
yews encrypt --verbose # 显示详细输出如果你想直接用 Docker 跑:
docker run --rm -it \
--user "$(id -u):$(id -g)" \
-v "$PWD:/work" \
-w /work \
ghcr.io/yewfence/yew-seal encrypt从加密文件恢复原始配置:
# 单文件模式
yews decrypt
yews d # 简写
# 批量模式
yews decrypt --dir ./configs --pattern "*.enc.toml.yaml"
yews d --dir ./configs --parallel 4支持的选项:
yews decrypt --input custom.enc.toml.yaml --output custom.toml
yews decrypt -i custom.enc.toml.yaml -o custom.toml --verbose如果私钥通过环境变量注入,Docker 用法类似这样:
docker run --rm \
-e SOPS_AGE_KEY="$SOPS_AGE_KEY" \
--user "$(id -u):$(id -g)" \
-v "$PWD:/work" \
-w /work \
ghcr.io/yewfence/yew-seal decrypt使用编辑器直接编辑加密文件(自动处理加密/解密):
yews edit指定编辑器:
yews edit --editor "code -w"
yews edit -e vim
yews edit --file custom.enc.toml.yamlYewSeal 支持通过配置文件管理常用设置,避免每次都输入参数。
按优先级从高到低:
{project}/.yewseal/.yewseal.toml{project}/.config/.yewseal.toml{project}/.yewseal.toml
cp .yewseal.example.toml .yewseal.toml[encryption]
[[encryption.files]]
# plaintext = 明文文件
# encrypted = 加密文件
plaintext = "wrangler.toml"
encrypted = "wrangler.enc.toml.yaml"
[[encryption.files]]
plaintext = ".dev.vars"
encrypted = ".dev.vars.enc.yaml"
format = "env"
[key]
# Age 公钥(用于加密)
public_key = "age1..."
# Age 私钥文件路径(只存储路径,不存储密钥值)
file_path = ".age/keys.txt"
[sync]
# Infisical 项目 ID(可选;未设置时使用 infisical init 生成的本地项目配置)
project_id = "your-infisical-project-id"
# Age 私钥同步到密钥管理服务时使用的远端路径和环境名称
path = "/yewseal"
environment = "prod"参数获取遵循以下优先级(从高到低):
- 命令行参数 - 最高优先级
- 环境变量 -
SOPS_INPUT_FILE,SOPS_OUTPUT_FILE,AGE_KEY_FILE,SOPS_AGE_RECIPIENTS - 配置文件 -
.yewseal.toml - 默认值 - 最低优先级
# 使用配置文件中的 [[encryption.files]]
# 配了 1 项就处理 1 项,配了多项就按整组处理
yews encrypt
yews decrypt
# 命令行参数会覆盖配置文件
yews encrypt -i custom.toml -o custom.enc.toml.yaml
# 环境变量也会覆盖配置文件
export SOPS_INPUT_FILE="custom.toml"
yews encrypt通过配置文件驱动时,yews encrypt / yews decrypt 还会自动确认所有 plaintext 明文文件都在 .gitignore 里;其中 yews encrypt 还会顺便重建 .sops.yaml。
[encryption]
[[encryption.files]]
plaintext = "app.toml"
encrypted = "app.enc.toml.yaml"
[[encryption.files]]
plaintext = ".dev.vars"
encrypted = ".dev.vars.enc.yaml"
format = "env"
[key]
public_key = "age1..."
file_path = ".age/keys.txt"
[sync]
project_id = "your-infisical-project-id"
path = "/yewseal"
environment = "prod"配置好以后,直接运行下面两条命令即可批量处理,不需要额外传 --dir:
yews encrypt
yews decrypt工具支持多种方式提供 Age 密钥,优先级从高到低:
# 直接传递私钥值
export SOPS_AGE_KEY="AGE-SECRET-KEY-..."
yews decrypt
# 或传递公钥用于加密
export SOPS_AGE_RECIPIENTS="age1..."
yews encryptyews --key-file /path/to/keys.txt decrypt
yews encrypt --public-key "age1..."在 .yewseal.toml 中配置:
[key]
file_path = ".age/keys.txt"
public_key = "age1..."默认从 .age/keys.txt 读取私钥,从 .yewseal.toml 读取公钥。
支持将 Age 密钥同步到 Infisical 密钥管理服务。
Infisical 是一个开源的,可轻松自托管的秘密管理平台,此处使用它的 infisical CLI。
infisical login
infisical init此时你的项目中会生成一个 .infisical.json 配置文件,本工具会检测该配置文件是否存在作为 Infisical 配置完成与否的标志。
# 直接同步到项目根目录的 AGE_KEY_FILE 变量
yews sync
# 自行指定项目、变量名、路径和环境(需要提前创建)
yews sync --project-id your-infisical-project-id --name AGE_KEY_FILE --path /yewseal --env prod也可以在 .yewseal.toml 中固定同步位置,这样 yews sync 和 yews sync pull 会自动使用配置里的项目、远端路径和环境名称;如果没有设置 project_id,就会沿用 infisical init 生成的 .infisical.json 本地项目配置。
[sync]
project_id = "your-infisical-project-id"
path = "/yewseal"
environment = "prod"检查所需外部工具是否已安装:
yews check
# 或
yews doctorgit add .gitignore .yewseal.toml wrangler.enc.toml.yaml
# git add .infisical.json # 如果使用 Infisical
git add .sops.yaml # 可选但推荐
git commit -m "feat: 添加加密配置"wrangler.toml- 明文配置文件.age/keys.txt- 私钥文件
name: Deploy
on: push
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: stable
- name: Install YewSeal
run: go install github.com/YewFence/YewSeal/cmd/yews@latest
- name: Install tools
run: |
# 仅 TOML 格式需要 remarshal
pipx install remarshal
- name: Decrypt configuration
env:
SOPS_AGE_KEY: ${{ secrets.AGE_KEY }}
run: yews decrypt
- name: Deploy
run: npx wrangler deployAge 和 SOPS 已内嵌,无需单独安装。仅 TOML 格式需要 remarshal:
# 检查 remarshal(仅 TOML 格式需要)
toml2yaml --version
yaml2toml --version检查密钥是否正确设置:
# 检查环境变量
echo $SOPS_AGE_KEY
# 或检查文件
cat .age/keys.txt工具使用 remarshal 进行 TOML/YAML 转换,应该支持所有标准 TOML 特性,并且声明转换前后的文件会完全一致。如果遇到问题,请提交 Issue。
完整的命令行参考请查看 CLI.md。
--key-file, -k 指定 Age 私钥文件路径
--help, -h 显示帮助信息
--version, -v 显示版本信息
| 命令 | 别名 | 说明 |
|---|---|---|
init |
- | 初始化项目,生成密钥和配置 |
encrypt |
e |
加密配置文件 |
decrypt |
d |
解密配置文件 |
edit |
- | 使用编辑器编辑加密文件 |
check |
doctor |
检查外部工具是否安装 |
sync |
- | 同步密钥到密钥管理服务 |
TOML 加密: TOML → toml2yaml → YAML → sops encrypt → 加密 YAML
TOML 解密: 加密 YAML → sops decrypt → YAML → yaml2toml → TOML
其他格式: 原文件 → sops encrypt/decrypt → 加密/解密文件
YewSeal 内嵌了成熟的加密库,仅 TOML 格式转换依赖外部工具:
- Age (
filippo.io/age) - 现代化的加密库(内嵌) - SOPS (
github.com/getsops/sops/v3) - 密钥管理库(内嵌) - Remarshal - 配置格式转换工具(仅 TOML 需要,外部工具)
MIT License
欢迎提交 Issue 和 Pull Request!
我写这个的原因是因为我真的不想把 wrangler.toml 直接放在 GitHub 上,虽然里面没有泄露就出事的敏感信息,但是会有自己的域名/项目名称/ KV ID``D1 ID / R2 NAME 之类的信息,放在公开仓库总觉得不太好。直接放在 Infisical 里又不太方便,毕竟每次改配置都得去网站上操作一遍。所以就想到使用 SOPS ,但 SOPS 原生不支持 TOML 格式,我又真的不想用 yaml,缩进地狱,所以就写了这个工具来帮忙做格式转换和加密解密的编排工作。
想着来都来了,增加一个方便点的包装吧,于是就有了短命令和配置文件持久化功能,省得每次都敲一大堆参数。包装都包装了,干脆支持所有 SOPS 支持的格式吧,万一以后有别的配置文件需要加密呢。支持都支持了,不如增加一个多文件批量加密解密的功能,省得每次都得写脚本。既然有了批量处理,那就顺便加个并行处理,都用 Go 了,不些并行多可惜。总之就是越做越多功能,最后变成了现在这个样子。
接下来就是密钥管理的问题了,Age 的密钥对生成很方便,而且公钥可以直接放在配置文件里,私钥只需要保存在本地就行了。再结合 Infisical 这种密钥管理服务,就能比较方便地在 CI/CD 里使用密钥了,它也可以实现一个项目一个密钥,减少爆破半径,非常完美。
关于安全性嘛,Age + SOPS 还是挺靠谱的,至少比我自己写加密算法要靠谱多了。
本工具仅作为个人学习项目,未经充分测试和审计,不建议在高安全要求环境中使用。
本项目核心功能依赖于以下优秀的开源工具,感谢它们的贡献:
- Age (BSD 3-Clause) - A simple, modern and secure encryption tool (and Go library) with small explicit keys, no config options, and UNIX-style composability.
- SOPS (MPL 2.0) - Simple and flexible tool for managing secrets
- Remarshal (MIT) - Convert between CBOR, JSON, MessagePack, TOML, and YAML 1.1 & 1.2
- Infisical CLI (MIT) - The official CLI of Infisical