为什么明文秘密不能进入 Store?#
在 NixOS 中,配置源和构建引用的文件可能被复制到 /nix/store。
/nix/store是世界可读的(World-readable)。- 任何普通用户都能在
/nix/store找到你的 明文 API Key。
现代解决方案:sops-nix#
sops-nix 为 NixOS 和 Home Manager 提供运行时密钥解密。
1. 工作原理
- 用 age 公钥接收者或 SOPS 支持的其他方式加密
secrets.yaml;对应私钥用于解密,保存在 Store 和公开仓库之外。 - 在 Nix 中,你只引用加密后的文件。
- NixOS 模块在激活或服务阶段解密到
/run/secrets/;通过 owner/group/mode 控制哪些服务或用户可以读取。
2. 实战步骤
- 安装
sops命令行工具。 - 生成 age 密钥。
- 在配置中集成:
# flake.nix 加入 inputs.sops-nix # configuration.nix { inputs, ... }: { imports = [ inputs.sops-nix.nixosModules.sops ]; sops.defaultSopsFile = ./secrets.yaml; sops.age.sshKeyPaths = [ "/etc/ssh/ssh_host_ed25519_key" ]; # 定义一个密钥 sops.secrets."github_token" = {}; }
另一种选择:agenix#
agenix 相比 sops-nix 更加轻量,以 age 文件为单位管理秘密,支持 age 的接收者方式,包括受支持的 SSH 密钥。
在 Home Manager 中使用 Secrets#
系统服务可由 NixOS 模块解密,用户配置只引用运行时文件路径并显式设置读取权限。sops-nix 也提供 Home Manager 模块,由用户服务解密到运行时目录;依赖秘密的用户服务需要正确排序。不要用 builtins.readFile 将解密后的明文插入 Nix 配置,也不要把秘密的值写进 home.sessionVariables;优先使用应用的凭据文件选项。
公开配置的准备#
如果你打算开源你的 Nix 配置,第一件事就是把所有的密码、Token 移除,并引入 sops-nix。
总结#
- 不要在
.nix里写明文密码。 - 使用合适的加密接收者并保护解密私钥。
- 确保私钥和原始明文不进入 Git、Store 或日志;
.gitignore不能清除已被跟踪的泄露历史。
参考与延伸
根据技术笔记重新整理,示例使用通用名称。