Skip to content

Commit 4a597fb

Browse files
danimoLennyPenny
authored andcommitted
add sops to command line tools for convenience
WiP wip wip add lenny encrypt for router and lenny don't get fancy with htaccess sops: add lenny remove superflouos sops.yaml make custom secrets module use different runtime dir it was clashing with the sops one, which is also hardcoded D:
1 parent 11d854b commit 4a597fb

6 files changed

Lines changed: 214 additions & 99 deletions

File tree

.sops.yaml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
keys:
2+
- &danimo age1jt9l7zef9mqdvjlkur2eqd6gsvyaj469nfxucv7dv08e3qpuvudswcf0ng
3+
- &reimerei age1p7kfmmtpcaxp8ya54azxwufl85ru3rlnpay27d3h4nrucyn6afzqzw5zrz
4+
- &lenny age164tnfsyunrhyyrmgdn437ajcyyn2ch4y453eu3e0s8z4jtnmc4qqfj0m5z
5+
- &machine_router age139t43h3ey5zn2uj5wh42upzzfqv9m5x6rwdy3g29n77yr5kwadns4n5xcs
6+
7+
creation_rules:
8+
- path_regex: secrets/[^/]+\.(yaml|json|env|ini)$
9+
key_groups:
10+
- age:
11+
- *danimo
12+
- *reimerei
13+
- *lenny
14+
- *machine_router

flake.nix

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
pkgs.alejandra
2525
pkgs.git
2626
pkgs.colmena
27+
pkgs.sops
2728
# pkgs.prometheus-snmp-exporter
2829
];
2930
env.DIRENV_LOG_FORMAT = "";

hosts/router/configuration.nix

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,14 @@
1-
{ lib, config, pkgs, ... }:
1+
{
2+
lib,
3+
config,
4+
pkgs,
5+
inputs,
6+
...
7+
}:
28

