blob: 2688a8d04a80c38372d8358121dbd2948625d758 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
|
{ config, pkgs, lib, flakeInputs, ... }:
with lib;
let
cfg = config.nfsroot;
in {
imports = [
"${flakeInputs.nixpkgs.outPath}/nixos/modules/profiles/minimal.nix"
"${flakeInputs.nixpkgs.outPath}/nixos/modules/profiles/all-hardware.nix"
"${flakeInputs.nixpkgs.outPath}/nixos/modules/profiles/base.nix"
"${flakeInputs.nixpkgs.outPath}/nixos/modules/profiles/installation-device.nix"
];
options = {
nfsroot = {
storeDevice = mkOption {
type = types.str;
default = "nfsroot:nix-store";
};
registrationUrl = mkOption {
type = types.str;
default = "http://nfsroot/nix-registration";
};
};
system.build = {
storeContents = mkOption {};
};
};
config = {
# Don't build the GRUB menu builder script, since we don't need it
# here and it causes a cyclic dependency.
boot.loader.grub.enable = false;
# !!! Hack - attributes expected by other modules.
environment.systemPackages = [ pkgs.grub2_efi ]
++ (if pkgs.stdenv.hostPlatform.system == "aarch64-linux"
then []
else [ pkgs.grub2 pkgs.syslinux ]);
fileSystems."/" = mkImageMediaOverride
{ fsType = "tmpfs";
options = [ "mode=0755" ];
};
# In stage 1, mount a tmpfs on top of /nix/store (the squashfs
# image) to make this a live CD.
fileSystems."/nix/.ro-store" = mkImageMediaOverride
{ fsType = "nfs4";
device = cfg.storeDevice;
options = [ "ro" ];
neededForBoot = true;
};
fileSystems."/nix/.rw-store" = mkImageMediaOverride
{ fsType = "tmpfs";
options = [ "mode=0755" ];
neededForBoot = true;
};
fileSystems."/nix/store" = mkImageMediaOverride
{ fsType = "overlay";
device = "overlay";
options = [
"lowerdir=/nix/.ro-store"
"upperdir=/nix/.rw-store/store"
"workdir=/nix/.rw-store/work"
];
depends = [
"/nix/.ro-store"
"/nix/.rw-store/store"
"/nix/.rw-store/work"
];
};
nix.extraOptions = ''
use-sqlite-wal = false
'';
boot.initrd.availableKernelModules = [ "nfs" "nfsv4" "overlay" ];
boot.initrd.supportedFilesystems = [ "nfs" "nfsv4" "overlay" ];
services.rpcbind.enable = mkImageMediaOverride false;
boot.initrd.network.enable = true;
boot.initrd.network.flushBeforeStage2 = false; # otherwise nfs doesn't work
boot.initrd.postMountCommands = ''
mkdir -p /mnt-root/etc/
cp /etc/resolv.conf /mnt-root/etc/resolv.conf
'';
networking.useDHCP = true;
networking.resolvconf.enable = false;
system.build.storeContents = [config.system.build.toplevel];
system.build.netbootIpxeScript = pkgs.writeTextDir "netboot.ipxe" ''
#!ipxe
# Use the cmdline variable to allow the user to specify custom kernel params
# when chainloading this script from other iPXE scripts like netboot.xyz
kernel ${pkgs.stdenv.hostPlatform.linux-kernel.target} init=${config.system.build.toplevel}/init initrd=initrd ${toString config.boot.kernelParams} ''${cmdline}
initrd initrd
boot
'';
boot.postBootCommands =
''
# After booting, register the contents of the Nix store on NFS
# in the Nix database in the tmpfs.
${pkgs.curl}/bin/curl ${escapeShellArg cfg.registrationUrl} | ${config.nix.package.out}/bin/nix-store --load-db
# nixos-rebuild also requires a "system" profile and an
# /etc/NIXOS tag.
touch /etc/NIXOS
${config.nix.package}/bin/nix-env -p /nix/var/nix/profiles/system --set /run/current-system
'';
};
}
|