···5let
6 fileSystems = config.system.build.fileSystems ++ config.swapDevices;
7 encDevs = filter (dev: dev.encrypted.enable) fileSystems;
8- keyedEncDevs = filter (dev: dev.encrypted.keyFile != null) encDevs;
9- keylessEncDevs = filter (dev: dev.encrypted.keyFile == null) encDevs;
0000000000000010 anyEncrypted =
11 foldr (j: v: v || j.encrypted.enable) false encDevs;
12···39 type = types.nullOr types.str;
40 description = lib.mdDoc ''
41 Path to a keyfile used to unlock the backing encrypted
42- device. At the time this keyfile is accessed, the
43- `neededForBoot` filesystems (see
44- `fileSystems.<name?>.neededForBoot`)
45- will have been mounted under `/mnt-root`,
46- so the keyfile path should usually start with "/mnt-root/".
00047 '';
48 };
49 };
···62 };
6364 config = mkIf anyEncrypted {
65- assertions = map (dev: {
66- assertion = dev.encrypted.label != null;
67- message = ''
68- The filesystem for ${dev.mountPoint} has encrypted.enable set to true, but no encrypted.label set
69- '';
70- }) encDevs;
0000000000000007172 boot.initrd = {
73 luks = {
74 devices =
75 builtins.listToAttrs (map (dev: {
76 name = dev.encrypted.label;
77- value = { device = dev.encrypted.blkDev; };
78- }) keylessEncDevs);
79 forceLuksSupportInInitrd = true;
80 };
81 postMountCommands =
82 concatMapStrings (dev:
83 "cryptsetup luksOpen --key-file ${dev.encrypted.keyFile} ${dev.encrypted.blkDev} ${dev.encrypted.label};\n"
84- ) keyedEncDevs;
85 };
86 };
87}
···5let
6 fileSystems = config.system.build.fileSystems ++ config.swapDevices;
7 encDevs = filter (dev: dev.encrypted.enable) fileSystems;
8+9+ # With scripted initrd, devices with a keyFile have to be opened
10+ # late, after file systems are mounted, because that could be where
11+ # the keyFile is located. With systemd initrd, each individual
12+ # systemd-cryptsetup@ unit has RequiresMountsFor= to delay until all
13+ # the mount units for the key file are done; i.e. no special
14+ # treatment is needed.
15+ lateEncDevs =
16+ if config.boot.initrd.systemd.enable
17+ then { }
18+ else filter (dev: dev.encrypted.keyFile != null) encDevs;
19+ earlyEncDevs =
20+ if config.boot.initrd.systemd.enable
21+ then encDevs
22+ else filter (dev: dev.encrypted.keyFile == null) encDevs;
23+24 anyEncrypted =
25 foldr (j: v: v || j.encrypted.enable) false encDevs;
26···53 type = types.nullOr types.str;
54 description = lib.mdDoc ''
55 Path to a keyfile used to unlock the backing encrypted
56+ device. When systemd stage 1 is not enabled, at the time
57+ this keyfile is accessed, the `neededForBoot` filesystems
58+ (see `utils.fsNeededForBoot`) will have been mounted under
59+ `/mnt-root`, so the keyfile path should usually start with
60+ "/mnt-root/". When systemd stage 1 is enabled,
61+ `fsNeededForBoot` file systems will be mounted as needed
62+ under `/sysroot`, and the keyfile will not be accessed until
63+ its requisite mounts are done.
64 '';
65 };
66 };
···79 };
8081 config = mkIf anyEncrypted {
82+ assertions = concatMap (dev: [
83+ {
84+ assertion = dev.encrypted.label != null;
85+ message = ''
86+ The filesystem for ${dev.mountPoint} has encrypted.enable set to true, but no encrypted.label set
87+ '';
88+ }
89+ {
90+ assertion =
91+ config.boot.initrd.systemd.enable -> (
92+ dev.encrypted.keyFile == null
93+ || !lib.any (x: lib.hasPrefix x dev.encrypted.keyFile) ["/mnt-root" "$targetRoot"]
94+ );
95+ message = ''
96+ Bad use of '/mnt-root' or '$targetRoot` in 'keyFile'.
97+98+ When 'boot.initrd.systemd.enable' is enabled, file systems
99+ are mounted at '/sysroot' instead of '/mnt-root'.
100+ '';
101+ }
102+ ]) encDevs;
103104 boot.initrd = {
105 luks = {
106 devices =
107 builtins.listToAttrs (map (dev: {
108 name = dev.encrypted.label;
109+ value = { device = dev.encrypted.blkDev; inherit (dev.encrypted) keyFile; };
110+ }) earlyEncDevs);
111 forceLuksSupportInInitrd = true;
112 };
113 postMountCommands =
114 concatMapStrings (dev:
115 "cryptsetup luksOpen --key-file ${dev.encrypted.keyFile} ${dev.encrypted.blkDev} ${dev.encrypted.label};\n"
116+ ) lateEncDevs;
117 };
118 };
119}