mirror of
https://github.com/TECHNOFAB11/disko.git
synced 2025-12-11 23:50:05 +01:00
If the keyfile attribute is not present it will omit any keyfile luks configuration and instead will make the user be prompted for any passphrases.
169 lines
5.3 KiB
Nix
169 lines
5.3 KiB
Nix
{ lib }:
|
|
with lib;
|
|
with builtins;
|
|
|
|
let {
|
|
|
|
body.config = config-f {};
|
|
body.create = create-f {};
|
|
body.mount = mount-f {};
|
|
|
|
|
|
helper.find-device = device: let
|
|
environment = helper.device-id device;
|
|
in
|
|
# DEVICE points already to /dev/disk, so we don't handle it via /dev/disk/by-path
|
|
if hasPrefix "/dev/disk" device then
|
|
"${environment}='${device}'"
|
|
else ''
|
|
${environment}=$(for x in /dev/disk/by-path/*; do
|
|
dev=$x
|
|
if [ "$(readlink -f $x)" = '${device}' ]; then
|
|
target=$dev
|
|
break
|
|
fi
|
|
done
|
|
if test -z $target; then
|
|
echo 'unable to find path of disk: ${device}, bailing out' >&2
|
|
exit 1
|
|
else
|
|
echo $target
|
|
fi)
|
|
'';
|
|
|
|
helper.device-id = device: "DEVICE${builtins.substring 0 5 (builtins.hashString "sha1" device)}";
|
|
|
|
config-f = q: x: config.${x.type} q x;
|
|
|
|
config.filesystem = q: x: {
|
|
fileSystems.${x.mountpoint} = {
|
|
device = q.device;
|
|
fsType = x.format;
|
|
${if x ? options then "options" else null} = x.options;
|
|
};
|
|
};
|
|
|
|
config.devices = q: x:
|
|
foldl' recursiveUpdate {} (mapAttrsToList (name: config-f { device = "/dev/${name}"; }) x.content);
|
|
|
|
config.luks = q: x: {
|
|
boot.initrd.luks.devices.${x.name}.device = q.device;
|
|
} // config-f { device = "/dev/mapper/${x.name}"; } x.content;
|
|
|
|
config.lv = q: x:
|
|
config-f { device = "/dev/mapper/${q.vgname}-${q.name}"; } x.content;
|
|
|
|
config.lvm = q: x:
|
|
foldl' recursiveUpdate {} (mapAttrsToList (name: config-f { inherit name; vgname = x.name; }) x.lvs);
|
|
|
|
config.noop = q: x: {};
|
|
|
|
config.partition = q: x:
|
|
config-f { device = q.device + toString q.index; } x.content;
|
|
|
|
config.table = q: x:
|
|
foldl' recursiveUpdate {} (imap (index: config-f (q // { inherit index; })) x.partitions);
|
|
|
|
|
|
create-f = q: x: create.${x.type} q x;
|
|
|
|
create.filesystem = q: x: ''
|
|
mkfs.${x.format} ${q.device}
|
|
'';
|
|
|
|
create.devices = q: x: ''
|
|
${concatStrings (mapAttrsToList (name: create-f { device = "/dev/${name}"; }) x.content)}
|
|
'';
|
|
|
|
create.luks = q: x: ''
|
|
cryptsetup -q luksFormat ${q.device} ${if builtins.hasAttr "keyfile" x then x.keyfile else ""} ${toString (x.extraArgs or [])}
|
|
cryptsetup luksOpen ${q.device} ${x.name} ${if builtins.hasAttr "keyfile" x then "--key-file " + x.keyfile else ""}
|
|
${create-f { device = "/dev/mapper/${x.name}"; } x.content}
|
|
'';
|
|
|
|
create.lv = q: x: ''
|
|
lvcreate -L ${x.size} -n ${q.name} ${q.vgname}
|
|
${create-f { device = "/dev/mapper/${q.vgname}-${q.name}"; } x.content}
|
|
'';
|
|
|
|
create.lvm = q: x: ''
|
|
pvcreate ${q.device}
|
|
vgcreate ${x.name} ${q.device}
|
|
${concatStrings (mapAttrsToList (name: create-f { inherit name; vgname = x.name; }) x.lvs)}
|
|
'';
|
|
|
|
create.noop = q: x: "";
|
|
|
|
create.partition = q: x: let
|
|
env = helper.device-id q.device;
|
|
in ''
|
|
parted -s "''${${env}}" mkpart ${x.part-type} ${x.fs-type or ""} ${x.start} ${x.end}
|
|
# ensure /dev/disk/by-path/..-partN exists before continuing
|
|
udevadm trigger --subsystem-match=block; udevadm settle
|
|
${optionalString (x.bootable or false) ''
|
|
parted -s "''${${env}}" set ${toString q.index} boot on
|
|
''}
|
|
${concatMapStringsSep "" (flag: ''
|
|
parted -s "''${${env}}" set ${toString q.index} ${flag} on
|
|
'') (x.flags or [])}
|
|
${create-f { device = "\"\${${env}}\"-part" + toString q.index; } x.content}
|
|
'';
|
|
|
|
create.table = q: x: ''
|
|
${helper.find-device q.device}
|
|
parted -s "''${${helper.device-id q.device}}" mklabel ${x.format}
|
|
${concatStrings (imap (index: create-f (q // { inherit index; })) x.partitions)}
|
|
'';
|
|
|
|
|
|
mount-f = q: x: mount.${x.type} q x;
|
|
|
|
mount.filesystem = q: x: {
|
|
fs.${x.mountpoint} = ''
|
|
if ! findmnt ${q.device} "/mnt${x.mountpoint}" > /dev/null 2>&1; then
|
|
mount ${q.device} "/mnt${x.mountpoint}" -o X-mount.mkdir
|
|
fi
|
|
'';
|
|
};
|
|
|
|
mount.devices = q: x: let
|
|
z = foldl' recursiveUpdate {} (mapAttrsToList (name: mount-f { device = "/dev/${name}"; }) x.content);
|
|
# attrValues returns values sorted by name. This is important, because it
|
|
# ensures that "/" is processed before "/foo" etc.
|
|
in ''
|
|
${optionalString (hasAttr "table" z) (concatStringsSep "\n" (attrValues z.table))}
|
|
${optionalString (hasAttr "luks" z) (concatStringsSep "\n" (attrValues z.luks))}
|
|
${optionalString (hasAttr "lvm" z) (concatStringsSep "\n" (attrValues z.lvm))}
|
|
${optionalString (hasAttr "fs" z) (concatStringsSep "\n" (attrValues z.fs))}
|
|
'';
|
|
|
|
mount.luks = q: x: (
|
|
recursiveUpdate
|
|
(mount-f { device = "/dev/mapper/${x.name}"; } x.content)
|
|
{luks.${q.device} = ''
|
|
cryptsetup luksOpen ${q.device} ${x.name} ${if builtins.hasAttr "keyfile" x then "--key-file " + x.keyfile else ""}
|
|
'';}
|
|
);
|
|
|
|
mount.lv = q: x:
|
|
mount-f { device = "/dev/mapper/${q.vgname}-${q.name}"; } x.content;
|
|
|
|
mount.lvm = q: x: (
|
|
recursiveUpdate
|
|
(foldl' recursiveUpdate {} (mapAttrsToList (name: mount-f { inherit name; vgname = x.name; }) x.lvs))
|
|
{lvm.${q.device} = ''
|
|
vgchange -a y
|
|
'';}
|
|
);
|
|
|
|
mount.noop = q: x: {};
|
|
|
|
mount.partition = q: x:
|
|
mount-f { device = "\"\${${q.device}}\"-part" + toString q.index; } x.content;
|
|
|
|
mount.table = q: x: (
|
|
recursiveUpdate
|
|
(foldl' recursiveUpdate {} (imap (index: mount-f (q // { inherit index; device = helper.device-id q.device; })) x.partitions))
|
|
{table.${q.device} = helper.find-device q.device;}
|
|
);
|
|
}
|