summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--accounts/gkleen@sif.nix1
-rw-r--r--hosts/sif/default.nix295
-rw-r--r--hosts/sif/hw.nix36
-rw-r--r--hosts/sif/mail/default.nix66
-rw-r--r--hosts/sif/mail/secrets.yaml33
-rw-r--r--hosts/sif/wacom.conf15
-rw-r--r--modules/borgbackup/btrfs-snapshots.nix52
-rw-r--r--modules/borgbackup/default.nix199
-rw-r--r--modules/borgbackup/lvm-snapshots.nix133
-rw-r--r--modules/kill-user.nix13
-rw-r--r--modules/tinc-networkmanager.nix36
-rw-r--r--modules/uucp.nix391
-rw-r--r--modules/yggdrasil/default.nix49
-rw-r--r--modules/yggdrasil/hosts/sif/default.nix13
-rw-r--r--modules/yggdrasil/hosts/sif/private-keys.yaml34
-rw-r--r--modules/yggdrasil/hosts/ymir.nix19
-rw-r--r--overlays/nvidia-kernel-5.7.nix19
-rw-r--r--system-profiles/default-locale.nix7
-rw-r--r--system-profiles/initrd-all-crypto-modules.nix7
-rw-r--r--system-profiles/openssh/default.nix36
-rw-r--r--system-profiles/openssh/host-keys/sif.yaml34
-rw-r--r--system-profiles/openssh/known-hosts/sif.nix16
-rw-r--r--system-profiles/openssh/known-hosts/ymir.nix16
-rw-r--r--system-profiles/sudo.nix39
-rw-r--r--users/gkleen/default.nix7
-rw-r--r--users/root.nix1
26 files changed, 1567 insertions, 0 deletions
diff --git a/accounts/gkleen@sif.nix b/accounts/gkleen@sif.nix
new file mode 100644
index 00000000..c157af78
--- /dev/null
+++ b/accounts/gkleen@sif.nix
@@ -0,0 +1 @@
{ ... }: {}
diff --git a/hosts/sif/default.nix b/hosts/sif/default.nix
new file mode 100644
index 00000000..4e9826bd
--- /dev/null
+++ b/hosts/sif/default.nix
@@ -0,0 +1,295 @@
1{ flake, pkgs, customUtils, lib, config, ... }:
2{
3 imports = with flake.nixosModules.systemProfiles; [
4 ./hw.nix
5 ./mail
6 initrd-all-crypto-modules default-locale openssh
7 ];
8
9 config = {
10 nixpkgs = {
11 system = "x86_64-linux";
12 config = {
13 allowUnfree = true;
14 };
15 };
16
17 boot = {
18 initrd = {
19 luks.devices = {
20 nvm0.device = "/dev/disk/by-uuid/fe641e81-0812-4181-a5f6-382ebba509bb";
21 nvm1.device = "/dev/disk/by-uuid/43df1ba8-1728-4193-8855-920a82d4494a";
22 };
23 availableKernelModules = [ "drbg" "nvme" "fbcon" "xhci_pci" "usb_storage" "sd_mod" "rtsx_pci_sdmmc" ];
24 kernelModules = [ "dm-raid" "dm-integrity" "dm-snapshot" "dm-thin-pool" ];
25 };
26
27 blacklistedKernelModules = [ "nouveau" ];
28
29 # Use the systemd-boot EFI boot loader.
30 loader = {
31 systemd-boot.enable = true;
32 efi.canTouchEfiVariables = true;
33 timeout = null;
34 };
35
36 plymouth.enable = true;
37
38 kernelPackages = pkgs.linuxPackages_latest;
39 kernelParams = [ "i915.fastboot=1" "intel_pstate=no_hwp" "acpi_backlight=vendor" "thinkpad-acpi.brightness_enable=1" "quiet" ];
40
41 tmpOnTmpfs = true;
42 };
43
44 networking = {
45 domain = "midgard.yggdrasil";
46 hosts = {
47 "127.0.0.1" = [ "sif.midgard.yggdrasil" "sif" ];
48 "::1" = [ "sif.midgard.yggdrasil" "sif" ];
49 };
50
51 firewall = {
52 enable = true;
53 allowedTCPPorts = [ 22 # ssh
54 8000 # quickserve
55 ];
56 };
57
58 networkmanager = {
59 enable = true;
60 dhcp = "internal";
61 dns = "dnsmasq";
62 extraConfig = ''
63 [connectivity]
64 uri=https://online.yggdrasil.li
65 '';
66 };
67
68 dhcpcd.enable = false;
69
70 interfaces.yggdrasil = {
71 virtual = true;
72 virtualType = config.services.tinc.networks.yggdrasil.interfaceType;
73 macAddress = "5c:93:21:c3:61:39";
74 };
75 };
76
77 environment.etc."NetworkManager/dnsmasq.d/libvirtd_dnsmasq.conf" = {
78 text = ''
79 server=/sif.libvirt/192.168.122.1
80 '';
81 };
82
83 powerManagement.enable = true;
84
85 environment.systemPackages = with pkgs; [
86 nvtop brightnessctl
87 ];
88
89 services = {
90 tinc.yggdrasil.enable = true;
91
92 uucp = {
93 enable = true;
94 nodeName = "sif";
95 remoteNodes = {
96 "ymir" = {
97 publicKeys = ["ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIG6KNtsCOl5fsZ4rV7udTulGMphJweLBoKapzerWNoLY root@ymir"];
98 hostnames = ["ymir.yggdrasil.li" "ymir.niflheim.yggdrasil"];
99 };
100 };
101
102 defaultCommands = lib.mkForce [];
103 };
104
105 avahi.enable = true;
106
107 fwupd.enable = true;
108
109 fprintd.enable = true;
110
111 blueman.enable = true;
112
113 colord.enable = true;
114
115 vnstat.enable = true;
116
117 logind = {
118 lidSwitch = "suspend";
119 lidSwitchDocked = "lock";
120 lidSwitchExternalPower = "lock";
121 };
122
123 atd = {
124 enable = true;
125 allowEveryone = true;
126 };
127
128 xserver = {
129 enable = true;
130
131 layout = "us";
132 xkbVariant = "dvp";
133 xkbOptions = "compose:caps";
134
135 displayManager.lightdm = {
136 enable = true;
137 greeters.gtk = {
138 clock-format = "%H:%M %a %b %_d";
139 indicators = ["~host" "~spacer" "~clock" "~session" "~power"];
140 theme = {
141 package = pkgs.equilux-theme;
142 name = "Equilux-compact";
143 };
144 iconTheme = {
145 package = pkgs.paper-icon-theme;
146 name = "Paper";
147 };
148 extraConfig = ''
149 background = #000000
150 user-background = false
151 active-monitor = #cursor
152 hide-user-image = true
153
154 [monitor: DP-2]
155 laptop = true
156 '';
157 };
158 };
159
160 displayManager.setupCommands = ''
161 ${pkgs.xorg.xinput}/bin/xinput disable 'SynPS/2 Synaptics TouchPad'
162 '';
163
164 desktopManager.xterm.enable = true;
165 windowManager.twm.enable = true;
166 displayManager.defaultSession = "xterm+twm";
167
168 wacom.enable = true;
169 libinput.enable = true;
170
171 dpi = 282;
172
173 videoDrivers = [ "nvidia" ];
174
175 screenSection = ''
176 Option "metamodes" "nvidia-auto-select +0+0 { ForceCompositionPipeline = On }"
177 '';
178
179 deviceSection = ''
180 Option "AccelMethod" "SNA"
181 Option "TearFree" "True"
182 '';
183
184 exportConfiguration = true;
185 };
186 };
187
188 users = {
189 users.gkleen.extraGroups = [ "media" ];
190 };
191
192 hardware = {
193 pulseaudio = {
194 enable = true;
195 package = with pkgs; pulseaudioFull;
196 support32Bit = true;
197 };
198
199 bluetooth = {
200 enable = true;
201 config = {
202 General = {
203 Enable = "Source,Sink,Media,Socket";
204 };
205 };
206 };
207
208 trackpoint = {
209 enable = true;
210 emulateWheel = true;
211 sensitivity = 255;
212 speed = 255;
213 };
214
215 nvidia = {
216 modesetting.enable = true;
217 prime = {
218 nvidiaBusId = "PCI:1:0:0";
219 intelBusId = "PCI:0:2:0";
220 sync.enable = true;
221 };
222 };
223
224 opengl = {
225 enable = true;
226 driSupport32Bit = true;
227 setLdLibraryPath = true;
228 };
229
230 firmware = [ pkgs.firmwareLinuxNonfree ];
231 };
232
233 sound.enable = true;
234
235 nix = {
236 autoOptimiseStore = true;
237 daemonNiceLevel = 10;
238 daemonIONiceLevel = 3;
239 };
240
241 environment.etc."X11/xorg.conf.d/50-wacom.conf".source = lib.mkForce ./wacom.conf;
242
243 systemd.services."ac-plugged" = {
244 description = "Inhibit handling of lid-switch and sleep";
245
246 path = with pkgs; [ systemd coreutils ];
247
248 script = ''
249 exec systemd-inhibit --what=handle-lid-switch --why="AC is connected" --mode=block sleep infinity
250 '';
251
252 serviceConfig = {
253 Type = "simple";
254 };
255 };
256
257 services.udev.extraRules = with pkgs; ''
258 SUBSYSTEM=="power_supply", ENV{POWER_SUPPLY_ONLINE}=="0", RUN+="${systemd}/bin/systemctl --no-block stop ac-plugged.service"
259 SUBSYSTEM=="power_supply", ENV{POWER_SUPPLY_ONLINE}=="1", RUN+="${systemd}/bin/systemctl --no-block start ac-plugged.service"
260 '';
261
262 services.btrfs.autoScrub = {
263 enable = true;
264 fileSystems = [ "/" "/home" ];
265 interval = "weekly";
266 };
267
268 systemd.services."nix-daemon".serviceConfig = {
269 MemoryAccounting = true;
270 MemoryHigh = "50%";
271 MemoryMax = "75%";
272 };
273
274 services.journald.extraConfig = ''
275 SystemMaxUse=100M
276 '';
277
278 services.dbus.packages = with pkgs;
279 [ dbus gnome3.dconf
280 ];
281
282 programs = {
283 light.enable = true;
284 wireshark.enable = true;
285 };
286
287 virtualisation.libvirtd = {
288 enable = true;
289 };
290
291 zramSwap.enable = true;
292
293 system.stateVersion = "20.03";
294 };
295}
diff --git a/hosts/sif/hw.nix b/hosts/sif/hw.nix
new file mode 100644
index 00000000..4a3e6c86
--- /dev/null
+++ b/hosts/sif/hw.nix
@@ -0,0 +1,36 @@
1{ config, lib, pkgs, ... }:
2
3{
4 fileSystems."/" =
5 { device = "/dev/disk/by-uuid/f094bf06-66f9-40a8-9ab2-2b54d05223d2";
6 fsType = "btrfs";
7 };
8
9 fileSystems."/boot" =
10 { device = "/dev/disk/by-uuid/B3A2-D029";
11 fsType = "vfat";
12 };
13
14 fileSystems."/home" =
15 { device = "/dev/disk/by-uuid/9e932072-3c56-4a9c-8da7-3163d2a8bf28";
16 fsType = "btrfs";
17 };
18
19 fileSystems."/var/media" =
20 { device = "/dev/disk/by-uuid/437eca70-d017-4d52-a1fa-2f4c7a87f096";
21 fsType = "btrfs";
22 };
23
24 swapDevices =
25 [ { device = "/dev/disk/by-uuid/50f3f856-cc17-4614-846a-34a14d5006ec"; }
26 ];
27
28 nix.maxJobs = 12;
29 powerManagement.cpuFreqGovernor = "powersave";
30 # High-DPI console
31 console.font = "${pkgs.terminus_font}/share/consolefonts/ter-u28n.psf.gz";
32
33 hardware.cpu.intel.updateMicrocode = true;
34
35 hardware.enableRedistributableFirmware = true;
36}
diff --git a/hosts/sif/mail/default.nix b/hosts/sif/mail/default.nix
new file mode 100644
index 00000000..2addba9d
--- /dev/null
+++ b/hosts/sif/mail/default.nix
@@ -0,0 +1,66 @@
1{ config, pkgs, ... }:
2{
3 services.postfix = {
4 enable = true;
5 enableSmtp = true;
6 enableSubmission = false;
7 setSendmail = true;
8 networksStyle = "host";
9 hostname = "sif.midgard.yggdrasil";
10 destination = [];
11 relayHost = "uucp:ymir";
12 recipientDelimiter = "+";
13 masterConfig = {
14 uucp = {
15 type = "unix";
16 private = true;
17 privileged = true;
18 chroot = false;
19 command = "pipe";
20 args = [ "flags=Fqhu" "user=uucp" ''argv=${config.security.wrapperDir}/uux -z -a $sender - $nexthop!rmail ($recipient)'' ];
21 };
22 };
23 transport = ''
24 odin.asgard.yggdrasil uucp:odin
25 '';
26 config = {
27 always_bcc = "gkleen+sent@odin.asgard.yggdrasil";
28
29 default_transport = "uucp:ymir";
30
31 inet_interfaces = "loopback-only";
32
33 authorized_submit_users = ["!uucp" "static:anyone"];
34 message_size_limit = "0";
35
36 sender_dependent_default_transport_maps = ''regexp:${pkgs.writeText "sender_relay" ''
37 /@(cip|stud)\.ifi\.(lmu|uni-muenchen)\.de$/ smtp:smtp.ifi.lmu.de
38 /@ifi\.(lmu|uni-muenchen)\.de$/ smtp:smtpin1.ifi.lmu.de:587
39 /@(campus\.)?lmu\.de$/ smtp:postout.lrz.de
40 ''}'';
41 sender_bcc_maps = ''texthash:${pkgs.writeText "sender_bcc" ''
42 uni2work@ifi.lmu.de uni2work@ifi.lmu.de
43 @ifi.lmu.de gregor.kleen@ifi.lmu.de
44 ''}'';
45
46 smtp_sasl_auth_enable = true;
47 smtp_sender_dependent_authentication = true;
48 smtp_sasl_tls_security_options = "noanonymous";
49 smtp_sasl_mechanism_filter = ["plain"];
50 smtp_sasl_password_maps = "texthash:/var/db/postfix/sasl_passwd";
51 smtp_cname_overrides_servername = false;
52 smtp_always_send_ehlo = true;
53
54 smtp_tls_loglevel = "1";
55 smtp_dns_support_level = "dnssec";
56 };
57 useDane = true;
58 };
59
60 sops.secrets.postfix-sasl-passwd = {
61 key = "sasl-passwd";
62 path = "/var/db/postfix/sasl_passwd";
63 owner = "postfix";
64 sopsFile = ./secrets.yaml;
65 };
66}
diff --git a/hosts/sif/mail/secrets.yaml b/hosts/sif/mail/secrets.yaml
new file mode 100644
index 00000000..00422f82
--- /dev/null
+++ b/hosts/sif/mail/secrets.yaml
@@ -0,0 +1,33 @@
1sasl-passwd: ENC[AES256_GCM,data:RDZHUgQJHH7IzJD5j+LOuQb4OuPopUEa6CwDRoD/FqoHFW/YKarF3Hxxu4HKA5GDf3SRrFOcPBXmf+0f1CucUQwJQh4nY4fmDVqrH0UXRowuAkIhYpt0sLXlzrOzSeZz788A9xK4AGPzEOx1va7GOqJIaPJ+pyyzazQsSgCJaFkUMriCfKbZ0zhRCr0pk2RPLOLKGuo2mDFf5c3EZYAn7vEzhZj+B3XbNWotV/JXTX7JPK6GPcsX2RMKEYBdmxZzrMCTTFU23W1DbiDJ01mxJh3ckIX+KTmaWNoVg4Tong1vBe2wxKchXajmykwFLJFR1Kj5wv4uAxy2qNvKtQIF/LJosG6LXcdk5QDQBXUINqswupBdV8lt08mk53JHLJPXcV8RpEHT3NUL,iv:2u203xTmUEfWIJDB2ZkOKzhYQrV4TGT7rfOd0md+VOw=,tag:RJ/iLbbq8B8dMmXGWjok/g==,type:str]
2sops:
3 kms: []
4 gcp_kms: []
5 azure_kv: []
6 hc_vault: []
7 lastmodified: '2021-01-02T19:29:40Z'
8 mac: ENC[AES256_GCM,data:g8wNpsFXiGoENSteWa1w1UkF8LQwnwtoeEHskKhGqAlCFtA1cVdyFSItm8/h1/eqJl/NWXRGU25XpZysCAkJi+uCq4bNGjV+gjqeIT8Dv5teQbVwthoFqkE/s3jew35+f29/xxb5Cro6EihlTrs5Lt3wExv2+NUdim1aeNgR+4Q=,iv:bj/igDT7GPiCjj4BwE7ihM8wR8CbJeXu/s550rc+QEw=,tag:KKt6tWlqxu5C/L/ZYbQL3g==,type:str]
9 pgp:
10 - created_at: '2021-01-02T19:29:14Z'
11 enc: |
12 -----BEGIN PGP MESSAGE-----
13
14 hF4Dgwm4NZSaLAcSAQdAE/883Tbc7WXuzOxjm5jVrOSbnYe+BEg75ijtZP2L3UMw
15 4mhqzy576jEQLPGrnMpX2zA2MwFAwGnMwC98sQ4vVTp/xgNQ0VHHNM4GnTi6VoUb
16 0l4BLgQrT6p2ul69ADecadWJsGm6roqMHrpNGZeeczDLOBIzrrwN4sL92jQiEPw9
17 Ih+EXJpJ1K4NouU1VRsfQPqJ6y+i295TnEgunlJeYc/MNQgBT4ABiPZgUZXnkhxl
18 =7rOv
19 -----END PGP MESSAGE-----
20 fp: F1AF20B9511B63F681A14E8D51AEFBCD1DEF68F8
21 - created_at: '2021-01-02T19:29:14Z'
22 enc: |
23 -----BEGIN PGP MESSAGE-----
24
25 hF4DXxoViZlp6dISAQdAGifJ6qk40VdF/WKaYa9v97PdSVkPvHZt+j0G8+ZDJSEw
26 8XC1622ElTWRCZ2bjUwMF77DMgMy3rEr8B7Bj6MnEzDd/Af63Np1cO+7juybxqhz
27 0l4BO6uZ+gCvKg45jWX0GE6ZBkoUTvh24djTngHFyIHDnpCxSB6s+jcYR9otco2F
28 ++E2pcoQR4GuOeyYa/8UsW+RzKWpCfskYbSIt4gAXyCt8ua1y5Rw0DEVdw91uJNC
29 =E/qh
30 -----END PGP MESSAGE-----
31 fp: 30D3453B8CD02FE2A3E7C78C0FB536FB87AE8F51
32 unencrypted_suffix: _unencrypted
33 version: 3.6.1
diff --git a/hosts/sif/wacom.conf b/hosts/sif/wacom.conf
new file mode 100644
index 00000000..864409f1
--- /dev/null
+++ b/hosts/sif/wacom.conf
@@ -0,0 +1,15 @@
1Section "InputClass"
2 Identifier "Wacom USB device class"
3 MatchUSBID "056a:*"
4 MatchDevicePath "/dev/input/event*"
5 Driver "wacom"
6EndSection
7
8Section "InputClass"
9 Identifier "calibration"
10 MatchProduct "Wacom USB device class"
11 Option "MinX" "58"
12 Option "MaxX" "30982"
13 Option "MinY" "87"
14 Option "MaxY" "17328"
15EndSection \ No newline at end of file
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
3with lib;
4
5let
6 cfg = config.services.btrfs-snapshots;
7
8 snapshotMount = str: "${str}${cfg.mountSuffix}";
9in {
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..47f8e06d
--- /dev/null
+++ b/modules/borgbackup/default.nix
@@ -0,0 +1,199 @@
1{ config, lib, utils, pkgs, ... }:
2
3with utils;
4with lib;
5
6let
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 };
70in {
71 disabledModules = [ "services/backup/borgbackup.nix" ];
72
73 options = {
74 services.borgbackup = {
75 snapshots = mkOption {
76 type = types.nullOr (types.enum ["btrfs" "lvm"]);
77 default = null;
78 };
79
80 targets = mkOption {
81 type = types.attrsOf (types.submodule targetOptions);
82 default = {};
83 };
84
85 prefix = mkOption {
86 type = types.str;
87 };
88 };
89 };
90
91 imports =
92 [ ./lvm-snapshots.nix
93 ./btrfs-snapshots.nix
94 ];
95
96 config = mkIf (any (t: t.paths != []) (attrValues cfg.targets)) {
97 services.btrfs-snapshots.enable = mkIf (cfg.snapshots == "btrfs") true;
98
99 services.lvm-snapshots.snapshots = mkIf (cfg.snapshots == "lvm") (listToAttrs (map (path: nameValuePair (path.VG + "-" + path.LV) {
100 inherit (path) LV VG;
101 mountName = withSuffix (path.VG + "-" + path.LV);
102 }) (unique (flatten (mapAttrsToList (target: tCfg: tCfg.paths) cfg.targets)))));
103
104 systemd.targets."timers-borg" = {
105 wantedBy = [ "timers.target" ];
106 };
107
108 systemd.slices."system-borgbackup" = {};
109
110 systemd.timers = (listToAttrs (map ({ target, path, tCfg }: nameValuePair "borgbackup-${target}@${systemdPath path}" {
111 requiredBy = [ "timers-borg.target" ];
112
113 timerConfig = {
114 Persistent = false;
115 OnBootSec = tCfg.interval;
116 OnUnitActiveSec = tCfg.interval;
117 RandomizedDelaySec = mkIf (tCfg.jitter != null) tCfg.jitter;
118 };
119 }) (flatten (mapAttrsToList (target: tCfg: map (path: { inherit target path tCfg; }) tCfg.paths) cfg.targets)))) // (mapAttrs' (target: tCfg: nameValuePair "borgbackup-prune-${target}" {
120 enable = tCfg.prune != {};
121
122 requiredBy = [ "timers-borg.target" ];
123
124 timerConfig = {
125 Persistent = false;
126 OnBootSec = tCfg.interval;
127 OnUnitActiveSec = tCfg.interval;
128 RandomizedDelaySec = mkIf (tCfg.jitter != null) tCfg.jitter;
129 };
130 }) cfg.targets);
131
132 systemd.services = (mapAttrs' (target: tCfg: nameValuePair "borgbackup-${target}@" (let
133 deps = flatten [
134 (optional (cfg.snapshots == "btrfs") "btrfs-snapshot@%i.service")
135 (optional tCfg.network "network-online.target")
136 ];
137 in {
138 bindsTo = deps;
139 after = deps;
140
141 path = with pkgs; [borgbackup] ++ optional (tCfg.lock != null) utillinux;
142
143 script = let
144 borgCmd = ''
145 borg create \
146 --lock-wait ${toString tCfg.lockWait} \
147 --stats \
148 --list \
149 --filter 'AME' \
150 --exclude-caches \
151 --keep-exclude-tags \
152 --patterns-from .backup-${target} \
153 --one-file-system \
154 --compression auto,lzma \
155 ${tCfg.repo}::${cfg.prefix}$1-{utcnow}
156 '';
157 in if tCfg.lock == null then borgCmd else "flock -xo /var/lock/${tCfg.lock} ${borgCmd}";
158 scriptArgs = if cfg.snapshots == "lvm" then "%I" else "%i";
159
160 unitConfig = {
161 AssertPathIsDirectory = mkIf (tCfg.lock != null) "/var/lock";
162 DefaultDependencies = false;
163 RequiresMountsFor = mkIf (cfg.snapshots == "lvm") [ "${mountPoint}/${withSuffix "%I"}" ];
164 };
165
166 serviceConfig = {
167 Type = "oneshot";
168 WorkingDirectory = if (cfg.snapshots == null) then "%I" else (if (cfg.snapshots == "lvm") then "${mountPoint}/${withSuffix "%I"}" else "${withSuffix "%f"}");
169 Nice = 15;
170 IOSchedulingClass = 2;
171 IOSchedulingPriority = 7;
172 SuccessExitStatus = [1 2];
173 Slice = "system-borgbackup.slice";
174 };
175 })) cfg.targets) // (mapAttrs' (target: tCfg: nameValuePair "borgbackup-prune-${target}" {
176 enable = tCfg.prune != {};
177
178 bindsTo = ["network-online.target"];
179 after = ["network-online.target"];
180
181 path = with pkgs; [borgbackup];
182
183 script = concatStringsSep "\n" (mapAttrsToList (path: args: ''
184 borg prune \
185 --lock-wait ${toString tCfg.lockWait} \
186 --list \
187 --stats \
188 --prefix ${escapeShellArg "${cfg.prefix}${path}"} \
189 ${escapeShellArgs args} \
190 ${tCfg.repo}
191 '') tCfg.prune);
192
193 serviceConfig = {
194 Type = "oneshot";
195 Slice = "system-borgbackup.slice";
196 };
197 }) cfg.targets);
198 };
199}
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
3with utils;
4with lib;
5
6let
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 };
43in {
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/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, ... }:
2let
3 cfg = config.services.tinc;
4in {
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
3with lib;
4
5let
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;
81in {
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, ... }:
2let
3 cfg = config.services.tinc.yggdrasil;
4in {
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 @@
1ed25519: ENC[AES256_GCM,data:1CqB4y6CIm5JUsznpXPqqLJqCKmmoAJOZQTWb7+Jbn0oZMX27qSMK4CchHF7Bmo24EK8rk5EyW5aQLnoxp/2NA62p8SXdaoI8Qgz3EgsQ5QrlJrt1jvERpNs4vttT9V6+aK3Yojr9IuQSvJ4jyKSLrzrTnLzF9pXlaOf1Ru5SxySRWtVzynzurRpdUVS6goE+lb+Irg6x2geV719iQ9bu1C2smeQDREdS+dlfoxp02/pU6kTFA7KAm5vA91HKEfMqfSEzuBgUB0=,iv:n6Yh0zZ9AbT+83P42QNO2rCCISJV5nbO9wYcwaRYD2E=,tag:dJpXV9ZzLSO1B+LsyV3vAg==,type:str]
2rsa: ENC[AES256_GCM,data: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,iv:ZUAqvOpcVCXQD2PFzUh0e2m20t6gVT3mYb7S50iV/m8=,tag:AssxMqjVUEwQ4R6Y7eG9Tg==,type:str]
3sops:
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}
diff --git a/overlays/nvidia-kernel-5.7.nix b/overlays/nvidia-kernel-5.7.nix
new file mode 100644
index 00000000..92d3abb3
--- /dev/null
+++ b/overlays/nvidia-kernel-5.7.nix
@@ -0,0 +1,19 @@
1final: prev: {
2 linuxPackages_latest = prev.linuxPackages_latest.extend (self: super: {
3 nvidiaPackages = super.nvidiaPackages // {
4 stable = super.nvidiaPackages.stable.overrideAttrs (attrs: {
5 patches = [
6 (prev.fetchpatch {
7 name = "nvidia-kernel-5.7.patch";
8 url = "https://gitlab.com/snippets/1965550/raw";
9 sha256 = "03iwxhkajk65phc0h5j7v4gr4fjj6mhxdn04pa57am5qax8i2g9w";
10 })
11 ];
12
13 passthru = {
14 inherit (super.nvidiaPackages.stable) settings persistenced persistencedVersion settingsVersion;
15 };
16 });
17 };
18 });
19}
diff --git a/system-profiles/default-locale.nix b/system-profiles/default-locale.nix
new file mode 100644
index 00000000..9775c095
--- /dev/null
+++ b/system-profiles/default-locale.nix
@@ -0,0 +1,7 @@
1{...}:
2{
3 i18n.defaultLocale = "en_US.UTF-8";
4 console.keyMap = "dvp";
5
6 time.timeZone = "Europe/Berlin";
7}
diff --git a/system-profiles/initrd-all-crypto-modules.nix b/system-profiles/initrd-all-crypto-modules.nix
new file mode 100644
index 00000000..6b1da298
--- /dev/null
+++ b/system-profiles/initrd-all-crypto-modules.nix
@@ -0,0 +1,7 @@
1{...}:
2{
3 boot.initrd.luks.cryptoModules = [
4 "serpent_generic" "algif_rng" "authencesn" "crct10dif_generic" "blowfish_generic" "aegis128" "crc32c_generic" "md4" "lz4hc" "cbc" "adiantum" "authenc" "seqiv" "ecdh_generic" "842" "pcbc" "curve25519-generic" "sha256_generic" "cmac" "async_tx" "async_raid6_recov" "async_memcpy" "async_xor" "gcm" "ccm" "async_pq" "sha512_generic" "echainiv" "anubis" "blowfish_common" "algif_hash" "tgr192" "ghash-generic" "crypto_simd" "michael_mic" "ansi_cprng" "cast_common" "rmd128" "sm4_generic" "twofish_common" "wp512" "zstd" "cast5_generic" "algif_skcipher" "crc32_generic" "sm3_generic" "nhpoly1305" "cryptd" "twofish_generic" "crypto_user" "af_alg" "des_generic" "rmd320" "salsa20_generic" "xts" "xxhash_generic" "ecrdsa_generic" "deflate" "rmd256" "camellia_generic" "lrw" "xor" "gf128mul" "ecc" "arc4" "crypto_engine" "ecb" "lz4" "xcbc" "aes_ti" "khazad" "streebog_generic" "cast6_generic" "blake2b_generic" "keywrap" "chacha_generic" "tea" "aes_generic" "fcrypt" "cts" "chacha20poly1305" "essiv" "hmac" "vmac" "poly1305_generic" "sha3_generic" "rmd160" "algif_aead" "ctr" "crct10dif_common" "jitterentropy_rng" "pcrypt" "serpent-avx-x86_64" "cast5-avx-x86_64" "twofish-x86_64-3way" "sha1-ssse3" "seed" "cfb" "blake2s_generic" "ofb" "cast6-avx-x86_64" "twofish-x86_64" "drbg" "serpent-sse2-x86_64" "camellia-aesni-avx2" "crct10dif-pclmul" "sha256-ssse3" "sha512-ssse3" "crc32-pclmul" "camellia-x86_64" "curve25519-x86_64" "nhpoly1305-avx2" "ghash-clmulni-intel" "poly1305-x86_64" "aegis128-aesni" "camellia-aesni-avx-x86_64" "blowfish-x86_64" "nhpoly1305-sse2" "crc32c-intel" "aesni-intel" "blake2s-x86_64" "twofish-avx-x86_64" "glue_helper" "chacha-x86_64" "serpent-avx2" "des3_ede-x86_64" "asym_tpm" "pkcs7_test_key" "tpm_key_parser"
5 "encrypted_keys"
6 ];
7}
diff --git a/system-profiles/openssh/default.nix b/system-profiles/openssh/default.nix
new file mode 100644
index 00000000..4db3d7db
--- /dev/null
+++ b/system-profiles/openssh/default.nix
@@ -0,0 +1,36 @@
1{ customUtils, lib, config, hostName, ... }:
2{
3 services.openssh = {
4 enable = true;
5 knownHosts = lib.zipAttrsWith (_name: values: builtins.head values) (lib.mapAttrsToList (name: lib.mapAttrs' (type: value: lib.nameValuePair "${name}-${type}" value)) (customUtils.recImport { dir = ./known-hosts; }));
6
7 hostKeys = [
8 { path = "/etc/ssh/ssh_host_rsa_key";
9 type = "rsa";
10 }
11 { path = "/etc/ssh/ssh_host_ed25519_key";
12 type = "ed25519";
13 }
14 ];
15 };
16
17 sops.secrets = {
18 ssh_host_rsa_key = {
19 key = "rsa";
20 path = "/etc/ssh/ssh_host_rsa_key";
21 sopsFile = ./host-keys + "/${hostName}.yaml";
22 };
23 ssh_host_ed25519_key = {
24 key = "ed25519";
25 path = "/etc/ssh/ssh_host_ed25519_key";
26 sopsFile = ./host-keys + "/${hostName}.yaml";
27 };
28 };
29
30 environment.etc = {
31 "ssh/ssh_host_rsa_key.pub".text = config.services.openssh.knownHosts."${hostName}-rsa".publicKey;
32 "ssh/ssh_host_ed25519_key.pub".text = config.services.openssh.knownHosts."${hostName}-ed25519".publicKey;
33 };
34
35 systemd.user.services."ssh-agent".enable = lib.mkForce false; # ssh-agent should be done via home-manager
36}
diff --git a/system-profiles/openssh/host-keys/sif.yaml b/system-profiles/openssh/host-keys/sif.yaml
new file mode 100644
index 00000000..ddef6dd5
--- /dev/null
+++ b/system-profiles/openssh/host-keys/sif.yaml
@@ -0,0 +1,34 @@
1ed25519: ENC[AES256_GCM,data:R7Ejs0DrCJOtEquvxuPCpwrOvV1xwCRtSMgzt7H6Dbv5z3zp94Ei8WKRPfju9dSz/4etHa1FV+1Zy7pAExWOOLU6qvaj4ZQa1FEMnJH76SN974D0hp2TON1l7QS/uRfopJJ0vnzITeCmeQcvvv0Rdz7ZUmyfPv8e76/k3h7FsGndu4wEkVg1/0a+E2dNST+/cp+l8RjXljYTiVLAByaMNz1XoK6wupef40Ce11zAGSmJS57gCwmc2yyq01sgnwex1TeDi+Pd43dTR/21n7AssqnpZGsSqpC4+RzHnxP3YGHN1dLTjHZ5fWW+zEHJZ/lG2eW4Gful+TnQ3fw2SHCjW/9BxpCjzo8GAByuJEr569fRXXAiDnmLG8GXGCpQDgSpjdkL4bFEDs0Uss3ydJEmwL3DaNkr/SHUyovwE2k5KnfIt6v0uEH+HsDSPRQpVoOgn7q3GgDmqwADfGt8MStdFVo3el/s6Rs+Q6r/ukYYu+Mon7Akv7HPGAnHDBSGOPBwy/a5Di3AA0TH/CHCmNdv,iv:HD2JAEUDz5BvZDOMAxb83UjoGZBewdePfSktD5Vh7qw=,tag:CIcXaGYLFeJrp+AU3dpStQ==,type:str]
2rsa: ENC[AES256_GCM,data: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,iv:X57Ayvq6r0m1SGeVrBH8WCZ7TihobLLhy7spX4NIly8=,tag:caDTP5SwuWJAWGpwr9x0eQ==,type:str]
3sops:
4 kms: []
5 gcp_kms: []
6 azure_kv: []
7 hc_vault: []
8 lastmodified: '2021-01-02T19:05:26Z'
9 mac: ENC[AES256_GCM,data:yJGzs0W0R+b6WPkUaQc9cxeTBBEXot0ffUAG77Of88kREFsD5ams9qEDCs8LhPhMtLSH5L8bqMLF28n2w6d9gf41NDBl/oj+XTJE26c4D+MWF2A0fqTvwv1l3524TfavVU8iur0bCbytNfcHSZ3zCQAYElswOGupO+K0Y3hwKKI=,iv:jHSgQV6Jg2Yckp8G0Z23Ny74ZQxZ/+C/neXKrEWUVak=,tag:DhOr2cVhIq8i4JAO+fdXxA==,type:str]
10 pgp:
11 - created_at: '2021-01-02T19:04:29Z'
12 enc: |
13 -----BEGIN PGP MESSAGE-----
14
15 hF4Dgwm4NZSaLAcSAQdArkswGx9w0Rbfp1N89qALAbPMhboirsnlNvms/FomXiUw
16 taW9n4oEJ5oW2UYzNNn72SwF1jYbrqczAbxt3dM9PSz1gHFoh+ZJhGokVFJvJ7sO
17 0l4BEOkWmL/9uyOiCq574nH6OxxTPu9C4GNU8lv/Z/qJ+oAocJkGknsIJzd8M5ax
18 Fo/HqAGGfvnH3RI5FO3tTxfAKlfxlO2MJ2lsCypJuez5WewPnaTPjTbogjhzG2aQ
19 =HXLp
20 -----END PGP MESSAGE-----
21 fp: F1AF20B9511B63F681A14E8D51AEFBCD1DEF68F8
22 - created_at: '2021-01-02T19:04:29Z'
23 enc: |
24 -----BEGIN PGP MESSAGE-----
25
26 hF4DXxoViZlp6dISAQdAUSTwFAciB+Yh2IieFoN/xmQd+GU/g+cuKej6cZk78TUw
27 ETM8c1TSovML5q9usUX0pl/AbRBwp2In47RMkTn4Mul1XxJuXhgCnrc5swwYrS+h
28 0l4BOxJ3bF/yYyKfGrmc/mNe51sdHH+fgQ9IXaQhcopw4kyZqvBXhJF/oP/mhnOL
29 VMhsfg50ol1XmXVefyo5JPedbzABm3vRZv9U+/zvKNJxIro2hWchd5CxvzN4l/MR
30 =30r5
31 -----END PGP MESSAGE-----
32 fp: 30D3453B8CD02FE2A3E7C78C0FB536FB87AE8F51
33 unencrypted_suffix: _unencrypted
34 version: 3.6.1
diff --git a/system-profiles/openssh/known-hosts/sif.nix b/system-profiles/openssh/known-hosts/sif.nix
new file mode 100644
index 00000000..8326d389
--- /dev/null
+++ b/system-profiles/openssh/known-hosts/sif.nix
@@ -0,0 +1,16 @@
1let
2 hostNames = ["sif.asgard.yggdrasil" "sif.faraday.asgard.yggdrasil" "sif.midgard.yggdrasil"];
3in {
4 rsa = {
5 inherit hostNames;
6 publicKey = ''
7 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCeFqJep1CuWakcoiAkz4bSaHbAIwM89Er46o3KUpjCWGTmDmhJyBiG38pupcctH0awwElkX09GsNx230mTtjT6qcxN+vGsGMJIqFD+/7ZobSLJDHYCo6Jx23jZUjg1SqxYjwB5ooWGI61Vh6SaOy8WRrUn0q8rJyd9SEC+3tJlKO5QqRi/Vnwzj47m+YjGz2UlqJ9a4GeRh1O5SiGx5jd4a/VoeK1XJcW94XeWpPQdUGnVYUXZn9cwYVrogmXdr18ImnPxghsQg4xwS2A6KMjUw9m56XkqIq7vTslmL9JaYcjlSCHbsSVq9+Wu1oKxoyndN7Sim7SkAZwHFUEMBNlontBitgYl6z10VdKX739os6h07uXjGEs+mPk4/CkGZhvhnErV2T9FO+65jnU3mZkeX5tfJHqJ8PnDch2JD6O7+Mjpce4zs/x3mwH36peER6iiIBYGlSF0AlUDShdqj+fPWFu6gZ9piOAZ2L3YXDA0ulM6pL69SbulrUNOwtTy6LkBfKDwpaQK1KO1VOYBaKa7s+krOJXW18k+tpfo4aKSeTuwvykMPndKMKvxcsxNymkGo2AzLw017Qgshzv9rRbLNMBFd85S3krakGyBVL0HAVrAdkjvsWqj5FnHAjgBc1AZnZPbJu3g9/wm7k8rPMV0jxKMpW+zxjVFYDhFUWYp9w==
8 '';
9 };
10 ed25519 = {
11 inherit hostNames;
12 publicKey = ''
13 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOfiwlzGcNQjamtIwv7fmXnddjajraeovaM6gRNui1+v
14 '';
15 };
16}
diff --git a/system-profiles/openssh/known-hosts/ymir.nix b/system-profiles/openssh/known-hosts/ymir.nix
new file mode 100644
index 00000000..f29baf1d
--- /dev/null
+++ b/system-profiles/openssh/known-hosts/ymir.nix
@@ -0,0 +1,16 @@
1let
2 hostNames = ["ymir.yggdrasil.li" "ymir.niflheim.yggdrasil"];
3in {
4 rsa = {
5 inherit hostNames;
6 publicKey = ''
7 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDNr7oFNneR3sVuAhdbnU83PuG6gTU6rDmiz+qykkRUr5Qdtm0NIr9lI7nhoO/MaALWmkMXsBGjvJ2UxvY959g0wQRHJZnuJDwOMo3YJjfuDGMTtp8ikzd646uMHQB+y/xb4dou6f0INr94eRsZcji7AQgZQnyWVV3DZuSADBfNK0Tx6sT6IdbJXaCwYoexnfSfzDdu3i5zMuReF4zdkFUEfAdcbOM8Cr0Abnn4+iLVrof/QaOEuZDC+Pf5QUhkAArETdavSCUIbV6+1md0jz/T8yalgrTCsYOoEUbSPwM/8vmiYDWSo/tvAf3KnVIPjjK2UFz7Qu0HyK0y1dBEXoYLGZ1ep4x67aE4zy7GlR2GZdAYilHknugZB+/kvYGDEixHFfcUh/uvF5PY8sm63C6HUBT1s/aQHXGHgE4uUru6YvbU3UW3fRdslABY/atZ9gc3MuKu9Zk27b1SYfAAoK1R8rKsOKWqUWvvMVCfKBNKqqb7+30q75iGeneB8Tb1C9lToyDG2Yl5p+Gpfnj8YmaU/xFm0HFEC42crRbaQyz01LmupHWf8VwH/O2LsjztAF9b4Oe2q/NwqQAF+h5hIm2tfM2fzxHGCmw1sFYf6dEdkyV5pge/IJrnuQn27iO06tRC6tvrt/ocbpwEEOk/3WWpAWW4oT8L5ceh7iAXrCRWpw==
8 '';
9 };
10 ed25519 = {
11 inherit hostNames;
12 publicKey = ''
13 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDeBBux2bIXnS/RUv+Y/NCpzI/SCW0KOJSzf48KDiEZD
14 '';
15 };
16}
diff --git a/system-profiles/sudo.nix b/system-profiles/sudo.nix
new file mode 100644
index 00000000..f2401b9f
--- /dev/null
+++ b/system-profiles/sudo.nix
@@ -0,0 +1,39 @@
1{ ... }:
2{
3 security.sudo.extraRules = [
4 { groups = "wheel";
5 commands = map (command: { inherit command; options = "NOPASSWD"; }) [
6 "/run/current-system/sw/sbin/shutdown"
7 "/run/current-system/sw/sbin/reboot"
8 "/run/current-system/sw/sbin/halt"
9 "/run/current-system/sw/bin/systemctl"
10 ];
11 }
12 ];
13
14 users.extraGroups.network = {};
15
16 security.polkit = {
17 enable = true;
18 extraConfig = ''
19 polkit.addRule(function(action, subject) {
20 if ( action.id == "org.freedesktop.systemd1.manage-units"
21 && subject.isInGroup("wheel")
22 ) {
23 return polkit.Result.YES;
24 }
25 });
26
27 polkit.addRule(function(action, subject) {
28 if ((action.id == "org.blueman.rfkill.setstate" ||
29 action.id == "org.blueman.network.setup" ||
30 action.id == "org.freedesktop.NetworkManager.settings.modify.system"
31 ) && subject.local
32 && subject.active && subject.isInGroup("network")
33 ) {
34 return polkit.Result.YES;
35 }
36 });
37 '';
38 };
39}
diff --git a/users/gkleen/default.nix b/users/gkleen/default.nix
new file mode 100644
index 00000000..03e4a64b
--- /dev/null
+++ b/users/gkleen/default.nix
@@ -0,0 +1,7 @@
1{ userName, pkgs, ... }:
2{
3 users.users.${userName} = {
4 hashedPassword = "$6$rounds=500000$dOMgCU7DAk$yQFYGOURTEt12387LIYBnFKSWmtwXMUk1LJWnV0m7OFt.y2TnxQn2abdGA5dhwG9EmMB5wZGXf4J5F71c746C/";
5 extraGroups = ["wheel" "networkmanager"];
6 };
7}
diff --git a/users/root.nix b/users/root.nix
new file mode 100644
index 00000000..88cc6b26
--- /dev/null
+++ b/users/root.nix
@@ -0,0 +1 @@
import ./gkleen