summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--accounts/gkleen@eos.nix25
-rw-r--r--accounts/mherold@eos.nix19
-rw-r--r--accounts/mherold@eos/default.nix1
-rw-r--r--deploy/eos.nix1
-rw-r--r--hosts/eos/default.nix101
-rw-r--r--hosts/eos/ruleset.nft101
-rw-r--r--hosts/vidhar/default.nix46
-rw-r--r--hosts/vidhar/network/dhcp/default.nix28
-rw-r--r--hosts/vidhar/samba.nix25
-rw-r--r--hosts/vidhar/zfs.nix12
-rw-r--r--installer-profiles/nfsroot.nix118
-rw-r--r--installer/default.nix2
-rw-r--r--system-profiles/nfsroot.nix114
13 files changed, 446 insertions, 147 deletions
diff --git a/accounts/gkleen@eos.nix b/accounts/gkleen@eos.nix
index c157af78..dbe48ead 100644
--- a/accounts/gkleen@eos.nix
+++ b/accounts/gkleen@eos.nix
@@ -1 +1,24 @@
1{ ... }: {} 1{ flake, userName, pkgs, ... }:
2{
3 imports = with flake.nixosModules.userProfiles.${userName}; [
4 zsh utils tmux
5 ];
6
7 config.home-manager.users.${userName} = {
8 nixpkgs.config = {
9 allowUnfree = true;
10 };
11
12 home.packages = with pkgs; [
13 thunderbird libreoffice element-desktop keepassxc
14 ];
15
16 programs.firefox = {
17 enable = true;
18 profiles.default.settings = {
19 "dom.security.https_only_mode" = true;
20 "browser.cache.disk.enable" = false;
21 };
22 };
23 };
24}
diff --git a/accounts/mherold@eos.nix b/accounts/mherold@eos.nix
new file mode 100644
index 00000000..6d376835
--- /dev/null
+++ b/accounts/mherold@eos.nix
@@ -0,0 +1,19 @@
1{ userName, pkgs, ... }: {
2 config.home-manager.users.${userName} = {
3 nixpkgs.config = {
4 allowUnfree = true;
5 };
6
7 home.packages = with pkgs; [
8 thunderbird libreoffice element-desktop keepassxc
9 ];
10
11 programs.firefox = {
12 enable = true;
13 profiles.default.settings = {
14 "dom.security.https_only_mode" = true;
15 "browser.cache.disk.enable" = false;
16 };
17 };
18 };
19}
diff --git a/accounts/mherold@eos/default.nix b/accounts/mherold@eos/default.nix
deleted file mode 100644
index c157af78..00000000
--- a/accounts/mherold@eos/default.nix
+++ /dev/null
@@ -1 +0,0 @@
1{ ... }: {}
diff --git a/deploy/eos.nix b/deploy/eos.nix
new file mode 100644
index 00000000..65a4c7ed
--- /dev/null
+++ b/deploy/eos.nix
@@ -0,0 +1 @@
{ ... }: { enabled = false; }
diff --git a/hosts/eos/default.nix b/hosts/eos/default.nix
new file mode 100644
index 00000000..1c5347e7
--- /dev/null
+++ b/hosts/eos/default.nix
@@ -0,0 +1,101 @@
1{ flake, config, pkgs, lib, ... }:
2
3with lib;
4
5{
6 imports = with flake.nixosModules.systemProfiles; [
7 nfsroot
8 ];
9
10 config = {
11 nixpkgs = {
12 system = "x86_64-linux";
13 config = {
14 allowUnfree = true;
15 };
16 };
17
18 boot = {
19 initrd = {
20 availableKernelModules = [ "nvme" "ahci" "xhci_pci" "usbhid" "sd_mod" "sr_mod" ];
21 kernelModules = [ "igb" ];
22 };
23 kernelModules = [ "kvm-amd" ];
24 extraModulePackages = [ ];
25
26 plymouth.enable = true;
27
28 tmpOnTmpfs = true;
29 };
30
31 hardware = {
32 enableRedistributableFirmware = true;
33 cpu.amd.updateMicrocode = config.hardware.enableRedistributableFirmware;
34
35 nvidia = {
36 modesetting.enable = true;
37 powerManagement.enable = true;
38 };
39
40 opengl.enable = true;
41 };
42
43 environment.etc."machine-id".text = "f457b21333f1491e916521151ff5d468";
44
45 networking = {
46 hostId = "f457b213";
47
48 domain = "asgard.yggdrasil";
49 search = [ "asgard.yggdrasil" "yggdrasil" ];
50
51 hosts = {
52 "127.0.0.1" = [ "eos.asgard.yggdrasil" "eos" ];
53 "::1" = [ "eos.asgard.yggdrasil" "eos" ];
54 };
55
56 firewall.enable = false;
57 nftables = {
58 enable = true;
59 rulesetFile = ./ruleset.nft;
60 };
61 };
62
63 services.resolved = {
64 llmnr = "false";
65 };
66
67 zramSwap.enable = true;
68
69 system.stateVersion = config.system.nixos.release; # No state
70
71
72 time.timeZone = "Europe/Berlin";
73 time.hardwareClockInLocalTime = true;
74 i18n.defaultLocale = "en_DK.UTF-8";
75
76
77 environment.systemPackages = with pkgs; [ cifs-utils ];
78
79 security.pam.mount = {
80 enable = true;
81 extraVolumes = [
82 "<volume sgrp=\"users\" fstype=\"cifs\" server=\"vidhar.lan.yggdrasil\" path=\"home-eos\" mountpoint=\"~\" />"
83 "<volume sgrp=\"users\" fstype=\"cifs\" server=\"vidhar.lan.yggdrasil\" path=\"%(USER)\" mountpoint=\"/run/media/%(USER)/vidhar\" />"
84 ];
85 };
86
87
88 services.xserver = {
89 enable = true;
90 displayManager.sddm = {
91 enable = true;
92 settings = {
93 Users.HideUsers = "gkleen";
94 };
95 };
96 desktopManager.plasma5.enable = true;
97
98 videoDrivers = [ "nvidia" ];
99 };
100 };
101}
diff --git a/hosts/eos/ruleset.nft b/hosts/eos/ruleset.nft
new file mode 100644
index 00000000..7b38a059
--- /dev/null
+++ b/hosts/eos/ruleset.nft
@@ -0,0 +1,101 @@
1define icmp_protos = {ipv6-icmp, icmp, igmp}
2
3table arp filter {
4 limit lim_arp {
5 rate over 50 mbytes/second burst 50 mbytes
6 }
7
8 chain input {
9 type filter hook input priority filter
10 policy accept
11
12 limit name lim_arp counter drop
13
14 counter
15 }
16
17 chain output {
18 type filter hook output priority filter
19 policy accept
20
21 limit name lim_arp counter drop
22
23 counter
24 }
25}
26
27table inet filter {
28 limit lim_reject {
29 rate over 1000/second burst 1000 packets
30 }
31
32 limit lim_icmp {
33 rate over 50 mbytes/second burst 50 mbytes
34 }
35
36
37 chain forward {
38 type filter hook forward priority filter
39 policy drop
40
41
42 ct state invalid log level debug prefix "drop invalid forward: " counter drop
43
44
45 iifname lo counter accept
46
47
48 limit name lim_reject log level debug prefix "drop forward: " counter drop
49 log level debug prefix "reject forward: " counter
50 meta l4proto tcp ct state new counter reject with tcp reset
51 ct state new counter reject
52
53
54 counter
55 }
56
57 chain input {
58 type filter hook input priority filter
59 policy drop
60
61
62 ct state invalid log level debug prefix "drop invalid input: " counter drop
63
64
65 iifname lo counter accept
66 iif != lo ip daddr 127.0.0.1/8 counter reject
67 iif != lo ip6 daddr ::1/128 counter reject
68
69 meta l4proto $icmp_protos limit name lim_icmp counter drop
70 meta l4proto $icmp_protos counter accept
71
72 tcp dport 22 counter accept
73 udp dport 60000-61000 counter accept
74
75
76 ct state {established, related} counter accept
77
78
79 limit name lim_reject log level debug prefix "drop input: " counter drop
80 log level debug prefix "reject input: " counter
81 meta l4proto tcp ct state new counter reject with tcp reset
82 ct state new counter reject
83
84
85 counter
86 }
87
88 chain output {
89 type filter hook output priority filter
90 policy accept
91
92
93 oifname lo counter accept
94
95 meta l4proto $icmp_protos limit name lim_icmp counter drop
96 meta l4proto $icmp_protos counter accept
97
98
99 counter
100 }
101} \ No newline at end of file
diff --git a/hosts/vidhar/default.nix b/hosts/vidhar/default.nix
index 3f5d17d5..fc77f03c 100644
--- a/hosts/vidhar/default.nix
+++ b/hosts/vidhar/default.nix
@@ -235,25 +235,30 @@ with lib;
235 ]; 235 ];
236 }; 236 };
237 }; 237 };
238 systemd.services.loki.preStart = let 238 systemd.services.loki = {
239 rulesYaml = generators.toYAML {} { 239 preStart = let
240 groups = [ 240 rulesYaml = generators.toYAML {} {
241 { name = "power-failures"; 241 groups = [
242 rules = [ 242 { name = "power-failures";
243 { record = "apcupsd_power_failures:per_day"; 243 rules = [
244 expr = "sum by (nodename) (rate({job=\"systemd-journal\"} | json | MESSAGE = \"Power failure.\"[1d])) * 86400"; 244 { record = "apcupsd_power_failures:per_day";
245 } 245 expr = "sum by (nodename) (rate({job=\"systemd-journal\"} | json | MESSAGE = \"Power failure.\"[1d])) * 86400";
246 { record = "apcupsd_power_failures:per_week"; 246 }
247 expr = "sum by (nodename) (rate({job=\"systemd-journal\"} | json | MESSAGE = \"Power failure.\"[1w])) * 604800"; 247 { record = "apcupsd_power_failures:per_week";
248 } 248 expr = "sum by (nodename) (rate({job=\"systemd-journal\"} | json | MESSAGE = \"Power failure.\"[1w])) * 604800";
249 ]; 249 }
250 } 250 ];
251 ]; 251 }
252 }; 252 ];
253 in '' 253 };
254 ${pkgs.coreutils}/bin/install -m 0755 -o ${config.services.loki.user} -g ${config.services.loki.group} -d ${config.services.loki.configuration.ruler.storage.local.directory}/fake 254 in ''
255 ${pkgs.coreutils}/bin/ln -sf ${pkgs.writeText "rules.yml" rulesYaml} ${config.services.loki.configuration.ruler.storage.local.directory}/fake/rules.yml 255 ${pkgs.coreutils}/bin/install -m 0755 -o ${config.services.loki.user} -g ${config.services.loki.group} -d ${config.services.loki.configuration.ruler.storage.local.directory}/fake
256 ''; 256 ${pkgs.coreutils}/bin/ln -sf ${pkgs.writeText "rules.yml" rulesYaml} ${config.services.loki.configuration.ruler.storage.local.directory}/fake/rules.yml
257 '';
258 serviceConfig.Environment = [
259 "ASSUME_NO_MOVING_GC_UNSAFE_RISK_IT_WITH=go1.19"
260 ];
261 };
257 services.promtail = { 262 services.promtail = {
258 enable = true; 263 enable = true;
259 configuration = { 264 configuration = {
@@ -286,6 +291,9 @@ with lib;
286 ]; 291 ];
287 }; 292 };
288 }; 293 };
294 systemd.services.promtail.serviceConfig.Environment = [
295 "ASSUME_NO_MOVING_GC_UNSAFE_RISK_IT_WITH=go1.19"
296 ];
289 297
290 services.apcupsd = { 298 services.apcupsd = {
291 enable = true; 299 enable = true;
diff --git a/hosts/vidhar/network/dhcp/default.nix b/hosts/vidhar/network/dhcp/default.nix
index dfaa4c9f..d3407f1d 100644
--- a/hosts/vidhar/network/dhcp/default.nix
+++ b/hosts/vidhar/network/dhcp/default.nix
@@ -23,6 +23,12 @@ with lib;
23 }; 23 };
24 24
25 client-classes = [ 25 client-classes = [
26 { name = "eos-ipxe";
27 test = "hexstring(pkt4.mac, ':') == '00:d8:61:79:c5:40' and option[77].hex == 'iPXE'";
28 next-server = "10.141.0.1";
29 boot-file-name = "http://nfsroot.vidhar.yggdrasil/eos/netboot.ipxe";
30 only-if-required = true;
31 }
26 { name = "ipxe"; 32 { name = "ipxe";
27 test = "option[77].hex == 'iPXE'"; 33 test = "option[77].hex == 'iPXE'";
28 next-server = "10.141.0.1"; 34 next-server = "10.141.0.1";
@@ -85,7 +91,7 @@ with lib;
85 ddns-send-updates = true; 91 ddns-send-updates = true;
86 ddns-qualifying-suffix = "lan.yggdrasil"; 92 ddns-qualifying-suffix = "lan.yggdrasil";
87 pools = [ { pool = "10.141.0.128 - 10.141.0.254"; } ]; 93 pools = [ { pool = "10.141.0.128 - 10.141.0.254"; } ];
88 require-client-classes = ["ipxe" "uefi-64" "uefi-32" "legacy"]; 94 require-client-classes = map (cc: cc.name) config.services.kea.dhcp4.settings.client-classes;
89 reservations = [ 95 reservations = [
90 { hostname = "sif"; 96 { hostname = "sif";
91 hw-address = "3c:e1:a1:52:24:35"; 97 hw-address = "3c:e1:a1:52:24:35";
@@ -258,7 +264,25 @@ with lib;
258 ${pkgs.closureInfo { rootPaths = installerBuild.storeContents; }}/registration 264 ${pkgs.closureInfo { rootPaths = installerBuild.storeContents; }}/registration
259 '') 265 '')
260 ) ["x86_64-linux"] 266 ) ["x86_64-linux"]
261 ); 267 ) ++ [
268 (let
269 eosBuild = (flake.nixosConfigurations.eos.extendModules {
270 modules = [
271 ({ ... }: {
272 config.nfsroot.storeDevice = "10.141.0.1:nix-store";
273 config.nfsroot.registrationUrl = "http://nfsroot.vidhar.yggdrasil/eos/registration";
274 })
275 ];
276 }).config.system.build;
277 in builtins.toPath (pkgs.runCommandLocal "eos" {} ''
278 mkdir -p $out/eos
279 install -m 0444 -t $out/eos \
280 ${eosBuild.initialRamdisk}/initrd \
281 ${eosBuild.kernel}/bzImage \
282 ${eosBuild.netbootIpxeScript}/netboot.ipxe \
283 ${pkgs.closureInfo { rootPaths = eosBuild.storeContents; }}/registration
284 ''))
285 ];
262 }; 286 };
263 }; 287 };
264 }; 288 };
diff --git a/hosts/vidhar/samba.nix b/hosts/vidhar/samba.nix
index 0ddf56a3..ffca9c6d 100644
--- a/hosts/vidhar/samba.nix
+++ b/hosts/vidhar/samba.nix
@@ -14,28 +14,45 @@
14 guest account = nobody 14 guest account = nobody
15 bind interfaces only = yes 15 bind interfaces only = yes
16 interfaces = lo lan 16 interfaces = lo lan
17 server signing = mandatory
18 server min protocol = SMB3
19 server smb encrypt = required
17 ''; 20 '';
18 shares = { 21 shares = {
19 homes = { 22 homes = {
20 comment = "Home Directories"; 23 comment = "Home directory for %S";
21 path = "/home/%S"; 24 path = "/home/%S";
22 browseable = "no"; 25 browseable = false;
23 "valid users" = "%S"; 26 "valid users" = "%S";
24 "read only" = "no"; 27 "read only" = false;
25 "create mask" = "0700"; 28 "create mask" = "0700";
26 "directory mask" = "0700"; 29 "directory mask" = "0700";
27 "vfs objects" = "shadow_copy2"; 30 "vfs objects" = "shadow_copy2";
28 "shadow:snapdir" = ".zfs/snapshot"; 31 "shadow:snapdir" = ".zfs/snapshot";
32 "shadow:snapdirseverywhere" = true;
29 "shadow:sort" = "desc"; 33 "shadow:sort" = "desc";
30 "shadow:format" = "%Y-%m-%dT%H:%M:%SZ"; 34 "shadow:format" = "%Y-%m-%dT%H:%M:%SZ";
31 }; 35 };
32 eos = { 36 eos = {
33 comment = "Disk image of eos"; 37 comment = "Disk image of legacy eos";
34 browseable = true; 38 browseable = true;
35 "valid users" = "mherold"; 39 "valid users" = "mherold";
36 writeable = "true"; 40 writeable = "true";
37 path = "/srv/eos"; 41 path = "/srv/eos";
38 }; 42 };
43 home-eos = {
44 comment = "Home directoriy for %u on PXE booted EOS";
45 path = "/srv/cifs/home-eos/%u";
46 volume = "%u@eos";
47 browseable = true;
48 "read only" = false;
49 "create mask" = "0700";
50 "directory mask" = "0700";
51 "vfs objects" = "shadow_copy2";
52 "shadow:snapdir" = ".zfs/snapshot";
53 "shadow:sort" = "desc";
54 "shadow:format" = "%Y-%m-%dT%H:%M:%SZ";
55 };
39 }; 56 };
40 }; 57 };
41 services.samba-wsdd = { 58 services.samba-wsdd = {
diff --git a/hosts/vidhar/zfs.nix b/hosts/vidhar/zfs.nix
index 52b48aca..1de4b9b7 100644
--- a/hosts/vidhar/zfs.nix
+++ b/hosts/vidhar/zfs.nix
@@ -23,7 +23,7 @@
23 fsType = "zfs"; 23 fsType = "zfs";
24 neededForBoot = true; 24 neededForBoot = true;
25 }; 25 };
26 26
27 "/var/lib/nixos" = 27 "/var/lib/nixos" =
28 { device = "ssd-raid1/local/var-lib-nixos"; 28 { device = "ssd-raid1/local/var-lib-nixos";
29 fsType = "zfs"; 29 fsType = "zfs";
@@ -34,22 +34,22 @@
34 { device = "ssd-raid1/local/var-lib-unbound"; 34 { device = "ssd-raid1/local/var-lib-unbound";
35 fsType = "zfs"; 35 fsType = "zfs";
36 }; 36 };
37 37
38 # "/var/lib/dhcp" = 38 # "/var/lib/dhcp" =
39 # { device = "ssd-raid1/local/var-lib-dhcp"; 39 # { device = "ssd-raid1/local/var-lib-dhcp";
40 # fsType = "zfs"; 40 # fsType = "zfs";
41 # }; 41 # };
42 42
43 "/var/lib/chrony" = 43 "/var/lib/chrony" =
44 { device = "ssd-raid1/local/var-lib-chrony"; 44 { device = "ssd-raid1/local/var-lib-chrony";
45 fsType = "zfs"; 45 fsType = "zfs";
46 }; 46 };
47 47
48 "/var/lib/samba" = 48 "/var/lib/samba" =
49 { device = "ssd-raid1/local/var-lib-samba"; 49 { device = "ssd-raid1/local/var-lib-samba";
50 fsType = "zfs"; 50 fsType = "zfs";
51 }; 51 };
52 52
53 # "/var/lib/prometheus2" = 53 # "/var/lib/prometheus2" =
54 # { device = "ssd-raid1/local/var-lib-prometheus2"; 54 # { device = "ssd-raid1/local/var-lib-prometheus2";
55 # fsType = "zfs"; 55 # fsType = "zfs";
@@ -67,7 +67,7 @@
67 # fsType = "zfs"; 67 # fsType = "zfs";
68 # options = [ "zfsutil" ]; 68 # options = [ "zfsutil" ];
69 # }; 69 # };
70 70
71 # "/srv/tftp" = 71 # "/srv/tftp" =
72 # { device = "ssd-raid1/local/srv-tftp"; 72 # { device = "ssd-raid1/local/srv-tftp";
73 # fsType = "zfs"; 73 # fsType = "zfs";
diff --git a/installer-profiles/nfsroot.nix b/installer-profiles/nfsroot.nix
index 2688a8d0..6bd875b4 100644
--- a/installer-profiles/nfsroot.nix
+++ b/installer-profiles/nfsroot.nix
@@ -1,121 +1,11 @@
1{ config, pkgs, lib, flakeInputs, ... }: 1{ flakeInputs, flake, ... }:
2 2
3with lib; 3{
4 4 imports = with flake.nixosModules.systemProfiles; [
5let 5 nfsroot
6 cfg = config.nfsroot;
7in {
8 imports = [
9 "${flakeInputs.nixpkgs.outPath}/nixos/modules/profiles/minimal.nix" 6 "${flakeInputs.nixpkgs.outPath}/nixos/modules/profiles/minimal.nix"
10 "${flakeInputs.nixpkgs.outPath}/nixos/modules/profiles/all-hardware.nix" 7 "${flakeInputs.nixpkgs.outPath}/nixos/modules/profiles/all-hardware.nix"
11 "${flakeInputs.nixpkgs.outPath}/nixos/modules/profiles/base.nix" 8 "${flakeInputs.nixpkgs.outPath}/nixos/modules/profiles/base.nix"
12 "${flakeInputs.nixpkgs.outPath}/nixos/modules/profiles/installation-device.nix" 9 "${flakeInputs.nixpkgs.outPath}/nixos/modules/profiles/installation-device.nix"
13 ]; 10 ];
14
15 options = {
16 nfsroot = {
17 storeDevice = mkOption {
18 type = types.str;
19 default = "nfsroot:nix-store";
20 };
21
22 registrationUrl = mkOption {
23 type = types.str;
24 default = "http://nfsroot/nix-registration";
25 };
26 };
27
28 system.build = {
29 storeContents = mkOption {};
30 };
31 };
32
33 config = {
34 # Don't build the GRUB menu builder script, since we don't need it
35 # here and it causes a cyclic dependency.
36 boot.loader.grub.enable = false;
37
38 # !!! Hack - attributes expected by other modules.
39 environment.systemPackages = [ pkgs.grub2_efi ]
40 ++ (if pkgs.stdenv.hostPlatform.system == "aarch64-linux"
41 then []
42 else [ pkgs.grub2 pkgs.syslinux ]);
43
44 fileSystems."/" = mkImageMediaOverride
45 { fsType = "tmpfs";
46 options = [ "mode=0755" ];
47 };
48
49 # In stage 1, mount a tmpfs on top of /nix/store (the squashfs
50 # image) to make this a live CD.
51 fileSystems."/nix/.ro-store" = mkImageMediaOverride
52 { fsType = "nfs4";
53 device = cfg.storeDevice;
54 options = [ "ro" ];
55 neededForBoot = true;
56 };
57
58 fileSystems."/nix/.rw-store" = mkImageMediaOverride
59 { fsType = "tmpfs";
60 options = [ "mode=0755" ];
61 neededForBoot = true;
62 };
63
64 fileSystems."/nix/store" = mkImageMediaOverride
65 { fsType = "overlay";
66 device = "overlay";
67 options = [
68 "lowerdir=/nix/.ro-store"
69 "upperdir=/nix/.rw-store/store"
70 "workdir=/nix/.rw-store/work"
71 ];
72
73 depends = [
74 "/nix/.ro-store"
75 "/nix/.rw-store/store"
76 "/nix/.rw-store/work"
77 ];
78 };
79
80 nix.extraOptions = ''
81 use-sqlite-wal = false
82 '';
83
84 boot.initrd.availableKernelModules = [ "nfs" "nfsv4" "overlay" ];
85 boot.initrd.supportedFilesystems = [ "nfs" "nfsv4" "overlay" ];
86 services.rpcbind.enable = mkImageMediaOverride false;
87
88 boot.initrd.network.enable = true;
89 boot.initrd.network.flushBeforeStage2 = false; # otherwise nfs doesn't work
90 boot.initrd.postMountCommands = ''
91 mkdir -p /mnt-root/etc/
92 cp /etc/resolv.conf /mnt-root/etc/resolv.conf
93 '';
94 networking.useDHCP = true;
95 networking.resolvconf.enable = false;
96
97
98 system.build.storeContents = [config.system.build.toplevel];
99
100 system.build.netbootIpxeScript = pkgs.writeTextDir "netboot.ipxe" ''
101 #!ipxe
102 # Use the cmdline variable to allow the user to specify custom kernel params
103 # when chainloading this script from other iPXE scripts like netboot.xyz
104 kernel ${pkgs.stdenv.hostPlatform.linux-kernel.target} init=${config.system.build.toplevel}/init initrd=initrd ${toString config.boot.kernelParams} ''${cmdline}
105 initrd initrd
106 boot
107 '';
108
109 boot.postBootCommands =
110 ''
111 # After booting, register the contents of the Nix store on NFS
112 # in the Nix database in the tmpfs.
113 ${pkgs.curl}/bin/curl ${escapeShellArg cfg.registrationUrl} | ${config.nix.package.out}/bin/nix-store --load-db
114
115 # nixos-rebuild also requires a "system" profile and an
116 # /etc/NIXOS tag.
117 touch /etc/NIXOS
118 ${config.nix.package}/bin/nix-env -p /nix/var/nix/profiles/system --set /run/current-system
119 '';
120 };
121} 11}
diff --git a/installer/default.nix b/installer/default.nix
index f882b22d..a0c84182 100644
--- a/installer/default.nix
+++ b/installer/default.nix
@@ -4,6 +4,8 @@
4 ]; 4 ];
5 5
6 config = { 6 config = {
7 hardware.cpu.amd.updateMicrocode = config.hardware.enableRedistributableFirmware;
8
7 networking = { 9 networking = {
8 firewall.enable = false; 10 firewall.enable = false;
9 nftables = { 11 nftables = {
diff --git a/system-profiles/nfsroot.nix b/system-profiles/nfsroot.nix
new file mode 100644
index 00000000..92cf98de
--- /dev/null
+++ b/system-profiles/nfsroot.nix
@@ -0,0 +1,114 @@
1{ config, pkgs, lib, flakeInputs, ... }:
2
3with lib;
4
5let
6 cfg = config.nfsroot;
7in {
8 options = {
9 nfsroot = {
10 storeDevice = mkOption {
11 type = types.str;
12 default = "nfsroot:nix-store";
13 };
14
15 registrationUrl = mkOption {
16 type = types.str;
17 default = "http://nfsroot/nix-registration";
18 };
19 };
20
21 system.build = {
22 storeContents = mkOption {};
23 };
24 };
25
26 config = {
27 # Don't build the GRUB menu builder script, since we don't need it
28 # here and it causes a cyclic dependency.
29 boot.loader.grub.enable = false;
30
31 # !!! Hack - attributes expected by other modules.
32 environment.systemPackages = [ pkgs.grub2_efi ]
33 ++ (if pkgs.stdenv.hostPlatform.system == "aarch64-linux"
34 then []
35 else [ pkgs.grub2 pkgs.syslinux ]);
36
37 fileSystems."/" = mkImageMediaOverride
38 { fsType = "tmpfs";
39 options = [ "mode=0755" ];
40 };
41
42 # In stage 1, mount a tmpfs on top of /nix/store (the squashfs
43 # image) to make this a live CD.
44 fileSystems."/nix/.ro-store" = mkImageMediaOverride
45 { fsType = "nfs4";
46 device = cfg.storeDevice;
47 options = [ "ro" ];
48 neededForBoot = true;
49 };
50
51 fileSystems."/nix/.rw-store" = mkImageMediaOverride
52 { fsType = "tmpfs";
53 options = [ "mode=0755" ];
54 neededForBoot = true;
55 };
56
57 fileSystems."/nix/store" = mkImageMediaOverride
58 { fsType = "overlay";
59 device = "overlay";
60 options = [
61 "lowerdir=/nix/.ro-store"
62 "upperdir=/nix/.rw-store/store"
63 "workdir=/nix/.rw-store/work"
64 ];
65
66 depends = [
67 "/nix/.ro-store"
68 "/nix/.rw-store/store"
69 "/nix/.rw-store/work"
70 ];
71 };
72
73 nix.extraOptions = ''
74 use-sqlite-wal = false
75 '';
76
77 boot.initrd.availableKernelModules = [ "nfs" "nfsv4" "overlay" ];
78 boot.initrd.supportedFilesystems = [ "nfs" "nfsv4" "overlay" ];
79 services.rpcbind.enable = mkImageMediaOverride false;
80
81 boot.initrd.network.enable = true;
82 boot.initrd.network.flushBeforeStage2 = false; # otherwise nfs doesn't work
83 boot.initrd.postMountCommands = ''
84 mkdir -p /mnt-root/etc/
85 cp /etc/resolv.conf /mnt-root/etc/resolv.conf
86 '';
87 networking.useDHCP = true;
88 networking.resolvconf.enable = false;
89
90
91 system.build.storeContents = [config.system.build.toplevel];
92
93 system.build.netbootIpxeScript = pkgs.writeTextDir "netboot.ipxe" ''
94 #!ipxe
95 # Use the cmdline variable to allow the user to specify custom kernel params
96 # when chainloading this script from other iPXE scripts like netboot.xyz
97 kernel ${pkgs.stdenv.hostPlatform.linux-kernel.target} init=${config.system.build.toplevel}/init initrd=initrd ${toString config.boot.kernelParams} ''${cmdline}
98 initrd initrd
99 boot
100 '';
101
102 boot.postBootCommands =
103 ''
104 # After booting, register the contents of the Nix store on NFS
105 # in the Nix database in the tmpfs.
106 ${pkgs.curl}/bin/curl ${escapeShellArg cfg.registrationUrl} | ${config.nix.package.out}/bin/nix-store --load-db
107
108 # nixos-rebuild also requires a "system" profile and an
109 # /etc/NIXOS tag.
110 touch /etc/NIXOS
111 ${config.nix.package}/bin/nix-env -p /nix/var/nix/profiles/system --set /run/current-system
112 '';
113 };
114}