1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
|
{ pkgs, lib }:
{
options.secrets = {
secrets = lib.mkOption {
description = ''
A set of secrets, each identified by a name (e.g. mattermost, gitlabce).
Each secret has a filename and a script to generate it.
'';
default = { };
type = lib.types.attrsOf (lib.types.submodule {
options = {
filename = lib.mkOption {
type = lib.types.pathWith {
absolute = false;
inStore = false;
};
description = ''
The filename this secret should have. This is a relative path,
relative to the base of the secret store, which is normally
`/etc/nixos/secrets`. It is fine for it to be a bare filename.
'';
example = "mysecret.key";
};
script = lib.mkOption {
type = lib.types.lines;
description = ''
Shell command that generates the secret.
'';
example = "head -c 32 /dev/urandom | base32";
};
};
});
};
# For modularity's sake, we export a cleanly-defined structure for the CLI
# tool to wrap around. That way we avoid inadvertently relying on the
# overall structure of the secrets options, and in particular we avoid
# relying on implementation details that will change.
export = lib.mkOption {
description = ''
An internal value used for the command-line secret-management tool to
query an assembled NixOS configuration about what secrets it expects
to exist, and their properties.
'';
example = {
mattermost = {
path = "/etc/nixos/secrets/mattermost.key";
script = "touch /etc/nixos/secrets/mattermost.key"
};
neooffice = {
path = "/etc/nixos/secrets/neooffice.key";
script = "head -c 32 /dev/urandom > /etc/nixos/secrets/neooffice.key"
};
};
type = lib.types.attrsOf lib.types.submodule = {
options = {
path = {
type = lib.types.pathWith {
absolute = true;
inStore = false;
};
description = ''
An internal value which is part of `secrets.export`, used by
the command-line secret-management tool. This is an absolute
path to the file which, if the secret exists, should contain it.
When the CLI tool is run, this directory is expected to exist;
whether the file exists is the thing the CLI tool is responsible
for managing.
'';
example = "/etc/nixos/secrets/neooffice.key";
};
script = {
type = lib.types.lines;
description = ''
An internal value which is part of `secrets.export`, used by
the command-line secret-management tool. This is a shell script
which will create the secret, destructively overwriting it if it
already exists. It runs in an empty shell environment with no
environment variables. It should start with an appropriate
`#!` line pointing to the correct shell to run it under.
'';
example = ''
#!/nix/store/s68ja06r60xbs51k8lrdciva4di46y61-bash-5.2/bin/bash
head -c 32 /dev/urandom > /etc/nixos/secrets/neooffice.key
'';
};
};
};
};
};
config.secrets.export = { config, pkgs, ... }:
let exportSecret = name: secret: {
path = "/etc/nixos/secrets/${secret.file}";
script = ''
#!${pkgs.bash}/bin/bash
${secret.script}
'';
};
in mapAttrs exportSecret config.secrets.secrets;
}
|