Skip to content

Commit 45219a1

Browse files
committed
feat(modules): Add secrets as nixosModules
1 parent c2b06de commit 45219a1

File tree

2 files changed

+118
-0
lines changed

2 files changed

+118
-0
lines changed

modules/default.nix

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,6 @@
77
./folder-size-metrics
88
./shard-split
99
./host-info.nix
10+
./secrets.nix
1011
];
1112
}

modules/secrets.nix

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
{withSystem, ...}: {
2+
flake.nixosModules.mcl-secrets = {
3+
config,
4+
options,
5+
lib,
6+
dirs,
7+
...
8+
}: let
9+
eachServiceCfg = config.mcl.secrets.services;
10+
isDebugVM = config.mcl.host-info.isDebugVM;
11+
12+
sshKey = config.mcl.host-info.sshKey;
13+
14+
ageSecretOpts =
15+
builtins.head
16+
(builtins.head
17+
options.age.secrets.type.nestedTypes.elemType.getSubModules)
18+
.imports;
19+
20+
secretDir = let
21+
machineConfigPath = config.mcl.host-info.configPath;
22+
machineSecretDir = machineConfigPath + "/secrets";
23+
vmConfig = dirs.modules + "/default-vm-config";
24+
vmSecretDir = vmConfig + "/secrets";
25+
in
26+
if isDebugVM
27+
then vmSecretDir
28+
else machineSecretDir;
29+
in {
30+
options.mcl.secrets = with lib; {
31+
services = mkOption {
32+
type = types.attrsOf (types.submodule ({config, ...}: let
33+
serviceName = config._module.args.name;
34+
in {
35+
options = {
36+
encryptedSecretDir = mkOption {
37+
type = types.path;
38+
default = secretDir;
39+
};
40+
secrets = mkOption {
41+
default = {};
42+
type = types.attrsOf (types.submoduleWith {
43+
modules = [
44+
ageSecretOpts
45+
({name, ...}: let
46+
secretName = name;
47+
in {
48+
config = {
49+
name = "${serviceName}/${secretName}";
50+
file =
51+
lib.mkDefault (config.encryptedSecretDir + "/${serviceName}/${secretName}.age");
52+
};
53+
})
54+
];
55+
});
56+
};
57+
extraGroups = mkOption {
58+
type = types.listOf types.str;
59+
default = [];
60+
example = ["devops" "secretsAccess"];
61+
description = "Groups which have access to decrypt the secrets.";
62+
};
63+
extraKeys = mkOption {
64+
type = types.listOf types.str;
65+
default = [];
66+
example = ["ssh-ed25519 AAAAC3Nza" "ssh-ed25519 AAAACSNss"];
67+
description = "Groups which have access to decrypt the secrets.";
68+
};
69+
nix-file = mkOption {
70+
default =
71+
if (pathIsRegularFile (config.encryptedSecretDir + "/${serviceName}/secrets.nix"))
72+
then config.encryptedSecretDir + "/${serviceName}/secrets.nix"
73+
else
74+
builtins.toFile "${serviceName}-secrets.nix" ''
75+
let
76+
hostKey = ["${sshKey}"];
77+
extraKeys = ["${concatStringsSep "\"\"" config.extraKeys}"];
78+
in {
79+
${concatMapStringsSep "\n"
80+
(n: "\"${n}.age\".publicKeys = hostKey ++ extraKeys;")
81+
(builtins.attrNames config.secrets)}
82+
}
83+
'';
84+
85+
# groupsKeys = ["${concatStringsSep "\"\"" (mcl-modules.libs.utils.allUserKeysForGroup config.extraGroups)}"];
86+
87+
type = types.path;
88+
};
89+
};
90+
}));
91+
default = {};
92+
example = {
93+
service1.secrets.secretA = {};
94+
service1.secrets.secretB = {};
95+
service2.secrets.secretC = {};
96+
cachix-deploy.secrets.token = {
97+
path = "/etc/cachix-agent.token";
98+
};
99+
};
100+
description = mdDoc "Per-service attrset of encryptedSecretDir and secrets";
101+
};
102+
};
103+
104+
config = lib.mkIf (eachServiceCfg != {}) {
105+
age.secrets = lib.pipe eachServiceCfg [
106+
(lib.mapAttrsToList (serviceName: service:
107+
lib.mapAttrsToList (
108+
secretName: config:
109+
lib.nameValuePair "${serviceName}/${secretName}" config
110+
)
111+
service.secrets))
112+
lib.concatLists
113+
lib.listToAttrs
114+
];
115+
};
116+
};
117+
}

0 commit comments

Comments
 (0)