39
{
410
imports = [
11+
inputs.sops-nix.nixosModules.sops
512
../../modules/nftables
613
../../modules/prometheus-iperf3-exporter
714
../../modules/rollback
@@ -21,7 +28,12 @@
2128
# boot.loader.grub.enable = true;
2229
# boot.loader.grub.version = 2;
2330
# boot.loader.grub.device = "/dev/sda";
24-
boot.kernelParams = [ "console=ttyS0,115200n8" "console=tty0" "panic=1" "boot.panic_on_fail" ];
31+
boot.kernelParams = [
32+
"console=ttyS0,115200n8"
33+
"console=tty0"
34+
"panic=1"
35+
"boot.panic_on_fail"
36+
];
2537

2638
networking.hostName = "router";
2739
networking.domain = "xhain.space";
@@ -30,6 +42,9 @@
3042
networking.useNetworkd = true;
3143
services.resolved.dnssec = "false";
3244

45+
# sops.age.sshKeyPaths = [ "/etc/ssh/ssh_host_ed25519_key" ];
46+
sops.defaultSopsFile = ../../secrets/router.yaml;
47+
3348
#networking.nameservers = [
3449
# "2606:4700:4700::1111" "2001:4860:4860::8888" "2606:4700:4700::1001" "2001:4860:4860::8844"
3550
# "1.1.1.1" "1.0.0.1"

hosts/router/dhcp.nix

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
1-
{ config, pkgs, lib, inputs, ... }:
1+
{
2+
config,
3+
pkgs,
4+
lib,
5+
inputs,
6+
...
7+
}:
28

39
let
410
subnets = {
@@ -35,7 +41,7 @@ let
3541
mkKeaSubnet = name: attrs: {
3642
id = attrs.id;
3743
subnet = attrs.subnet;
38-
pools = [{ pool = attrs.dhcp_range; }];
44+
pools = [ { pool = attrs.dhcp_range; } ];
3945
ddns-qualifying-suffix = attrs.ddns_domain;
4046
option-data = [
4147
{
@@ -56,12 +62,12 @@ let
5662
}
5763
];
5864
};
59-
mkKeaDdnsDomains = name: attrs:
60-
''{
61-
"dns-servers": [{"ip-address": "127.0.0.1"}],
62-
"key-name": "rndc-key",
63-
"name": "${attrs.ddns_domain}"
64-
}'';
65+
mkKeaDdnsDomains = name: attrs: ''
66+
{
67+
"dns-servers": [{"ip-address": "127.0.0.1"}],
68+
"key-name": "rndc-key",
69+
"name": "${attrs.ddns_domain}"
70+
}'';
6571
controlSocket = "/run/kea/dhcp4.sock";
6672
in
6773
{
@@ -71,6 +77,9 @@ in
7177
};
7278
users.groups.kea = { };
7379

80+
sops.secrets.kea-ddns-key = {
81+
owner = "kea";
82+
};
7483
secrets.kea-ddns-key.owner = "kea";
7584

7685
services.kea = {
@@ -83,7 +92,12 @@ in
8392
rebind-timer = 9800;
8493

8594
interfaces-config = {
86-
interfaces = [ "voc" "intern" "hosting" "guest" ];
95+
interfaces = [
96+
"voc"
97+
"intern"
98+
"hosting"
99+
"guest"
100+
];
87101
};
88102

89103
lease-database = {
@@ -120,7 +134,7 @@ in
120134
{
121135
name = "uefi HTTP Clients";
122136
#test = "substring(option[60].hex,0,10) == 'HTTPClient' and (option[93].hex == 0x0007 or option[93].hex == 0x0010)";
123-
test = "substring(option[60].hex,0,10) == 'HTTPClient'";
137+
test = "substring(option[60].hex,0,10) == 'HTTPClient'";
124138
option-data = [
125139
{
126140
space = "dhcp4";
@@ -143,7 +157,7 @@ in
143157
hooks-libraries = [
144158
{
145159
library = "${pkgs.kea}/lib/kea/hooks/libdhcp_lease_cmds.so";
146-
parameters = {};
160+
parameters = { };
147161
}
148162
];
149163

@@ -174,7 +188,7 @@ in
174188
]
175189
},
176190
"tsig-keys": [
177-
<?include "${config.secrets.kea-ddns-key.path}"?>
191+
<?include "${config.sops.secrets.kea-ddns-key.path}"?>
178192
],
179193
# "loggers": [
180194
# {
@@ -213,7 +227,7 @@ in
213227
keaSocketPath = controlSocket;
214228
};
215229

216-
services.nginx.virtualHosts.${config.networking.hostName + "." + config.networking.domain} = {
230+
services.nginx.virtualHosts.${config.networking.hostName + "." + config.networking.domain} = {
217231
locations."/leases" = {
218232
recommendedProxySettings = true;
219233
proxyPass = "http://${config.services.kea-lease-viewer.listenAddress}:${toString config.services.kea-lease-viewer.port}/";

modules/secrets/default.nix

Lines changed: 107 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -1,97 +1,120 @@
1-
{ config, lib, pkgs, ... }:
1+
{
2+
config,
3+
lib,
4+
pkgs,
5+
...
6+
}:
27

38
with lib;
49

510
let
6-
secret-file = types.submodule ({ ... }@moduleAttrs: {
7-
options = {
8-
name = mkOption {
9-
type = types.str;
10-
default = moduleAttrs.config._module.args.name;
11+
secret-file = types.submodule (
12+
{ ... }@moduleAttrs:
13+
{
14+
options = {
15+
name = mkOption {
16+
type = types.str;
17+
default = moduleAttrs.config._module.args.name;
18+
};
19+
path = mkOption {
20+
type = types.str;
21+
readOnly = true;
22+
default = "/run/secrets-old/${removeSuffix ".gpg" (baseNameOf moduleAttrs.config.source-path)}";
23+
};
24+
mode = mkOption {
25+
type = types.str;
26+
default = "0400";
27+
};
28+
owner = mkOption {
29+
type = types.str;
30+
default = "root";
31+
};
32+
group-name = mkOption {
33+
type = types.str;
34+
default = "root";
35+
};
36+
source-path = mkOption {
37+
type = types.str;
38+
default = pkgs.copyPathToStore "${toString ../../secrets}/${config.networking.hostName}/${moduleAttrs.config.name}.gpg";
39+
};
40+
encrypted = mkOption {
41+
type = types.bool;
42+
default = true;
43+
};
44+
enable = mkOption {
45+
type = types.bool;
46+
default = true;
47+
};
1148
};
12-
path = mkOption {
13-
type = types.str;
14-
readOnly = true;
15-
default = "/run/secrets/${removeSuffix ".gpg" (baseNameOf moduleAttrs.config.source-path)}";
16-
};
17-
mode = mkOption {
18-
type = types.str;
19-
default = "0400";
20-
};
21-
owner = mkOption {
22-
type = types.str;
23-
default = "root";
24-
};
25-
group-name = mkOption {
26-
type = types.str;
27-
default = "root";
28-
};
29-
source-path = mkOption {
30-
type = types.str;
31-
default = pkgs.copyPathToStore "${toString ../../secrets}/${config.networking.hostName}/${moduleAttrs.config.name}.gpg";
32-
};
33-
encrypted = mkOption {
34-
type = types.bool;
35-
default = true;
36-
};
37-
enable = mkOption {
38-
type = types.bool;
39-
default = true;
40-
};
41-
};
42-
});
49+
}
50+
);
4351
enabledFiles = filterAttrs (n: file: file.enable) config.secrets;
4452

45-
mkDecryptSecret = file: pkgs.writeScript "decrypt-secret-${removeSuffix ".gpg" (baseNameOf file.source-path)}.sh" ''
46-
#!${pkgs.runtimeShell}
47-
set -eu pipefail
48-
if [ ! -f "${file.path}" ]; then
49-
umask 0077
50-
echo "${file.source-path} -> ${file.path}"
51-
${if file.encrypted then ''
52-
${pkgs.gnupg}/bin/gpg --decrypt ${escapeShellArg file.source-path} > ${file.path}
53-
'' else ''
54-
cat ${escapeShellArg file.source-path} > ${file.path}
55-
''}
56-
fi
57-
'';
58-
mkSetupSecret = file: pkgs.writeScript "setup-secret-${removeSuffix ".gpg" (baseNameOf file.source-path)}.sh" ''
59-
#!${pkgs.runtimeShell}
60-
set -eu pipefail
61-
chown ${escapeShellArg file.owner}:${escapeShellArg file.group-name} ${escapeShellArg file.path}
62-
chmod ${escapeShellArg file.mode} ${escapeShellArg file.path}
63-
'';
53+
mkDecryptSecret =
54+
file:
55+
pkgs.writeScript "decrypt-secret-${removeSuffix ".gpg" (baseNameOf file.source-path)}.sh" ''
56+
#!${pkgs.runtimeShell}
57+
set -eu pipefail
58+
if [ ! -f "${file.path}" ]; then
59+
umask 0077
60+
echo "${file.source-path} -> ${file.path}"
61+
${
62+
if file.encrypted then
63+
''
64+
${pkgs.gnupg}/bin/gpg --decrypt ${escapeShellArg file.source-path} > ${file.path}
65+
''
66+
else
67+
''
68+
cat ${escapeShellArg file.source-path} > ${file.path}
69+
''
70+
}
71+
fi
72+
'';
73+
mkSetupSecret =
74+
file:
75+
pkgs.writeScript "setup-secret-${removeSuffix ".gpg" (baseNameOf file.source-path)}.sh" ''
76+
#!${pkgs.runtimeShell}
77+
set -eu pipefail
78+
chown ${escapeShellArg file.owner}:${escapeShellArg file.group-name} ${escapeShellArg file.path}
79+
chmod ${escapeShellArg file.mode} ${escapeShellArg file.path}
80+
'';
6481

65-
in {
82+
in
83+
{
6684
options.secrets = mkOption {
6785
type = with types; attrsOf secret-file;
68-
default = {};
86+
default = { };
6987
};
70-
config = mkIf (enabledFiles != {}) {
71-
system.activationScripts = let
72-
files = unique (map (flip removeAttrs ["_module"]) (attrValues enabledFiles));
73-
decrypt = ''
74-
function fail() {
75-
rm $1
76-
echo "failed to decrypt $1"
77-
}
78-
echo setting up secrets...
79-
mkdir -p /run/secrets
80-
chown 0:0 /run/secrets
81-
chmod 0755 /run/secrets
82-
${concatMapStringsSep "\n" (file: ''
83-
${mkDecryptSecret file} || fail ${file.path}
84-
'') files}
85-
'';
86-
setup = ''
87-
echo setting up secrets...
88-
${concatMapStringsSep "\n" (file: ''
89-
${mkSetupSecret file} || echo "failed to set up ${file.path}"
90-
'') files}
91-
'';
92-
in {
93-
decrypt-secrets.text = "source ${pkgs.writeText "setup-secrets.sh" decrypt}";
94-
setup-secrets = stringAfter [ "users" "groups" ] "source ${pkgs.writeText "setup-secrets.sh" setup}";
95-
};
88+
config = mkIf (enabledFiles != { }) {
89+
system.activationScripts =
90+
let
91+
files = unique (map (flip removeAttrs [ "_module" ]) (attrValues enabledFiles));
92+
decrypt = ''
93+
function fail() {
94+
rm $1
95+
echo "failed to decrypt $1"
96+
}
97+
echo setting up secrets...
98+
mkdir -p /run/secrets-old
99+
chown 0:0 /run/secrets-old
100+
chmod 0755 /run/secrets-old
101+
${concatMapStringsSep "\n" (file: ''
102+
${mkDecryptSecret file} || fail ${file.path}
103+
'') files}
104+
'';
105+
setup = ''
106+
echo setting up secrets...
107+
${concatMapStringsSep "\n" (file: ''
108+
${mkSetupSecret file} || echo "failed to set up ${file.path}"
109+
'') files}
110+
'';
111+
in
112+
{
113+
decrypt-secrets.text = "source ${pkgs.writeText "setup-secrets.sh" decrypt}";
114+
setup-secrets = stringAfter [
115+
"users"
116+
"groups"
117+
] "source ${pkgs.writeText "setup-secrets.sh" setup}";
118+
};
96119
};
97120
}

0 commit comments

Comments
 (0)