sops-nix 加密敏感信息

将 NixOS 配置托管在公开的 GitHub 仓库中,是实践声明式管理和分享的最佳方式,但这引出了一个关键问题:如何处理 SSH 密钥和密码等敏感信息?
所以我们需要一个既安全又能融入 NixOS 哲学的方案 — 采用 sops-nix 来加密私密信息,并将其无缝集成到我公开配置中。

寻找那把合适的“锁”

我的目标是:找到一个工具,能将我的私密文件加密后安全地存入 Git,并且在 nixos-rebuild switch 时,系统能自动用机器上的密钥解密它们。

社区里主流的方案有两个:agenixsops-nixagenix 更轻量,只专注于 age 加密;而 sops-nix 则更像一个瑞士军刀,支持 ageGPG 等多种后端,社区也更庞大。本着一步到位的原则,我选择了 sops-nix

配置 .sops.yaml

万里长征第一步,是配置 sops 的规则文件——.sops.yaml。这个文件告诉 sops:“当你加密一个文件时,应该用哪些人的‘公钥锁’把它锁上?”

我很快写出了第一版配置,并满怀信心地创建了一个 ssh.secrets.yaml 文件,准备加密。

sops --encrypt --in-place ssh.secrets.yaml

回车!然后……

1
config file not found, or has no creation rules...

这是我遇到的第一个拦路虎。经过一番排查,我意识到 sops 命令对执行路径非常敏感,它需要在我项目的根目录下执行,那里才有 .sops.yaml。吸取教训后,我决定采用一种更优雅、可维护性更高的方式来组织我的公钥,使用了 YAML 的“锚点”特性:

1
2
3
4
5
6
7
8
9
# .sops.yaml
keys:
- &admin_seeker_age age19jg9f78x9dxmze6chtd29zhyltr0udndfajp0spc67ygznfv9pjqshah6c

creation_rules:
- path_regex: .*secrets\.yaml$
key_groups:
- age:
- *admin_seeker_age

这种写法不仅清晰,而且以后如果我有多个服务器或者协作者,只需要在 keys 部分添加,然后在规则里引用别名即可,非常方便。

sops 融入我的 Flake

加密工作流跑通了,接下来就是把它集成到我的 NixOS 配置中。

首先,修改 flake.nix,加入 sops-nix 作为输入源,并把它传递给 outputs 函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# flake.nix
{
inputs = {
# ...
sops-nix = {
url = "github:Mic92/sops-nix";
inputs.nixpkgs.follows = "nixpkgs";
};
# ...
};

outputs = { self, nixpkgs, sops-nix, ... }: {
# ...
homeConfigurations.seeker = home-manager.lib.homeManagerConfiguration {
# ...
# 在这里为 home-manager 引入 sops 模块
sharedModules = [
inputs.sops-nix.homeManagerModules.sops
];
};
};
}

接着,我开始在我的 home-manager 配置里使用它。我的目标是将加密的 SSH 私钥部署到 ~/.ssh/ 目录下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# modules/shell/tools.nix

{ pkgs, config, ... }: {
programs.ssh = {
enable = true;
# ...
# 引用解密后文件的路径
matchBlocks."*".identityFile = [
config.sops.secrets."id_ed25519".path
];
};

# 在这里声明 secret
sops.secrets."id_ed25519" = {
sopsFile = ./ssh.secrets.yaml;
key = "ssh_id_ed25519_private_key";
path = "${config.home.homeDirectory}/.ssh/id_seeker";
};
# ...
}

最终章:梦想照进现实

经过一番折腾,我的配置终于成型了。

  1. 一个可靠的 .sops.yaml 文件定义了加密规则。
  2. 一个加密的 ssh.secrets.yaml 文件安全地躺在我的 Git 仓库里。
  3. flake.nix 正确地引入了 sops-nix 模块。
  4. home-manager 配置在正确的层级结构下,声明了我的 SSH 密钥,并让 programs.ssh 直接引用解密后的文件路径。

我深吸一口气,最后一次运行 sudo nixos-rebuild switch --flake .#miLaptop

构建过程顺利通过,系统切换成功!我立刻检查 ~/.ssh/ 目录:

1
2
3
$ ls -la ~/.ssh/id_seeker*
-rw------- 1 seeker users 2610 Aug 27 22:30 /home/seeker/.ssh/id_seeker
-rw-r--r-- 1 seeker users 573 Aug 27 22:30 /home/seeker/.ssh/id_seeker.pub

sops-nix 加密敏感信息
https://20040702.xyz/2025/08/27/sops-nix/
作者
Seeker
发布于
2025年8月27日
许可协议