Show HN: Secs-man,一个你可以(不)依赖的机密管理器
摘要
secs-man 是一个机密备份工具,设计为工具无关,使用 age 加密和标准 Unix 工具,因此即使没有软件本身,数据也能恢复。
查看缓存全文
缓存时间: 2026/06/25 14:11
Fran314/secrets-manager-rs 源代码:https://github.com/Fran314/secrets-manager-rs
secs-man
secs-man 是一个用于管理机密备份的工具,其设计思想是工具无关:如果你用此软件加密了机密文件,你应该能够在不依赖此软件的情况下解密和恢复它们。即使 secs-man 从世界上消失,你的数据仍然可以访问。
secs-man 可用于管理本地和远程机器的机密文件,非常适合创建仅本地备份,用于那些过于敏感、不宜备份到云中的数据。
哲学
理论
你不应该依赖任何特定软件来备份极其重要的数据。任何迫使你在使用后仍留在其生态系统中的软件(例如:“如果你用这个软件加密,就只能用这个软件解密”)都会使你对其产生依赖。因此,重要数据的加密、解密和恢复应该是解耦的,也就是说,如果你用软件X加密了数据,你应该能够在没有软件X的情况下解密它。
实践
在实践中,你无法创建一个让机密100%免于数据丢失的配置。即使你的软件X与Y、Z、W兼容,如果X、Y、Z、W同时停止工作,你仍会失去对数据的访问。在实践中,你要做的是确保只依赖那些“标准”或接近标准的技术。我可以接受依赖bash解释器、USB端口和Linux机器的存在。因此,secs-man的真正目标是仅通过以下工具实现完全可复现:
- 一个终端
- coreutils,如
cp、mv和sha256sum - age(https://github.com/FiloSottile/age)
- 手动操作和一点时间
对
age的依赖是最微妙的,但依赖某种加密库是不可避免的,而age既有很高的人气,也有很好的Rust绑定。这确保了即使此软件发生任何问题而无法再次使用,只要age仍然存在,并且你愿意花上30分钟,你仍然可以恢复所有机密。
手动恢复部分说明了如何在不使用此软件的情况下,仅使用coreutils、age和终端来导入此软件导出的机密。
安装
secs-man 未在任何地方发布(既不是发布的crate,也不在nixpkgs、AUR等)。只能通过以下方式从此仓库直接安装。
使用 nix run
如果你只是偶尔使用 secs-man,可以直接运行而不安装(需要启用 flakes)
nix run github:Fran314/secrets-manager-rs -- export /path/to/secrets /path/to/export/endpoint
通过 Nix 配置
要使 secs-man 系统可用,可以在你的 Nix 配置中使用 fetchGit 导入此仓库,并将生成的包添加到 environment.systemPackages(或使用 home-manager 时添加到 home.packages)
let
secs-man = pkgs.callPackage "${builtins.fetchGit {
url = "https://github.com/Fran314/secrets-manager-rs.git";
ref = "main";
# rev = ""; # 锁定特定提交以实现可复现性
}}/default.nix" {};
in
# 将 secs-man 添加到 environment.systemPackages 或 home.packages
使用 cargo
如果你不使用 NixOS,可以通过 cargo 指向此仓库来安装 secs-man 二进制文件
cargo install --git https://github.com/Fran314/secrets-manager-rs
注意,这些方法都不会安装 secs-man-ssh 脚本,该脚本用于远程机器:它是一个独立的脚本,需要从此仓库单独复制。
使用
此工具允许从给定的源目录导出和加密文件,并通过导入到相同目录来恢复文件。
推荐的使用方式是将所有“机密”(密钥、文件等)集中在一个目录中。在机密集的根目录下应有一个 .secrets-manifest 明文文件,其中包含要管理的机密列表,以相对于机密集的路径形式给出。文件路径不能包含空格。每个条目还可以指定 owner 和 mode,这些将在导入时用于设置正确的权限。语法见 .secrets-manifest.example。
在导出过程中,清单中列出的文件将通过 age 加密,加密口令通过交互提示请求(secs-man 从不从文件、参数或环境变量中读取口令)。导入时会再次请求相同的口令以解密文件。文件的完整性由配套的 *.sha256 文件保证,该文件在缺失时会自动生成。
加密后的文件会导出到导出目标目录内一个带时间戳的快照中。之后可以通过指向导出目标目录(导入最新快照)或指向该目录中的特定快照来解密和导入文件。
以下命令可以在没有 sudo 的情况下运行,但如果清单中指定了与执行命令的用户不同的所有者,命令将失败(因为内部的 chown 调用会失败)。
要导出你的机密,运行
sudo secs-man export /path/to/secrets /path/to/export/endpoint
要验证现有导出的完整性(参见下面的注释),运行
# 验证所有导出快照的完整性
sudo secs-man verify-export /path/to/export/endpoint
# 验证特定快照的完整性
sudo secs-man verify-export /path/to/export/endpoint/export-YYYY-MM-DD_HH-MM-SSZ
注意:每次导出时都会自动进行完整性检查。只有在需要检查可能已损坏的旧导出时才需要此命令。
要导入你的机密,运行
# 导入最新快照
sudo secs-man import /path/to/export/endpoint /path/to/secrets
# 导入特定快照
sudo secs-man import /path/to/export/endpoint/export-YYYY-MM-DD_HH-MM-SSZ /path/to/secrets
# 仅导入特定机密
sudo secs-man import /path/to/export/endpoint /path/to/secrets --pick ssh/id_ed25519 wg/wg0.key
远程机器使用
此工具也可用于在远程机器上部署和备份机密。导出远程机密的最简单方法是将它们导出到远程主机上的临时目录,然后将导出的快照复制到本地备份。类似地,要导入本地备份,最简单的方法是将本地快照复制到远程主机上的临时目录,然后从那里导入。
但是,这存在一个问题:加密/解密口令必须经过远程主机,而远程主机可能被视为不受信任。为了在不将口令传递到远程的情况下部署到/备份来自不受信任的远程主机,你可以使用 secs-man-ssh 脚本。此脚本不假设通过SSH进行root登录(因为出于安全原因可能被禁用),但假设远程用户具有 sudo 权限(以便让 secs-man 运行 chown 和 chmod)。
要从远程主机导出,运行:
secs-man-ssh export
# 流程如下:
# 1. 脚本将远程机密复制到远程主机上的临时目录
# 2. 临时目录的所有权更改为远程普通用户,以便能够无sudo读取并复制到本地
# 3. 临时目录被复制到本地主机,并从远程主机删除
# 4. 本地目录被导出到本地备份,然后删除
要导入到远程主机,运行:
# 脚本导入需要远程安装 secs-man
secs-man-ssh import
# 流程如下:
# 1. 最新快照被导入到本地临时目录,使用 `--skip-chown-chmod` 标志,以便能够无sudo读取并复制到远程主机
# 2. 本地目录被复制到远程主机的临时目录,并从本地主机删除
# 3. 远程临时目录被导入到远程机密目录,使用 `--from-plaintext`,因为文件已经解密
# 4. 远程临时目录被删除
手动恢复
导出
导出的文件使用 age 采用口令加密。导出文件的名称是原始名称加上额外的 .age 扩展名。要获得相同的行为,可以使用以下命令:
age --passphrase --output filename.txt.age --encrypt filename.txt
注意:
- 导出前,会检查源文件的校验和
- 导出过程中,现有明文文件的校验和会导出到加密文件旁边
- 导出后,会为所有加密文件创建另一个校验和,以便以后检查导出的完整性。
验证导出
验证导出的完整性包括检查每个校验和是否匹配。为此,可以在导出的快照目录中运行:
find . -name "sha256sums.txt" -execdir sha256sum -c sha256sums.txt \;
导入
导入的文件使用 age 采用口令解密。导入文件的名称是导出名称去掉 .age 扩展名。如果在清单中为某个条目指定了 owner 和/或 mode,则导入的文件会设置为指定的所有者和权限。如果未指定 mode,则默认为 600。要获得相同的行为,可以使用以下命令:
age --output filename.txt --decrypt filename.txt.age
# 如果未指定mode,默认为600
chmod 600 filename.txt
# 如果未指定owner,跳过此步骤
chown user:group filename.txt
注意:
- 导入前,会检查源文件的校验和
- 导入后,会检查导入文件的校验和
威胁模型
此工具在导出期间自动创建快照,但不会自动清理这些快照。这意味着使用此工具导出机密时应格外小心。
当导出“认证”机密(SSH/WireGuard密钥、令牌)时,这些机密可以轻松轮换,快照的存在不会带来额外风险。
然而,当导出“解密”机密(磁盘密钥、age/PGP身份、密码管理器主密钥)时,快照的存在意味着,如果导出中的机密被泄露并以某种方式解密,攻击者可能访问当前和过去的解密密钥。因此,在轮换“解密”机密时,最好同时删除旧的导出快照(可以轻松地用 rm -r /path/to/export/endpoint/export-YYYY-MM-DD_HH-MM-SSZ 完成)。注意,暴露旧解密密钥的关键路径也意味着知道当前机密,这可能是更大的问题。
相似文章
使用sops-nix在NixOS上管理机密
使用sops-nix在NixOS配置中管理机密的指南,涵盖设置、加密以及与Samba等服务的集成。
NixOS 与密钥管理
教程介绍 NixOS 的密钥管理选项,比较 sops-nix、agenix 和 ragenix 工具,并提供使用 sops-nix 进行加密密钥管理的实际示例。
配置中不应包含秘密
本文认为秘密不应存储在配置文件中,通过对NixOS模块的审计显示,四分之一的模块需要变通方法才能将秘密与配置分离。它提倡为秘密使用专门的运行时通道。
Show HN: Flashpaper – 无数据库的自毁式秘密分享
Flashpaper 是一种自毁式秘密共享服务,在浏览器中零知识加密数据,仅将载荷存储在 RAM 中(无数据库),并为 AI 代理提供 REST API 和 MCP 服务器。
Show HN:开源私有家庭安防摄像头系统(端到端加密)
Secluso 是一款基于树莓派的开源、端到端加密家庭安防摄像头系统,可在无需云监控的情况下实现远程访问。它支持 5 分钟快速部署和可重现构建。