diff options
Diffstat (limited to 'modules')
-rw-r--r-- | modules/borgbackup/btrfs-snapshots.nix | 52 | ||||
-rw-r--r-- | modules/borgbackup/default.nix | 206 | ||||
-rw-r--r-- | modules/borgbackup/lvm-snapshots.nix | 133 | ||||
-rw-r--r-- | modules/borgbackup/repokeys/borg_munin__borg.yaml | 33 | ||||
-rw-r--r-- | modules/kill-user.nix | 13 | ||||
-rw-r--r-- | modules/tinc-networkmanager.nix | 36 | ||||
-rw-r--r-- | modules/uucp.nix | 391 | ||||
-rw-r--r-- | modules/yggdrasil/default.nix | 49 | ||||
-rw-r--r-- | modules/yggdrasil/hosts/sif/default.nix | 13 | ||||
-rw-r--r-- | modules/yggdrasil/hosts/sif/private-keys.yaml | 34 | ||||
-rw-r--r-- | modules/yggdrasil/hosts/ymir.nix | 19 |
11 files changed, 979 insertions, 0 deletions
diff --git a/modules/borgbackup/btrfs-snapshots.nix b/modules/borgbackup/btrfs-snapshots.nix new file mode 100644 index 00000000..96d2b2ba --- /dev/null +++ b/modules/borgbackup/btrfs-snapshots.nix | |||
@@ -0,0 +1,52 @@ | |||
1 | { config, lib, pkgs, ... }: | ||
2 | |||
3 | with lib; | ||
4 | |||
5 | let | ||
6 | cfg = config.services.btrfs-snapshots; | ||
7 | |||
8 | snapshotMount = str: "${str}${cfg.mountSuffix}"; | ||
9 | in { | ||
10 | options = { | ||
11 | |||
12 | services.btrfs-snapshots = { | ||
13 | enable = mkEnableOption "a systemd unit for btrfs snapshots"; | ||
14 | |||
15 | mountSuffix = mkOption { | ||
16 | type = types.str; | ||
17 | default = ".snapshot"; | ||
18 | }; | ||
19 | |||
20 | readOnly = mkOption { | ||
21 | type = types.bool; | ||
22 | default = true; | ||
23 | }; | ||
24 | |||
25 | persist = mkOption { | ||
26 | type = types.bool; | ||
27 | default = false; | ||
28 | }; | ||
29 | }; | ||
30 | |||
31 | }; | ||
32 | |||
33 | |||
34 | config = mkIf cfg.enable { | ||
35 | systemd.services."btrfs-snapshot@" = { | ||
36 | enable = true; | ||
37 | |||
38 | unitConfig = { | ||
39 | StopWhenUnneeded = !cfg.persist; | ||
40 | }; | ||
41 | |||
42 | serviceConfig = with pkgs; { | ||
43 | Type = "oneshot"; | ||
44 | ExecStartPre = "-${btrfs-progs}/bin/btrfs subvolume delete -c ${snapshotMount "%f"}"; | ||
45 | ExecStart = "${btrfs-progs}/bin/btrfs subvolume snapshot ${optionalString cfg.readOnly "-r"} %f ${snapshotMount "%f"}"; | ||
46 | RemainAfterExit = true; | ||
47 | ExecStop = "${btrfs-progs}/bin/btrfs subvolume delete -c ${snapshotMount "%f"}"; | ||
48 | }; | ||
49 | }; | ||
50 | |||
51 | }; | ||
52 | } | ||
diff --git a/modules/borgbackup/default.nix b/modules/borgbackup/default.nix new file mode 100644 index 00000000..a0419d0e --- /dev/null +++ b/modules/borgbackup/default.nix | |||
@@ -0,0 +1,206 @@ | |||
1 | { config, lib, utils, pkgs, ... }: | ||
2 | |||
3 | with utils; | ||
4 | with lib; | ||
5 | |||
6 | let | ||
7 | cfg = config.services.borgbackup; | ||
8 | |||
9 | lvmPath = { | ||
10 | options = { | ||
11 | LV = mkOption { | ||
12 | type = types.str; | ||
13 | }; | ||
14 | VG = mkOption { | ||
15 | type = types.str; | ||
16 | }; | ||
17 | }; | ||
18 | }; | ||
19 | |||
20 | pathType = if cfg.snapshots == "lvm" then types.submodule lvmPath else types.path; | ||
21 | |||
22 | systemdPath = path: escapeSystemdPath (if cfg.snapshots == "lvm" then "${path.VG}-${path.LV}" else path); | ||
23 | |||
24 | withSuffix = path: path + (if cfg.snapshots == "btrfs" then config.services.btrfs-snapshots.mountSuffix else config.services.lvm-snapshots.mountSuffix); | ||
25 | |||
26 | mountPoint = if cfg.snapshots == "lvm" then config.services.lvm-snapshots.mountPoint else ""; | ||
27 | |||
28 | targetOptions = { | ||
29 | options = { | ||
30 | repo = mkOption { | ||
31 | type = types.str; | ||
32 | }; | ||
33 | |||
34 | paths = mkOption { | ||
35 | type = types.listOf pathType; | ||
36 | default = []; | ||
37 | }; | ||
38 | |||
39 | prune = mkOption { | ||
40 | type = types.attrsOf (types.listOf types.str); | ||
41 | default = {}; | ||
42 | }; | ||
43 | |||
44 | interval = mkOption { | ||
45 | type = types.str; | ||
46 | default = "6h"; | ||
47 | }; | ||
48 | |||
49 | jitter = mkOption { | ||
50 | type = with types; nullOr str; | ||
51 | default = "6h"; | ||
52 | }; | ||
53 | |||
54 | lock = mkOption { | ||
55 | type = types.nullOr types.str; | ||
56 | default = "backup"; | ||
57 | }; | ||
58 | |||
59 | network = mkOption { | ||
60 | type = types.bool; | ||
61 | default = true; | ||
62 | }; | ||
63 | |||
64 | lockWait = mkOption { | ||
65 | type = types.int; | ||
66 | default = 600; | ||
67 | }; | ||
68 | |||
69 | keyFile = mkOption { | ||
70 | type = types.nullOr types.path; | ||
71 | default = null; | ||
72 | }; | ||
73 | }; | ||
74 | }; | ||
75 | in { | ||
76 | disabledModules = [ "services/backup/borgbackup.nix" ]; | ||
77 | |||
78 | options = { | ||
79 | services.borgbackup = { | ||
80 | snapshots = mkOption { | ||
81 | type = types.nullOr (types.enum ["btrfs" "lvm"]); | ||
82 | default = null; | ||
83 | }; | ||
84 | |||
85 | targets = mkOption { | ||
86 | type = types.attrsOf (types.submodule targetOptions); | ||
87 | default = {}; | ||
88 | }; | ||
89 | |||
90 | prefix = mkOption { | ||
91 | type = types.str; | ||
92 | }; | ||
93 | }; | ||
94 | }; | ||
95 | |||
96 | imports = | ||
97 | [ ./lvm-snapshots.nix | ||
98 | ./btrfs-snapshots.nix | ||
99 | ]; | ||
100 | |||
101 | config = mkIf (any (t: t.paths != []) (attrValues cfg.targets)) { | ||
102 | services.btrfs-snapshots.enable = mkIf (cfg.snapshots == "btrfs") true; | ||
103 | |||
104 | services.lvm-snapshots.snapshots = mkIf (cfg.snapshots == "lvm") (listToAttrs (map (path: nameValuePair (path.VG + "-" + path.LV) { | ||
105 | inherit (path) LV VG; | ||
106 | mountName = withSuffix (path.VG + "-" + path.LV); | ||
107 | }) (unique (flatten (mapAttrsToList (target: tCfg: tCfg.paths) cfg.targets))))); | ||
108 | |||
109 | systemd.targets."timers-borg" = { | ||
110 | wantedBy = [ "timers.target" ]; | ||
111 | }; | ||
112 | |||
113 | systemd.slices."system-borgbackup" = {}; | ||
114 | |||
115 | systemd.timers = (listToAttrs (map ({ target, path, tCfg }: nameValuePair "borgbackup-${target}@${systemdPath path}" { | ||
116 | requiredBy = [ "timers-borg.target" ]; | ||
117 | |||
118 | timerConfig = { | ||
119 | Persistent = false; | ||
120 | OnBootSec = tCfg.interval; | ||
121 | OnUnitActiveSec = tCfg.interval; | ||
122 | RandomizedDelaySec = mkIf (tCfg.jitter != null) tCfg.jitter; | ||
123 | }; | ||
124 | }) (flatten (mapAttrsToList (target: tCfg: map (path: { inherit target path tCfg; }) tCfg.paths) cfg.targets)))) // (mapAttrs' (target: tCfg: nameValuePair "borgbackup-prune-${target}" { | ||
125 | enable = tCfg.prune != {}; | ||
126 | |||
127 | requiredBy = [ "timers-borg.target" ]; | ||
128 | |||
129 | timerConfig = { | ||
130 | Persistent = false; | ||
131 | OnBootSec = tCfg.interval; | ||
132 | OnUnitActiveSec = tCfg.interval; | ||
133 | RandomizedDelaySec = mkIf (tCfg.jitter != null) tCfg.jitter; | ||
134 | }; | ||
135 | }) cfg.targets); | ||
136 | |||
137 | systemd.services = (mapAttrs' (target: tCfg: nameValuePair "borgbackup-${target}@" (let | ||
138 | deps = flatten [ | ||
139 | (optional (cfg.snapshots == "btrfs") "btrfs-snapshot@%i.service") | ||
140 | (optional tCfg.network "network-online.target") | ||
141 | ]; | ||
142 | in { | ||
143 | bindsTo = deps; | ||
144 | after = deps; | ||
145 | |||
146 | path = with pkgs; [borgbackup] ++ optional (tCfg.lock != null) utillinux; | ||
147 | |||
148 | script = let | ||
149 | borgCmd = '' | ||
150 | borg create \ | ||
151 | --lock-wait ${toString tCfg.lockWait} \ | ||
152 | --stats \ | ||
153 | --list \ | ||
154 | --filter 'AME' \ | ||
155 | --exclude-caches \ | ||
156 | --keep-exclude-tags \ | ||
157 | --patterns-from .backup-${target} \ | ||
158 | --one-file-system \ | ||
159 | --compression auto,lzma \ | ||
160 | ${tCfg.repo}::${cfg.prefix}$1-{utcnow} | ||
161 | ''; | ||
162 | in if tCfg.lock == null then borgCmd else "flock -xo /var/lock/${tCfg.lock} ${borgCmd}"; | ||
163 | scriptArgs = if cfg.snapshots == "lvm" then "%I" else "%i"; | ||
164 | |||
165 | unitConfig = { | ||
166 | AssertPathIsDirectory = mkIf (tCfg.lock != null) "/var/lock"; | ||
167 | DefaultDependencies = false; | ||
168 | RequiresMountsFor = mkIf (cfg.snapshots == "lvm") [ "${mountPoint}/${withSuffix "%I"}" ]; | ||
169 | }; | ||
170 | |||
171 | serviceConfig = { | ||
172 | Type = "oneshot"; | ||
173 | WorkingDirectory = if (cfg.snapshots == null) then "%I" else (if (cfg.snapshots == "lvm") then "${mountPoint}/${withSuffix "%I"}" else "${withSuffix "%f"}"); | ||
174 | Nice = 15; | ||
175 | IOSchedulingClass = 2; | ||
176 | IOSchedulingPriority = 7; | ||
177 | SuccessExitStatus = [1 2]; | ||
178 | Slice = "system-borgbackup.slice"; | ||
179 | Environment = lib.mkIf (tCfg.keyFile != null) "BORG_KEY_FILE=${tCfg.keyFile}"; | ||
180 | }; | ||
181 | })) cfg.targets) // (mapAttrs' (target: tCfg: nameValuePair "borgbackup-prune-${target}" { | ||
182 | enable = tCfg.prune != {}; | ||
183 | |||
184 | bindsTo = ["network-online.target"]; | ||
185 | after = ["network-online.target"]; | ||
186 | |||
187 | path = with pkgs; [borgbackup]; | ||
188 | |||
189 | script = concatStringsSep "\n" (mapAttrsToList (path: args: '' | ||
190 | borg prune \ | ||
191 | --lock-wait ${toString tCfg.lockWait} \ | ||
192 | --list \ | ||
193 | --stats \ | ||
194 | --prefix ${escapeShellArg "${cfg.prefix}${path}"} \ | ||
195 | ${escapeShellArgs args} \ | ||
196 | ${tCfg.repo} | ||
197 | '') tCfg.prune); | ||
198 | |||
199 | serviceConfig = { | ||
200 | Type = "oneshot"; | ||
201 | Slice = "system-borgbackup.slice"; | ||
202 | Environment = lib.mkIf (tCfg.keyFile != null) "BORG_KEY_FILE=${tCfg.keyFile}"; | ||
203 | }; | ||
204 | }) cfg.targets); | ||
205 | }; | ||
206 | } | ||
diff --git a/modules/borgbackup/lvm-snapshots.nix b/modules/borgbackup/lvm-snapshots.nix new file mode 100644 index 00000000..9b2a6562 --- /dev/null +++ b/modules/borgbackup/lvm-snapshots.nix | |||
@@ -0,0 +1,133 @@ | |||
1 | { config, lib, utils, pkgs, ... }: | ||
2 | |||
3 | with utils; | ||
4 | with lib; | ||
5 | |||
6 | let | ||
7 | cfg = config.services.lvm-snapshots; | ||
8 | |||
9 | snapshotMount = name: "${cfg.mountPoint}/${if isNull cfg.snapshots."${name}".mountName then name else cfg.snapshots."${name}".mountName}"; | ||
10 | snapshotName = name: "${name}-${cfg.mountSuffix}"; | ||
11 | |||
12 | snapshotConfig = { | ||
13 | options = { | ||
14 | LV = mkOption { | ||
15 | type = types.str; | ||
16 | }; | ||
17 | |||
18 | VG = mkOption { | ||
19 | type = types.str; | ||
20 | }; | ||
21 | |||
22 | mountName = mkOption { | ||
23 | type = types.nullOr types.str; | ||
24 | default = null; | ||
25 | }; | ||
26 | |||
27 | cowSize = mkOption { | ||
28 | type = types.str; | ||
29 | default = "-l20%ORIGIN"; | ||
30 | }; | ||
31 | |||
32 | readOnly = mkOption { | ||
33 | type = types.bool; | ||
34 | default = true; | ||
35 | }; | ||
36 | |||
37 | persist = mkOption { | ||
38 | type = types.bool; | ||
39 | default = false; | ||
40 | }; | ||
41 | }; | ||
42 | }; | ||
43 | in { | ||
44 | options = { | ||
45 | |||
46 | services.lvm-snapshots = { | ||
47 | snapshots = mkOption { | ||
48 | type = types.attrsOf (types.submodule snapshotConfig); | ||
49 | default = {}; | ||
50 | }; | ||
51 | |||
52 | mountPoint = mkOption { | ||
53 | type = types.path; | ||
54 | default = "/mnt"; | ||
55 | }; | ||
56 | |||
57 | mountSuffix = mkOption { | ||
58 | type = types.str; | ||
59 | default = "-snapshot"; | ||
60 | }; | ||
61 | }; | ||
62 | }; | ||
63 | |||
64 | |||
65 | config = mkIf (cfg != {}) { | ||
66 | |||
67 | boot.kernelModules = [ "dm_snapshot" ]; | ||
68 | |||
69 | # system.activationScripts = mapAttrs' (name: scfg: nameValuePair ("lvm-mountpoint" + name) '' | ||
70 | # mkdir -p ${snapshotMount name} | ||
71 | # '') cfg.snapshots; | ||
72 | |||
73 | systemd.services = mapAttrs' (name: scfg: nameValuePair ("lvm-snapshot@" + escapeSystemdPath name) { | ||
74 | enable = true; | ||
75 | |||
76 | description = "LVM-snapshot of ${scfg.VG}/${scfg.LV}"; | ||
77 | |||
78 | bindsTo = ["${escapeSystemdPath "/dev/${scfg.VG}/${scfg.LV}"}.device"]; | ||
79 | after = ["${escapeSystemdPath "/dev/${scfg.VG}/${scfg.LV}"}.device"]; | ||
80 | |||
81 | unitConfig = { | ||
82 | StopWhenUnneeded = !scfg.persist; | ||
83 | AssertPathIsDirectory = "/var/lock"; | ||
84 | }; | ||
85 | |||
86 | path = with pkgs; [ devicemapper utillinux ]; | ||
87 | |||
88 | script = '' | ||
89 | ( | ||
90 | flock -xn -E 4 9 | ||
91 | if [[ "$?" -ne 0 ]]; then | ||
92 | exit $? | ||
93 | fi | ||
94 | |||
95 | lvcreate -s ${scfg.cowSize} --name ${snapshotName name} ${scfg.VG}/${scfg.LV} | ||
96 | |||
97 | sleep infinity & | ||
98 | ) 9>/var/lock/lvm-snapshot.${scfg.VG} | ||
99 | ''; | ||
100 | |||
101 | preStart = '' | ||
102 | lvremove -f ${scfg.VG}/${snapshotName name} | ||
103 | ''; | ||
104 | |||
105 | preStop = '' | ||
106 | lvremove -f ${scfg.VG}/${snapshotName name} | ||
107 | ''; | ||
108 | |||
109 | serviceConfig = with pkgs; { | ||
110 | Type = "forking"; | ||
111 | RestartForceExitStatus = [ "4" ]; | ||
112 | RestartSec = "5min"; | ||
113 | }; | ||
114 | }) cfg.snapshots; | ||
115 | |||
116 | systemd.mounts = mapAttrsToList (name: scfg: { | ||
117 | enable = true; | ||
118 | |||
119 | unitConfig = { | ||
120 | # AssertPathIsDirectory = snapshotMount name; | ||
121 | StopWhenUnneeded = !scfg.persist; | ||
122 | }; | ||
123 | |||
124 | bindsTo = [ ("lvm-snapshot@" + escapeSystemdPath name + ".service") ]; | ||
125 | after = [ ("lvm-snapshot@" + escapeSystemdPath name + ".service") ]; | ||
126 | |||
127 | options = concatStringsSep "," ([ "noauto" ] ++ optional scfg.readOnly "ro"); | ||
128 | |||
129 | where = snapshotMount name; | ||
130 | what = "/dev/" + scfg.VG + "/" + snapshotName name; | ||
131 | }) cfg.snapshots; | ||
132 | }; | ||
133 | } | ||
diff --git a/modules/borgbackup/repokeys/borg_munin__borg.yaml b/modules/borgbackup/repokeys/borg_munin__borg.yaml new file mode 100644 index 00000000..f302fe06 --- /dev/null +++ b/modules/borgbackup/repokeys/borg_munin__borg.yaml | |||
@@ -0,0 +1,33 @@ | |||
1 | key: ENC[AES256_GCM,data:mxh+Jtxx+HyD246yPwo0vy7vSTz3IG8VmfbxPMwqJRreh9ZwkGnH5aCTDOvWOHIrkmzaRMF3oCi1P8D29+abMUZdt0MuJ3UE6iL8+SXlflR+WACgALM2Df+x9B3BwQM3yeoCiWG+ebr0iQPHM3jqqpkjoRv1CcythxG2deZueur9lzgC2CwG1g3O8Prnl9z0JQGOa+gjic8Zwfn38B1BECeNPrbjzICGBOrSbN/6EnfBDygI2QzseamzK2I6R6jT+QxHvkl+Zi1m2TRB+4o82VgTjPhIReJyT7PrlDnUyrKObhCOlb3v+LiSdp16IPIDVs968kyDzgyi7QPOpGr+5tutWCZrau5xhPDrONKByl/0nVVwEZfRIYATvEXtn5okJru/mglcpeD0I7AtLt+Vfv9CB9pQczvkHo0cDtgudQDf9ADt/nkmqHugm5VfMg9m9aGbKqzXt6pPOMsXSbS43K7wgDaduLZ/PW4Ookx9gTNLtJHnZ64GBorOv4QSrZIZF8pE1FsQdUhmp/YzVhaNBnjCr+Jh77sYjoOwzF77Xy+VP2C/yVIf492P+FcgkSj6XhYYqHffpFW9l/xmUvyQF5gjj2k5T21UvgChhI1HeLPzQ7W9+xuGSMtg58aD/VPe1loCy8zLITNl71bneararRS5vItoZyzMdmIRMLAZD1klPmDNe1yufTpubOXzNYbWUqFUZtwH/mDL5GRZBD9dqs2b3F26c1CUyw==,iv:NJBHesKSZ1zuKk8qHnYKqIwMnFkH+rkQD1bam5XpLXU=,tag:EiYbIFY/r/eTSTJIhYV+GA==,type:str] | ||
2 | sops: | ||
3 | kms: [] | ||
4 | gcp_kms: [] | ||
5 | azure_kv: [] | ||
6 | hc_vault: [] | ||
7 | lastmodified: '2021-01-02T20:38:48Z' | ||
8 | mac: ENC[AES256_GCM,data:3rkFTOk3r2dx3hOqu1u7XIIibTDfqNlRcWY9X2N/LFa/BKojgDt5tcpbphV4HqWvl8nS+fPcVrIElJfQ/QGFEOx68G95BhByntT9+JhSbHJt73dGnCSroZCw5QefdydREGvA5n00Vo9yT9IMvQsQbmpRzo6hcrSSUvagZqmZckA=,iv:F/HllDzyxgulIWZbfz9bFKR+SFg4PoaUYZ5N5hfIzw0=,tag:h2NXmvj/thhBg1rIkwdXXA==,type:str] | ||
9 | pgp: | ||
10 | - created_at: '2021-01-02T20:38:09Z' | ||
11 | enc: | | ||
12 | -----BEGIN PGP MESSAGE----- | ||
13 | |||
14 | hF4Dgwm4NZSaLAcSAQdAwmvyXlr9MyfPfLgkfQkoktKBV2WA2xhZrGL7NeeGfhAw | ||
15 | REk+clJ9WgiJ0iceRAONPnEjeiK0J6Fsj+5Ulq8flFGkoj5Pta0pm/9fudKmcPdC | ||
16 | 0l4BF0G5LSpG1EmY+LmVdSdas16rWgthnojoXPvbbHG6jZs3aDETshdiN8Bdlqsf | ||
17 | aVhq2LYzscnYezNcdernR4uojtiFny8qcmdF3tFacr+mkgfgIQr0W9yWFhDH15gm | ||
18 | =4TwU | ||
19 | -----END PGP MESSAGE----- | ||
20 | fp: F1AF20B9511B63F681A14E8D51AEFBCD1DEF68F8 | ||
21 | - created_at: '2021-01-02T20:38:09Z' | ||
22 | enc: | | ||
23 | -----BEGIN PGP MESSAGE----- | ||
24 | |||
25 | hF4DXxoViZlp6dISAQdAruPXj9IsllEN7R5jk4gF7bW0ZirhvX7qsu22/6HbSw8w | ||
26 | 66RwN3WGjYO1CcVbHKuLqVVaUBCnrR/4XHN0JYUaqjubrSZBTWFKTBFsKSTT0LZq | ||
27 | 0l4BKcsXrbGpYC5+yQvg0RHJ7LplxpKOmqMY8KGckvGnVf2xg7k6wuWQREFzqwt+ | ||
28 | lOa3x+xFy9c0JwE8AafyKjb/cgqJiMb96lhsH57BpXJa2E39ImQbXqzDzdx2jEUt | ||
29 | =3rxi | ||
30 | -----END PGP MESSAGE----- | ||
31 | fp: 30D3453B8CD02FE2A3E7C78C0FB536FB87AE8F51 | ||
32 | unencrypted_suffix: _unencrypted | ||
33 | version: 3.6.1 | ||
diff --git a/modules/kill-user.nix b/modules/kill-user.nix new file mode 100644 index 00000000..dd897b36 --- /dev/null +++ b/modules/kill-user.nix | |||
@@ -0,0 +1,13 @@ | |||
1 | { lib, pkgs, config, ... }: | ||
2 | { | ||
3 | options = { | ||
4 | systemd.kill-user.enable = lib.mkEnableOption "Systemd kill-user@ services"; | ||
5 | }; | ||
6 | |||
7 | config.systemd.services."kill-user@" = lib.mkIf config.systemd.kill-user.enable { | ||
8 | serviceConfig = { | ||
9 | Type = "oneshot"; | ||
10 | ExecStart = "${pkgs.systemd}/bin/loginctl kill-user %I"; | ||
11 | }; | ||
12 | }; | ||
13 | } | ||
diff --git a/modules/tinc-networkmanager.nix b/modules/tinc-networkmanager.nix new file mode 100644 index 00000000..ff03abd2 --- /dev/null +++ b/modules/tinc-networkmanager.nix | |||
@@ -0,0 +1,36 @@ | |||
1 | { lib, config, pkgs, ... }: | ||
2 | let | ||
3 | cfg = config.services.tinc; | ||
4 | in { | ||
5 | options = { | ||
6 | services.tinc.networks = lib.mkOption { | ||
7 | type = lib.types.attrsOf (lib.types.submodule { | ||
8 | options.nmDispatch = lib.mkOption { | ||
9 | type = lib.types.bool; | ||
10 | default = config.networking.networkmanager.enable; | ||
11 | description = '' | ||
12 | Install a network-manager dispatcher script to automatically | ||
13 | connect to all remotes when networking is available | ||
14 | ''; | ||
15 | }; | ||
16 | }); | ||
17 | }; | ||
18 | }; | ||
19 | |||
20 | config = { | ||
21 | networking.networkmanager.dispatcherScripts = lib.concatLists (lib.flip lib.mapAttrsToList cfg.networks (network: data: lib.optional data.nmDispatch { | ||
22 | type = "basic"; | ||
23 | source = pkgs.writeScript "connect-${network}.sh" '' | ||
24 | #!${pkgs.stdenv.shell} | ||
25 | |||
26 | shopt -s extglob | ||
27 | |||
28 | case "''${2}" in | ||
29 | (?(vpn-)up) | ||
30 | ${data.package}/bin/tinc -n ${network} --pidfile /run/tinc.${network}.pid --batch retry | ||
31 | ;; | ||
32 | esac | ||
33 | ''; | ||
34 | })); | ||
35 | }; | ||
36 | } | ||
diff --git a/modules/uucp.nix b/modules/uucp.nix new file mode 100644 index 00000000..8d8ac1a2 --- /dev/null +++ b/modules/uucp.nix | |||
@@ -0,0 +1,391 @@ | |||
1 | { flake, config, lib, pkgs, ... }: | ||
2 | |||
3 | with lib; | ||
4 | |||
5 | let | ||
6 | portSpec = name: node: concatStringsSep "\n" (map (port: '' | ||
7 | port ${name}.${port} | ||
8 | type pipe | ||
9 | protocol ${node.protocols} | ||
10 | reliable true | ||
11 | command ${pkgs.openssh}/bin/ssh -x -o batchmode=yes ${name}.${port} | ||
12 | '') node.hostnames); | ||
13 | sysSpec = name: node: '' | ||
14 | system ${name} | ||
15 | time any | ||
16 | chat-seven-bit false | ||
17 | chat . "" | ||
18 | protocol ${node.protocols} | ||
19 | command-path ${concatStringsSep " " cfg.commandPath} | ||
20 | commands ${concatStringsSep " " node.commands} | ||
21 | ${concatStringsSep "\nalternate\n" (map (port: '' | ||
22 | port ${name}.${port} | ||
23 | '') node.hostnames)} | ||
24 | ''; | ||
25 | sshConfig = name: node: concatStringsSep "\n" (map (port: '' | ||
26 | Host ${name}.${port} | ||
27 | Hostname ${port} | ||
28 | IdentitiesOnly Yes | ||
29 | IdentityFile ${cfg.sshKeyDir}/${name} | ||
30 | '') node.hostnames); | ||
31 | sshKeyGen = name: node: '' | ||
32 | if [[ ! -e ${cfg.sshKeyDir}/${name} ]]; then | ||
33 | ${pkgs.openssh}/bin/ssh-keygen ${escapeShellArgs node.generateKey} -f ${cfg.sshKeyDir}/${name} | ||
34 | fi | ||
35 | ''; | ||
36 | restrictKey = key: '' | ||
37 | restrict,command="${chat}" ${key} | ||
38 | ''; | ||
39 | chat = pkgs.writeScript "chat" '' | ||
40 | #!${pkgs.stdenv.shell} | ||
41 | |||
42 | echo . | ||
43 | exec ${config.security.wrapperDir}/uucico | ||
44 | ''; | ||
45 | |||
46 | nodeCfg = { | ||
47 | options = { | ||
48 | commands = mkOption { | ||
49 | type = types.listOf types.str; | ||
50 | default = cfg.defaultCommands; | ||
51 | description = "Commands to allow for this remote"; | ||
52 | }; | ||
53 | |||
54 | protocols = mkOption { | ||
55 | type = types.separatedString ""; | ||
56 | default = cfg.defaultProtocols; | ||
57 | description = "UUCP protocols to use for this remote"; | ||
58 | }; | ||
59 | |||
60 | publicKeys = mkOption { | ||
61 | type = types.listOf types.str; | ||
62 | default = []; | ||
63 | description = "SSH client public keys for this node"; | ||
64 | }; | ||
65 | |||
66 | generateKey = mkOption { | ||
67 | type = types.listOf types.str; | ||
68 | default = [ "-t" "ed25519" "-N" "" ]; | ||
69 | description = "Arguments to pass to `ssh-keygen` to generate a keypair for communication with this host"; | ||
70 | }; | ||
71 | |||
72 | hostnames = mkOption { | ||
73 | type = types.listOf types.str; | ||
74 | default = []; | ||
75 | description = "Hostnames to try in order when connecting"; | ||
76 | }; | ||
77 | }; | ||
78 | }; | ||
79 | |||
80 | cfg = config.services.uucp; | ||
81 | in { | ||
82 | options = { | ||
83 | services.uucp = { | ||
84 | enable = mkOption { | ||
85 | type = types.bool; | ||
86 | default = false; | ||
87 | description = '' | ||
88 | If enabled we set up an account accesible via uucp over ssh | ||
89 | ''; | ||
90 | }; | ||
91 | |||
92 | nodeName = mkOption { | ||
93 | type = types.str; | ||
94 | default = "nixos"; | ||
95 | description = "uucp node name"; | ||
96 | }; | ||
97 | |||
98 | sshUser = mkOption { | ||
99 | type = types.attrs; | ||
100 | default = {}; | ||
101 | description = "Overrides for the local uucp linux-user"; | ||
102 | }; | ||
103 | |||
104 | extraSSHConfig = mkOption { | ||
105 | type = types.str; | ||
106 | default = ""; | ||
107 | description = "Extra SSH config"; | ||
108 | }; | ||
109 | |||
110 | remoteNodes = mkOption { | ||
111 | type = types.attrsOf (types.submodule nodeCfg); | ||
112 | default = {}; | ||
113 | description = '' | ||
114 | Ports to set up | ||
115 | Names will probably need to be configured in sshConfig | ||
116 | ''; | ||
117 | }; | ||
118 | |||
119 | commandPath = mkOption { | ||
120 | type = types.listOf types.path; | ||
121 | default = [ "${pkgs.rmail}/bin" ]; | ||
122 | description = '' | ||
123 | Command search path for all systems | ||
124 | ''; | ||
125 | }; | ||
126 | |||
127 | defaultCommands = mkOption { | ||
128 | type = types.listOf types.str; | ||
129 | default = ["rmail"]; | ||
130 | description = "Commands allowed for remotes without explicit override"; | ||
131 | }; | ||
132 | |||
133 | defaultProtocols = mkOption { | ||
134 | type = types.separatedString ""; | ||
135 | default = "te"; | ||
136 | description = "UUCP protocol to use within ssh unless overriden"; | ||
137 | }; | ||
138 | |||
139 | incomingProtocols = mkOption { | ||
140 | type = types.separatedString ""; | ||
141 | default = "te"; | ||
142 | description = "UUCP protocols to use when called"; | ||
143 | }; | ||
144 | |||
145 | homeDir = mkOption { | ||
146 | type = types.path; | ||
147 | default = "/var/uucp"; | ||
148 | description = "Home of the uucp user"; | ||
149 | }; | ||
150 | |||
151 | sshKeyDir = mkOption { | ||
152 | type = types.path; | ||
153 | default = "${cfg.homeDir}/.ssh/"; | ||
154 | description = "Directory to store ssh keypairs"; | ||
155 | }; | ||
156 | |||
157 | spoolDir = mkOption { | ||
158 | type = types.path; | ||
159 | default = "/var/spool/uucp"; | ||
160 | description = "Spool directory"; | ||
161 | }; | ||
162 | |||
163 | lockDir = mkOption { | ||
164 | type = types.path; | ||
165 | default = "/var/spool/uucp"; | ||
166 | description = "Lock directory"; | ||
167 | }; | ||
168 | |||
169 | pubDir = mkOption { | ||
170 | type = types.path; | ||
171 | default = "/var/spool/uucppublic"; | ||
172 | description = "Public directory"; | ||
173 | }; | ||
174 | |||
175 | logFile = mkOption { | ||
176 | type = types.path; | ||
177 | default = "/var/log/uucp"; | ||
178 | description = "Log file"; | ||
179 | }; | ||
180 | |||
181 | statFile = mkOption { | ||
182 | type = types.path; | ||
183 | default = "/var/log/uucp.stat"; | ||
184 | description = "Statistics file"; | ||
185 | }; | ||
186 | |||
187 | debugFile = mkOption { | ||
188 | type = types.path; | ||
189 | default = "/var/log/uucp.debug"; | ||
190 | description = "Debug file"; | ||
191 | }; | ||
192 | |||
193 | interval = mkOption { | ||
194 | type = types.nullOr types.str; | ||
195 | default = "1h"; | ||
196 | description = '' | ||
197 | Specification of when to run `uucico' in format used by systemd timers | ||
198 | The default is to do so every hour | ||
199 | ''; | ||
200 | }; | ||
201 | |||
202 | nmDispatch = mkOption { | ||
203 | type = types.bool; | ||
204 | default = config.networking.networkmanager.enable; | ||
205 | description = '' | ||
206 | Install a network-manager dispatcher script to automatically | ||
207 | call all remotes when networking is available | ||
208 | ''; | ||
209 | }; | ||
210 | |||
211 | extraConfig = mkOption { | ||
212 | type = types.lines; | ||
213 | default = '' | ||
214 | run-uuxqt 1 | ||
215 | ''; | ||
216 | description = "Extra configuration to append verbatim to `/etc/uucp/config'"; | ||
217 | }; | ||
218 | |||
219 | extraSys = mkOption { | ||
220 | type = types.lines; | ||
221 | default = '' | ||
222 | protocol-parameter g packet-size 4096 | ||
223 | ''; | ||
224 | description = "Extra configuration to prepend verbatim to `/etc/uucp/sys`"; | ||
225 | }; | ||
226 | }; | ||
227 | }; | ||
228 | |||
229 | config = mkIf cfg.enable { | ||
230 | environment.etc."uucp/config" = { | ||
231 | text = '' | ||
232 | hostname ${cfg.nodeName} | ||
233 | |||
234 | spool ${cfg.spoolDir} | ||
235 | lockdir ${cfg.lockDir} | ||
236 | pubdir ${cfg.pubDir} | ||
237 | logfile ${cfg.logFile} | ||
238 | statfile ${cfg.statFile} | ||
239 | debugfile ${cfg.debugFile} | ||
240 | |||
241 | ${cfg.extraConfig} | ||
242 | ''; | ||
243 | }; | ||
244 | |||
245 | users.users."uucp" = { | ||
246 | name = "uucp"; | ||
247 | isSystemUser = true; | ||
248 | isNormalUser = false; | ||
249 | createHome = true; | ||
250 | home = cfg.homeDir; | ||
251 | description = "User for uucp over ssh"; | ||
252 | useDefaultShell = true; | ||
253 | openssh.authorizedKeys.keys = map restrictKey (concatLists (mapAttrsToList (name: node: node.publicKeys) cfg.remoteNodes)); | ||
254 | } // cfg.sshUser; | ||
255 | |||
256 | system.activationScripts."uucp-sshconfig" = '' | ||
257 | mkdir -p ${config.users.users."uucp".home}/.ssh | ||
258 | chown ${config.users.users."uucp".name}:${config.users.users."uucp".group} ${config.users.users."uucp".home}/.ssh | ||
259 | chmod 700 ${config.users.users."uucp".home}/.ssh | ||
260 | ln -fs ${builtins.toFile "ssh-config" '' | ||
261 | ${concatStringsSep "\n" (mapAttrsToList sshConfig cfg.remoteNodes)} | ||
262 | |||
263 | ${cfg.extraSSHConfig} | ||
264 | ''} ${config.users.users."uucp".home}/.ssh/config | ||
265 | |||
266 | mkdir -p ${cfg.sshKeyDir} | ||
267 | chown ${config.users.users."uucp".name}:${config.users.users."uucp".group} ${cfg.sshKeyDir} | ||
268 | chmod 700 ${cfg.sshKeyDir} | ||
269 | |||
270 | ${concatStringsSep "\n" (mapAttrsToList sshKeyGen cfg.remoteNodes)} | ||
271 | ''; | ||
272 | |||
273 | system.activationScripts."uucp-logs" = '' | ||
274 | touch ${cfg.logFile} | ||
275 | chown ${config.users.users."uucp".name}:${config.users.users."uucp".group} ${cfg.logFile} | ||
276 | chmod 644 ${cfg.logFile} | ||
277 | touch ${cfg.statFile} | ||
278 | chown ${config.users.users."uucp".name}:${config.users.users."uucp".group} ${cfg.statFile} | ||
279 | chmod 644 ${cfg.statFile} | ||
280 | touch ${cfg.debugFile} | ||
281 | chown ${config.users.users."uucp".name}:${config.users.users."uucp".group} ${cfg.debugFile} | ||
282 | chmod 644 ${cfg.debugFile} | ||
283 | ''; | ||
284 | |||
285 | environment.etc."uucp/port" = { | ||
286 | text = '' | ||
287 | port ssh | ||
288 | type stdin | ||
289 | protocol ${cfg.incomingProtocols} | ||
290 | '' + concatStringsSep "\n" (mapAttrsToList portSpec cfg.remoteNodes); | ||
291 | }; | ||
292 | environment.etc."uucp/sys" = { | ||
293 | text = cfg.extraSys + "\n" + concatStringsSep "\n" (mapAttrsToList sysSpec cfg.remoteNodes); | ||
294 | }; | ||
295 | |||
296 | security.wrappers = let | ||
297 | wrapper = p: { | ||
298 | name = p; | ||
299 | value = { | ||
300 | source = "${pkgs.uucp}/bin/${p}"; | ||
301 | owner = "root"; | ||
302 | group = "root"; | ||
303 | setuid = true; | ||
304 | setgid = false; | ||
305 | }; | ||
306 | }; | ||
307 | in listToAttrs (map wrapper ["uucico" "cu" "uucp" "uuname" "uustat" "uux" "uuxqt"]); | ||
308 | |||
309 | nixpkgs.overlays = [(self: super: { | ||
310 | uucp = super.stdenv.lib.overrideDerivation super.uucp (oldAttrs: { | ||
311 | configureFlags = "--with-newconfigdir=/etc/uucp"; | ||
312 | patches = [ | ||
313 | (super.writeText "mailprogram" '' | ||
314 | policy.h | 2 +- | ||
315 | 1 file changed, 1 insertion(+), 1 deletion(-) | ||
316 | |||
317 | diff --git a/policy.h b/policy.h | ||
318 | index 5afe34b..8e92c8b 100644 | ||
319 | --- a/policy.h | ||
320 | +++ b/policy.h | ||
321 | @@ -240,7 +240,7 @@ | ||
322 | the sendmail choice below. Otherwise, select one of the other | ||
323 | choices as appropriate. */ | ||
324 | #if 1 | ||
325 | -#define MAIL_PROGRAM "/usr/lib/sendmail -t" | ||
326 | +#define MAIL_PROGRAM "${config.security.wrapperDir}/sendmail -t" | ||
327 | /* #define MAIL_PROGRAM "/usr/sbin/sendmail -t" */ | ||
328 | #define MAIL_PROGRAM_TO_BODY 1 | ||
329 | #define MAIL_PROGRAM_SUBJECT_BODY 1 | ||
330 | '') | ||
331 | ]; | ||
332 | }); | ||
333 | rmail = super.writeScriptBin "rmail" '' | ||
334 | #!${super.stdenv.shell} | ||
335 | |||
336 | # Dummy UUCP rmail command for postfix/qmail systems | ||
337 | |||
338 | IFS=" " read junk from junk junk junk junk junk junk junk relay | ||
339 | |||
340 | case "$from" in | ||
341 | *[@!]*) ;; | ||
342 | *) from="$from@$relay";; | ||
343 | esac | ||
344 | |||
345 | exec ${config.security.wrapperDir}/sendmail -G -i -f "$from" -- "$@" | ||
346 | ''; | ||
347 | })]; | ||
348 | |||
349 | environment.systemPackages = with pkgs; [ | ||
350 | uucp | ||
351 | ]; | ||
352 | |||
353 | systemd.services."uucico@" = { | ||
354 | serviceConfig = { | ||
355 | User = "uucp"; | ||
356 | Type = "oneshot"; | ||
357 | ExecStart = "${config.security.wrapperDir}/uucico -D -S %i"; | ||
358 | }; | ||
359 | }; | ||
360 | |||
361 | systemd.timers."uucico@" = { | ||
362 | timerConfig.OnActiveSec = cfg.interval; | ||
363 | timerConfig.OnUnitActiveSec = cfg.interval; | ||
364 | }; | ||
365 | |||
366 | systemd.targets."multi-user" = { | ||
367 | wants = mapAttrsToList (name: node: "uucico@${name}.timer") cfg.remoteNodes; | ||
368 | }; | ||
369 | |||
370 | systemd.kill-user.enable = true; | ||
371 | systemd.targets."sleep" = { | ||
372 | after = [ "kill-user@uucp.service" ]; | ||
373 | wants = [ "kill-user@uucp.service" ]; | ||
374 | }; | ||
375 | |||
376 | networking.networkmanager.dispatcherScripts = optional cfg.nmDispatch { | ||
377 | type = "basic"; | ||
378 | source = pkgs.writeScript "callRemotes.sh" '' | ||
379 | #!${pkgs.stdenv.shell} | ||
380 | |||
381 | shopt -s extglob | ||
382 | |||
383 | case "''${2}" in | ||
384 | (?(vpn-)up) | ||
385 | ${concatStringsSep "\n " (mapAttrsToList (name: node: "${pkgs.systemd}/bin/systemctl start uucico@${name}.service") cfg.remoteNodes)} | ||
386 | ;; | ||
387 | esac | ||
388 | ''; | ||
389 | }; | ||
390 | }; | ||
391 | } | ||
diff --git a/modules/yggdrasil/default.nix b/modules/yggdrasil/default.nix new file mode 100644 index 00000000..91a550d6 --- /dev/null +++ b/modules/yggdrasil/default.nix | |||
@@ -0,0 +1,49 @@ | |||
1 | { config, lib, customUtils, ... }: | ||
2 | let | ||
3 | cfg = config.services.tinc.yggdrasil; | ||
4 | in { | ||
5 | options = { | ||
6 | services.tinc.yggdrasil = lib.mkOption { | ||
7 | type = lib.types.submodule { | ||
8 | options = { | ||
9 | enable = lib.mkEnableOption "Yggdrasil tinc network"; | ||
10 | |||
11 | connect = lib.mkOption { | ||
12 | default = true; | ||
13 | type = lib.types.bool; | ||
14 | description = '' | ||
15 | Connect to central server | ||
16 | ''; | ||
17 | }; | ||
18 | }; | ||
19 | }; | ||
20 | }; | ||
21 | }; | ||
22 | |||
23 | config = lib.mkIf cfg.enable { | ||
24 | services.tinc.networks.yggdrasil = { | ||
25 | name = config.networking.hostName; | ||
26 | hostSettings = customUtils.recImport { dir = ./hosts; }; | ||
27 | debugLevel = 2; | ||
28 | interfaceType = "tap"; | ||
29 | settings = { | ||
30 | Mode = "switch"; | ||
31 | PingTimeout = 30; | ||
32 | ConnectTo = lib.mkIf cfg.connect "ymir"; | ||
33 | }; | ||
34 | }; | ||
35 | |||
36 | sops.secrets = { | ||
37 | tinc-yggdrasil-rsa = { | ||
38 | key = "rsa"; | ||
39 | path = "/etc/tinc/yggdrasil/rsa_key.priv"; | ||
40 | sopsFile = ./hosts + "/${config.services.tinc.networks.yggdrasil.name}/private-keys.yaml"; | ||
41 | }; | ||
42 | tinc-yggdrasil-ed25519 = { | ||
43 | key = "ed25519"; | ||
44 | path = "/etc/tinc/yggdrasil/rsa_key.priv"; | ||
45 | sopsFile = ./hosts + "/${config.services.tinc.networks.yggdrasil.name}/private-keys.yaml"; | ||
46 | }; | ||
47 | }; | ||
48 | }; | ||
49 | } | ||
diff --git a/modules/yggdrasil/hosts/sif/default.nix b/modules/yggdrasil/hosts/sif/default.nix new file mode 100644 index 00000000..32b844de --- /dev/null +++ b/modules/yggdrasil/hosts/sif/default.nix | |||
@@ -0,0 +1,13 @@ | |||
1 | { | ||
2 | settings.Ed25519PublicKey = "qJqty+wiTNcYaHQCvQNiMqXYz30C9M3+LI/qjmU/9hK"; | ||
3 | rsaPublicKey = '' | ||
4 | -----BEGIN RSA PUBLIC KEY----- | ||
5 | MIIBCgKCAQEA0ACaacg9EN0hBQct8ZwQ/i6EsXKP4DIwKwabM2rp8azValTHU2uI | ||
6 | WW6JRY+Eii6zRx9B5kJ96C4rJJeAGV6lZPAogaC2LbM7lcsZ7oRDWZGaQKcZFNGi | ||
7 | laEcDg2dRuDx1W4at0rb03SDLNPt8sXSV6BcK9n/7m7+s9cwM/+PB8FHDMnWvwbC | ||
8 | usbP23020s+CVr/PU1z/7J0y3Eat+Acut6x5X8DNewpqV96wQpqdAggbhtYERMFH | ||
9 | +i0sa1WUDQtJ6HGChbENRTMlsPJ6lnzXY+J0pzatzzvetLsOljES9uJ8dtk6qBC7 | ||
10 | KRZo5lvdUwR6j9XiHMQeRerUt23b9ATFXQIDAQAB | ||
11 | -----END RSA PUBLIC KEY----- | ||
12 | ''; | ||
13 | } | ||
diff --git a/modules/yggdrasil/hosts/sif/private-keys.yaml b/modules/yggdrasil/hosts/sif/private-keys.yaml new file mode 100644 index 00000000..9be82bc1 --- /dev/null +++ b/modules/yggdrasil/hosts/sif/private-keys.yaml | |||
@@ -0,0 +1,34 @@ | |||
1 | ed25519: ENC[AES256_GCM,data:1CqB4y6CIm5JUsznpXPqqLJqCKmmoAJOZQTWb7+Jbn0oZMX27qSMK4CchHF7Bmo24EK8rk5EyW5aQLnoxp/2NA62p8SXdaoI8Qgz3EgsQ5QrlJrt1jvERpNs4vttT9V6+aK3Yojr9IuQSvJ4jyKSLrzrTnLzF9pXlaOf1Ru5SxySRWtVzynzurRpdUVS6goE+lb+Irg6x2geV719iQ9bu1C2smeQDREdS+dlfoxp02/pU6kTFA7KAm5vA91HKEfMqfSEzuBgUB0=,iv:n6Yh0zZ9AbT+83P42QNO2rCCISJV5nbO9wYcwaRYD2E=,tag:dJpXV9ZzLSO1B+LsyV3vAg==,type:str] | ||
2 | rsa: ENC[AES256_GCM,data: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,iv:ZUAqvOpcVCXQD2PFzUh0e2m20t6gVT3mYb7S50iV/m8=,tag:AssxMqjVUEwQ4R6Y7eG9Tg==,type:str] | ||
3 | sops: | ||
4 | kms: [] | ||
5 | gcp_kms: [] | ||
6 | azure_kv: [] | ||
7 | hc_vault: [] | ||
8 | lastmodified: '2021-01-02T14:46:16Z' | ||
9 | mac: ENC[AES256_GCM,data:Phng7z7UlE6nO3FFIQPOHgKCqDm2uOGL57ryJbokjipSSdoWPinpz0zIJv9Z67b9uOf3CQoGtV4YwcudNkzDBKOyD8uA6RYwCKpbYcZIdiy8DLL46+VT/wq9toTkeDXM6jKupzzOARZhHT8DCOLqW7u8Q3S645cbTJmw0+LMIGk=,iv:y4KEh0+bKhtnSobKVdfaPuRsueNC1lcrEbUGfEAn+Bg=,tag:3Oi4e/hSgPVsoFQpnVQj+g==,type:str] | ||
10 | pgp: | ||
11 | - created_at: '2021-01-02T14:45:04Z' | ||
12 | enc: | | ||
13 | -----BEGIN PGP MESSAGE----- | ||
14 | |||
15 | hF4Dgwm4NZSaLAcSAQdAwWM12Zara3T2xDIX3rhakGxXFyme4LE5QZgE2GjnnWEw | ||
16 | T/vhPfsKFCjA2kAmj41NupjvTPL/nzfd7+MrdHRfC462Jrq+UF1W8A4bUa3OMH5J | ||
17 | 0l4BuFhl93w/VBftvnG8oSBAFCPNDapNADjTVJQStgsZa0/uD93NnCxyQmtuJYsQ | ||
18 | URlH0KMT6Kouaec4qk3SqkAHzaIIAukahBHAPf2C5cvXYw7AAOOBOdRaWycsmZDc | ||
19 | =S4Ig | ||
20 | -----END PGP MESSAGE----- | ||
21 | fp: F1AF20B9511B63F681A14E8D51AEFBCD1DEF68F8 | ||
22 | - created_at: '2021-01-02T14:45:04Z' | ||
23 | enc: | | ||
24 | -----BEGIN PGP MESSAGE----- | ||
25 | |||
26 | hF4DXxoViZlp6dISAQdA7apd+ipJ0lUiuPI5Sq6uj6iOQYFfuNDuzse1JFJMfn4w | ||
27 | McsGPcbMorZV0OVFmg9vuZ0GP9sb7mkm+oRuY9OeMDEifjWGHJ2UN4TvdEcCO1zx | ||
28 | 0l4BvYyzFbShlQjge7+nrzVi2lzEvqsozEW76K3arWb/iYLCRyl0/Vhw5WT4K/UE | ||
29 | fw4cbqz7JrogVLFNeWSRPk3Y+Dg4Pf9rQnw1EJhUEIczYjnfajPhYe5K4M01mOby | ||
30 | =B0n7 | ||
31 | -----END PGP MESSAGE----- | ||
32 | fp: 30D3453B8CD02FE2A3E7C78C0FB536FB87AE8F51 | ||
33 | unencrypted_suffix: _unencrypted | ||
34 | version: 3.6.1 | ||
diff --git a/modules/yggdrasil/hosts/ymir.nix b/modules/yggdrasil/hosts/ymir.nix new file mode 100644 index 00000000..b77a9216 --- /dev/null +++ b/modules/yggdrasil/hosts/ymir.nix | |||
@@ -0,0 +1,19 @@ | |||
1 | { | ||
2 | addresses = [{ address = "ymir.yggdrasil.li"; }]; | ||
3 | settings.Ed25519PublicKey = "b/SobnMqByzHOQeO+iU7OZ1liD8a++knbi5ebNawnaC"; | ||
4 | rsaPublicKey = '' | ||
5 | -----BEGIN RSA PUBLIC KEY----- | ||
6 | MIICCgKCAgEAuInSfQf5euFXEVkLLzf9TumQJ+3WRsxX4uKdOXBqrIC7yjSBP8j9 | ||
7 | ql5rNWPzgXxFF5ERmwW+E3cyzJLU9Htu7r3muqM6nhSZizhCskifPRFc3e5ssSke | ||
8 | XhHICHfe90+qvab/hWx/NjkW59bBYIzDuJfq+ijDFMVNgOxaiM2f3/2prUUhP7bN | ||
9 | r3wVI8KCkOaknc0SOOmOhLzfJaD5wosqLOjgaNhlro2eMgMjQlxbyW8dVVgjwseR | ||
10 | Cl/mpu7r1pSMhS66RFH68wDoC3X81f7Zs9ZGDLTD8KXWhx0qgUMUAH4n6YGY0RM6 | ||
11 | BZ3qR/3KFRU64QPVAERpb0JdsU9ggCVydHkjrWW23ptHOPAOO5+yQj7tSDCKTRy9 | ||
12 | dHMQnbtPrgAb6iMhO1XTxA8Hdta1sCHsewsQekarwsA1bmk3hTgi/k8vwoGDUWtk | ||
13 | jgiDEPuutfmH4C6qxq9s+6lRboNKH8wgkVGpHiaq7mmePFdhzFdrj4+fYAMZTbil | ||
14 | 2iygsJ+yFOjA7U+iT6QDK33/MLsrQg0Ue6RPiG1qnDyax7gBAjz52iWkiuSkUXk0 | ||
15 | E5ImdP4XMILgGcWk8iPq5iRS03edE0pCpxGX3ZZwFE5+CoXgO6wR1ToL1vZEEHMQ | ||
16 | SHJPufKjkavPKbejPps/mLaJQVw3W10PAJssB9nxW2aHX3n0ugGaIvMCAwEAAQ== | ||
17 | -----END RSA PUBLIC KEY----- | ||
18 | ''; | ||
19 | } | ||