1{ config, lib, ... }:
2
3with lib;
4
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;
10 isIn = needle: haystack: filter (p: p == needle) haystack != [];
11 anyEncrypted =
12 fold (j: v: v || j.encrypted.enable) false encDevs;
13
14 encryptedFSOptions = {
15
16 encrypted = {
17 enable = mkOption {
18 default = false;
19 type = types.bool;
20 description = "The block device is backed by an encrypted one, adds this device as a initrd luks entry.";
21 };
22
23 blkDev = mkOption {
24 default = null;
25 example = "/dev/sda1";
26 type = types.nullOr types.str;
27 description = "Location of the backing encrypted device.";
28 };
29
30 label = mkOption {
31 default = null;
32 example = "rootfs";
33 type = types.nullOr types.str;
34 description = "Label of the unlocked encrypted device. Set <literal>fileSystems.<name?>.device</literal> to <literal>/dev/mapper/<label></literal> to mount the unlocked device.";
35 };
36
37 keyFile = mkOption {
38 default = null;
39 example = "/root/.swapkey";
40 type = types.nullOr types.str;
41 description = "File system location of keyfile. This unlocks the drive after the root has been mounted to <literal>/mnt-root</literal>.";
42 };
43 };
44 };
45in
46
47{
48
49 options = {
50 fileSystems = mkOption {
51 options = [encryptedFSOptions];
52 };
53 swapDevices = mkOption {
54 options = [encryptedFSOptions];
55 };
56 };
57
58 config = mkIf anyEncrypted {
59 boot.initrd = {
60 luks = {
61 devices =
62 map (dev: { name = dev.encrypted.label; device = dev.encrypted.blkDev; } ) keylessEncDevs;
63 cryptoModules = [ "aes" "sha256" "sha1" "xts" ];
64 };
65 postMountCommands =
66 concatMapStrings (dev: "cryptsetup luksOpen --key-file ${dev.encrypted.keyFile} ${dev.encrypted.blkDev} ${dev.encrypted.label};\n") keyedEncDevs;
67 };
68 };
69}
70