Full disk encryption with ordering

Hi,

I’m trying to set up multi-level full disk encryption (except for boot) but couldn’t find enough information on how to do it. Following is what I’m trying to set up as the boot process:

  1. Decrypt a USB device with prompt
  2. Decrypt the disk with the keyfile on the usb
  3. Close the decrypted USB device

There are many threads saying that crypttab with boot.initrd.systemd.enable can be used but I couldn’t find any details about how to do it.
The tricky part in the config is that I need to specify ordering of the decryption process but there’s nothing about it in crypttab man page (only x-systemd.device-timeout is supported but I need x-systemd.after to make it work)
Besides, since /nix dir is on the encrypted disk, how can I make sure it is decrypted in stage 1?

I’d appreciate any suggestions or ideas on it!

If you use boot.initrd.systemd.enable, a lot of this will just be automatic. e.g. You can do this:

boot.initrd.luks.device = {
  usb.device = "UUID=asdf";
  root = {
    device = "UUID=hjkl";
    keyFile = "/dev/mapper/usb";
    crypttabExtraOpts = [ "keyfile-size=4096" ];
  };
};

With this, systemd-cryptsetup-generator will automatically add dependencies so this will be ordered correctly, including the root device depending on the usb device being decrypted.

If you’d rather the key be a file on the USB device instead of using the block device itself, you can just use a fancy keyFile

boot.initrd.luks.device = {
  usb.device = "UUID=asdf";
  root = {
    device = "UUID=hjkl";
    # Use the file /key from the /dev/mapper/usb file system
    keyFile = "/key:/dev/mapper/usb";
  };
};
2 Likes

Thanks for the advice! However, I couldn’t use boot.initrd.luks options as I need to use plain type for encryption (without luks).
In crypttab, I could specify plain option directly but not with boot.initrd.luks.

If I configure the crypttab file directly, would it still work in stage 1? (I assume that I may miss some important configuration that comes with boot.initrd.luks)

Oh, I see. Well, with boot.initrd.systemd.enable = true, the name boot.initrd.luks is a bit of a misnomer. It is indeed a thin abstraction over regular ole crypttab. So you can do crypttabExtraOpts = [ "plain" ]; like you would with crypttab (because it is crypttab).

Indeed there are a couple issues with just configuring crypttab manually. For one, you have to configure that file in the initrd, not in stage 2. But you also need to make sure all the relevant binaries and plugins are copied into initrd. It’s easier to just use the boot.initrd.luks wrapper, which, again, is just a frontend for crypttab.

2 Likes

Oh I see. It makes sense. Thanks for your detailed explanation!
I’ll try it out when I get some time.