Full Disk Encryption
There are a few options for full disk encryption. Below are a few guides for specific cases.
- Installation of NixOS with encrypted root
- Encryption in ZFS
- Using a Yubikey as the authentication mechanism (unattended boot and two factor boot with user password).
- Have a look at https://wiki.archlinux.org/index.php/Disk_encryption to see all the possible options. This wiki page is not complete.
- Installation with encrypted /boot
- Using Tor and SSH to unlock your LUKS Disk over the internet.
Basic Installation
Unattended Boot via USB
Sometimes it is necessary to boot a system without needing an keyboard and monitor. You will create a secret key, add it to a key slot and put it onto an USB stick.
dd if=/dev/urandom of=hdd.key bs=4096 count=1
cryptsetup luksAddKey /dev/sda1 ./hdd.key
Option 1: Write key onto the start of the stick
This will make the usb-stick unusable for any other operations than being used for decryption. Write they key onto the stick: dd if=hdd.key of=/dev/sdb
.
Then add the following configuration to your configuration.nix
:
{
"..."
boot.initrd.luks.devices = [
{
name = "luksroot";
device = "/dev/disk/by-id/<disk-name>-part2";
allowDiscards = true;
keyFileSize = 4096;
# pinning to /dev/disk/by-id/usbkey works
keyFile = "/dev/sdb";
}
];
}
As of right now (2017-08-18) the NixOS options do not provide means to hide a key after the MBR as described in this article in the archlinux forums. More specificially you will need to be able to provide a keyOffset
With NixOS 20.04 the syntax has changed slightly:
{
"..."
boot.initrd.luks.devices.luksroot = {
device = "/dev/disk/by-id/<disk-name>-part2";
allowDiscards = true;
keyFileSize = 4096;
# pinning to /dev/disk/by-id/usbkey works
keyFile = "/dev/sdb";
};
}
Option 2: Copy Key as file onto a vfat usb stick
If you want to use your stick for other stuff or it already has other keys on it you can use the following method by Tzanko Matev. Add this to your configuration.nix
:
let
PRIMARYUSBID = "b501f1b9-7714-472c-988f-3c997f146a17";
BACKUPUSBID = "b501f1b9-7714-472c-988f-3c997f146a18";
in {
"..."
# Kernel modules needed for mounting USB VFAT devices in initrd stage
boot.initrd.kernelModules = ["uas" "usbcore" "usb_storage" "vfat" "nls_cp437" "nls_iso8859_1"];
# Mount USB key before trying to decrypt root filesystem
boot.initrd.postDeviceCommands = pkgs.lib.mkBefore ''
mkdir -m 0755 -p /key
sleep 2 # To make sure the usb key has been loaded
mount -n -t vfat -o ro `findfs UUID=${PRIMARYUSBID}` /key || mount -n -t vfat -o ro `findfs UUID=${BACKUPUSBID}` /key
'';
boot.initrd.luks.devices."crypted" = {
keyFile = "/key/keyfile";
preLVM = false; # If this is true the decryption is attempted before the postDeviceCommands can run
};
}
Option 3: Full disk encryption (encrypted /boot) with password
Partition formatting will be : one partition with LVM on LUKS, and the other in FAT. (EFI partition) The LVM partition contains both the swap and the root filesystem. This only works with LUKS1 partition because Grub doesn't know LUKS2, so make sure to pass the argument --type luks1 to cryptsetup when creating the LUKS partition.
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sda 8:0 0 233.8G 0 disk
├─sda1 8:1 0 500M 0 part /boot/efi
└─sda2 8:2 0 233.3G 0 part
└─root 254:0 0 233.3G 0 crypt
├─vg-swap 254:1 0 8G 0 lvm [SWAP]
└─vg-root 254:2 0 225.3G 0 lvm /
- mount your EFI partition (here /dev/sda1) as /boot/efi. - generate your nixos config - add the following options : (replace TODO by the UUID in /dev/disk/by-uuid pointing to the partition containing the encrypted part. -- You can also do lsblk -f.)
boot.loader.efi.canTouchEfiVariables = true;
boot.loader.grub = {
enable = true;
version = 2;
device = "nodev";
efiSupport = true;
enableCryptodisk = true;
};
boot.loader.efi.efiSysMountPoint = "/boot/efi";
boot.initrd.luks.devices = [
{
name = "root";
device = "/dev/disk/by-uuid/TODO";
preLVM = true;
}
];
zimbatm's laptop recommendation
Let's say that you have a GPT partition with EFI enabled. You might be booting on other OSes with it. Let's say that your disk layout looks something like this:
8 0 500107608 sda
8 1 266240 sda1 - the EFI partition
8 2 16384 sda2
8 3 127388672 sda3
8 4 371409920 sda4 - the NixOS root partition
8 5 1024000 sda5
Boot the NixOS installer and partition things according to your taste. What we are then going to do is prepare sda4 with a luks encryption layer:
# format the disk with the luks structure
$ cryptsetup luksFormat /dev/sda4
# open the encrypted partition and map it to /dev/mapper/cryptroot
$ cryptsetup luksOpen /dev/sda4 cryptroot
# format as usual
$ mkfs.ext4 -L nixos /dev/mapper/cryptroot
# mount
$ mount /dev/disk/by-label/nixos /mnt
$ mkdir /mnt/boot
$ mount /dev/sda1 /mnt/boot
Now keep installing as usual, nixos-generate-config should detect the right partitioning. You should have something like this in your /etc/nixos/hardware-configuration.nix:
{ # cut
fileSystems."/" =
{ device = "/dev/disk/by-uuid/5e7458b3-dcd2-49c6-a330-e2c779e99b66";
fsType = "ext4";
};
boot.initrd.luks.devices."cryptroot".device = "/dev/disk/by-uuid/d2cb12f8-67e3-4725-86c3-0b5c7ebee3a6";
fileSystems."/boot" =
{ device = "/dev/disk/by-uuid/863B-7B32";
fsType = "vfat";
};
swapDevices = [ ];
}
To create a swap add the following in your /etc/nixos/configuration.nix:
{
swapDevices = [{device = "/swapfile"; size = 10000;}];
}
Perf test
# compare
nix-shell -p hdparm --run "hdparm -Tt /dev/mapper/cryptroot"
# with
nix-shell -p hdparm --run "hdparm -Tt /dev/sda1"
I had to add a few modules to initrd to make it fast. Since cryptroot is opened really early on, all the AES descryption modules should already be made available. This obviously depends on the platform that you are on.
{
boot.initrd.availableKernelModules = [
"aes_x86_64"
"aesni_intel"
"cryptd"
];
}