Full Disk Encryption: Difference between revisions
m Added a link to use tpm2 with disk encryption |
mNo edit summary |
||
| (10 intermediate revisions by 6 users not shown) | |||
| Line 1: | Line 1: | ||
There are a few options for full disk encryption. The easiest way is to use the graphical installer and choose | There are a few options for full disk encryption. The easiest way is to use the graphical installer and choose "encrypt" while doing the installation. | ||
= | = LVM on LUKS = | ||
In this example, everything except for the <code>/boot</code> partition is encrypted. | In this example, everything except for the <code>/boot</code> partition is encrypted. | ||
| Line 22: | Line 22: | ||
└─vg-root 254:2 0 225.3G 0 lvm / | └─vg-root 254:2 0 225.3G 0 lvm / | ||
</syntaxhighlight> | </syntaxhighlight> | ||
== Enter password on Boot == | |||
The initrd needs to be configured to unlock the encrypted <code>/dev/sda2</code> partition during stage 1 of the boot process. | The initrd needs to be configured to unlock the encrypted <code>/dev/sda2</code> partition during stage 1 of the boot process. | ||
| Line 27: | Line 29: | ||
<syntaxhighlight lang="nix"> | <syntaxhighlight lang="nix"> | ||
boot = { | |||
loader = { | |||
efi.canTouchEfiVariables = true; | |||
grub = { | |||
enable = true; | |||
device = "nodev"; | |||
efiSupport = true; | |||
}; | }; | ||
}; | |||
initrd.luks.devices.cryptroot.device = "/dev/disk/by-uuid/UUID-OF-SDA2"; | |||
}; | |||
</syntaxhighlight> | </syntaxhighlight> | ||
With <code lang="nix">initrd.luks.devices.cryptroot.device = "/dev/disk/by-uuid/UUID-OF-SDA2";</code>, the initrd knows it must unlock <code>/dev/sda2</code> before activating LVM and proceeding with the boot process. | With <code lang="nix">initrd.luks.devices.cryptroot.device = "/dev/disk/by-uuid/UUID-OF-SDA2";</code>, the initrd knows it must unlock <code>/dev/sda2</code> before activating LVM and proceeding with the boot process. | ||
= Unattended Boot via USB = | == Unattended Boot via USB == | ||
Sometimes it is necessary to boot a system without needing | Sometimes it is necessary to boot a system without needing a keyboard and monitor. You will create a secret key, add it to a key slot and put it onto a USB stick. | ||
<syntaxhighlight lang= | <syntaxhighlight lang=console> | ||
dd if=/dev/random of=hdd.key bs=4096 count=1 | # dd if=/dev/random of=hdd.key bs=4096 count=1 | ||
cryptsetup luksAddKey /dev/sda1 ./hdd.key | # cryptsetup luksAddKey /dev/sda1 ./hdd.key | ||
</syntaxhighlight>You can enable fallback to password (in case the USB stick is lost or corrupted) by setting the <code>boot.initrd.luks.devices.<name>.fallbackToPassword</code> option to <code>true</code>. By default, this option is <code>false</code> so you will have to perform a manual recovery if the USB stick becomes unavailable (which you may prefer, depending on your use case). | </syntaxhighlight>You can enable fallback to password (in case the USB stick is lost or corrupted) by setting the <code>boot.initrd.luks.devices.<name>.fallbackToPassword</code> option to <code>true</code>. By default, this option is <code>false</code> so you will have to perform a manual recovery if the USB stick becomes unavailable (which you may prefer, depending on your use case). | ||
== Option 1: Write key onto the start of the stick == | === Option 1: Write key onto the start of the stick === | ||
This will make the | This will make the USB stick unusable for any other operations than being used for decryption. Write the key onto the stick: | ||
<syntaxhighlight lang= | <syntaxhighlight lang=console> | ||
dd if=hdd.key of=/dev/sdb | # dd if=hdd.key of=/dev/sdb | ||
</syntaxhighlight> | </syntaxhighlight> | ||
| Line 80: | Line 82: | ||
}</syntaxhighlight> | }</syntaxhighlight> | ||
== Option 2: Copy Key as file onto a vfat | === 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 <code>configuration.nix</code>: | 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 <code>configuration.nix</code>: | ||
| Line 98: | Line 100: | ||
boot.initrd.postDeviceCommands = pkgs.lib.mkBefore '' | boot.initrd.postDeviceCommands = pkgs.lib.mkBefore '' | ||
mkdir -m 0755 -p /key | mkdir -m 0755 -p /key | ||
sleep 2 # To make sure the | 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 | mount -n -t vfat -o ro `findfs UUID=${PRIMARYUSBID}` /key || mount -n -t vfat -o ro `findfs UUID=${BACKUPUSBID}` /key | ||
''; | ''; | ||
| Line 109: | Line 111: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
= Unattended Boot via keyfile = | == Unattended Boot via keyfile == | ||
A simpler but insecure option for unattended boots is to copy the keyfile into the initrd itself. | A simpler but insecure option for unattended boots is to copy the keyfile into the initrd itself. | ||
| Line 116: | Line 118: | ||
First move the key to a safe location. | First move the key to a safe location. | ||
<syntaxhighlight lang= | <syntaxhighlight lang=console> | ||
mkdir /var/lib/secrets | # mkdir /var/lib/secrets | ||
chown root:root /var/lib/secrets | # chown root:root /var/lib/secrets | ||
chmod 700 /var/lib/secrets | # chmod 700 /var/lib/secrets | ||
mv -v hdd.key /var/lib/secrets/ | # mv -v hdd.key /var/lib/secrets/ | ||
chmod 600 /var/lib/secrets/hdd.key | # chmod 600 /var/lib/secrets/hdd.key | ||
</syntaxhighlight> | </syntaxhighlight> | ||
| Line 136: | Line 138: | ||
boot.initrd.secrets = { "/${keyFile}" = /var/lib/secrets/${keyFile}; }; | boot.initrd.secrets = { "/${keyFile}" = /var/lib/secrets/${keyFile}; }; | ||
} | } | ||
</syntaxhighlight> | |||
== Store key on FIDO2 device or TPM == | |||
Unattended boot can also happen with a FIDO2 device (e.g. Yubikey) or TPM. This cannot be performed in a fully declarative way because every such security device is unique; some manual running of <code>systemd-cryptenroll</code> is required. | |||
For FIDO2, directly read the [https://github.com/NixOS/nixpkgs/blob/7be68f763d94cdb4c809b7980647828e3274a511/nixos/doc/manual/configuration/luks-file-systems.section.md chapter in the official manual]. | |||
=== TPM2 === | |||
To store a key on the TPM2 module to unlock the device unattended, first find the UUID values of the encrypted LUKS devices. One way to do this is by running the <code>lsblk</code> command and seeing an output similar to: | |||
<pre> | |||
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS | |||
nvme0n1 259:0 0 1.8T 0 disk | |||
├─nvme0n1p1 259:1 0 1G 0 part /boot | |||
├─nvme0n1p2 259:2 0 1.8T 0 part | |||
│ └─luks-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx 254:1 0 1.8T 0 crypt /nix/store | |||
│ / | |||
└─nvme0n1p3 259:3 0 8G 0 part | |||
└─luks-yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy 254:0 0 7.9G 0 crypt [SWAP] | |||
</pre> | |||
You are looking for devices in the format of <code>luks-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx</code> where <code>xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx</code> is replaced with an actual UUID. There may be multiple of these drives, in which case complete the following step on each device individually if unlocking via TPM2 is desired for all (in this example there are two devices due to the encrypted swap). | |||
Run the following command but replace <code>YOUR-UUID</code> with the UUID you found in the previous step '''without the <code>luks-</code> at the start''': | |||
<syntaxhighlight lang=console> | |||
# systemd-cryptenroll --wipe-slot=tpm2 --tpm2-device=auto /dev/disk/by-uuid/YOUR-UUID | |||
</syntaxhighlight> | |||
Now the device should unlock without prompting you for the password. After this is working, you should add certain restrictions to your saved key using Platform Configuration Registers (PCR). All options for these can be found at the [https://uapi-group.org/specifications/specs/linux_tpm_pcr_registry/ Linux TPM PCR Registry]. If using the default <code>systemd-boot</code> without [[Secure Boot]], then a standard set of options to use is <code>4+9+12</code>. This can be applied by running the above command again with <code>--tpm2-pcrs=4+9+12</code>. If your system uses secure boot with [[Limine]] you may want to use <code>--tpm2-pcrs=4+7+8+9</code> instead. | |||
Because the TPM is attached to your computer, it provides no protection against a stolen computer when used on its own (it usually allows for setting a password, but that is it). It can only protect against a stolen drive. | |||
= Encrypted /boot = | |||
[https://libreboot.org/ Libreboot] supports decrypting boot partition with built-in GRUB. | |||
Example layout of unified LUKS-encrypted btrfs partition: | |||
* boot subvolume mounted at /boot | |||
* home subvolume mounted at /home | |||
* nix subvolume mounted at /nix | |||
* swap subvolume mounted at /swap | |||
NixOS-generated grub.cfg may cause problems when loaded with Libreboot GRUB, so using extlinux configuration file is recommended instead.<syntaxhighlight lang="nix"> | |||
boot.loader.grub.enable = false; | |||
boot.loader.generic-extlinux-compatible.enable = true; | |||
</syntaxhighlight>Partition can be decrypted and booted with following GRUB commands:<syntaxhighlight lang="console"> | |||
# cryptomount -a | |||
# try_bootcfg crypto0 # assuming configuration file is located at /boot/extlinux/extlinux.conf | |||
</syntaxhighlight> | </syntaxhighlight> | ||
| Line 153: | Line 203: | ||
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: | 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: | ||
<syntaxhighlight lang= | <syntaxhighlight lang=console> | ||
# format the partition with the luks structure | # # format the partition with the luks structure | ||
cryptsetup luksFormat /dev/sda4 | # cryptsetup luksFormat /dev/sda4 | ||
# open the encrypted partition and map it to /dev/mapper/cryptroot | # # open the encrypted partition and map it to /dev/mapper/cryptroot | ||
cryptsetup luksOpen /dev/sda4 cryptroot | # cryptsetup luksOpen /dev/sda4 cryptroot | ||
# format as usual | # # format as usual | ||
mkfs.ext4 -L nixos /dev/mapper/cryptroot | # mkfs.ext4 -L nixos /dev/mapper/cryptroot | ||
# mount | # # mount | ||
mount /dev/disk/by-label/nixos /mnt | # mount /dev/disk/by-label/nixos /mnt | ||
mkdir /mnt/boot | # mkdir /mnt/boot | ||
mount /dev/sda1 /mnt/boot | # mount /dev/sda1 /mnt/boot | ||
</syntaxhighlight> | </syntaxhighlight> | ||
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: | 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: | ||
{{file|configuration.nix|nix|3= | |||
{ # cut | { # cut | ||
fileSystems."/" = | fileSystems."/" = | ||
| Line 184: | Line 234: | ||
swapDevices = [ ]; | swapDevices = [ ]; | ||
} | } | ||
}} | |||
To create a swap add the following in your /etc/nixos/configuration.nix: | To create a swap add the following in your /etc/nixos/configuration.nix: | ||
{{file|configuration.nix|nix|3= | |||
{ | { | ||
swapDevices = [{device = "/swapfile"; size = 10000;}]; | swapDevices = [{device = "/swapfile"; size = 10000;}]; | ||
} | } | ||
}} | |||
== Perf test == | == Perf test == | ||
<syntaxhighlight lang= | <syntaxhighlight lang=console> | ||
# compare | $ # compare | ||
nix-shell -p hdparm --run "hdparm -Tt /dev/mapper/cryptroot" | $ nix-shell -p hdparm --run "hdparm -Tt /dev/mapper/cryptroot" | ||
# with | $ # with | ||
nix-shell -p hdparm --run "hdparm -Tt /dev/sda1" | $ nix-shell -p hdparm --run "hdparm -Tt /dev/sda1" | ||
</syntaxhighlight> | </syntaxhighlight> | ||
| Line 218: | Line 268: | ||
Encrypt the drive and create the filesystem on it (LVM is used in this example): | Encrypt the drive and create the filesystem on it (LVM is used in this example): | ||
<syntaxhighlight lang= | <syntaxhighlight lang=console> | ||
cryptsetup luksFormat --label CRYPTSTORAGE /dev/sdb | # cryptsetup luksFormat --label CRYPTSTORAGE /dev/sdb | ||
cryptsetup open /dev/sdb cryptstorage | # cryptsetup open /dev/sdb cryptstorage | ||
pvcreate /dev/mapper/cryptstorage | # pvcreate /dev/mapper/cryptstorage | ||
vgcreate vg-storage /dev/mapper/cryptstorage | # vgcreate vg-storage /dev/mapper/cryptstorage | ||
lvcreate -l 100%FREE -n storage vg-storage | # lvcreate -l 100%FREE -n storage vg-storage | ||
mkfs.ext4 -L STORAGE /dev/vg-storage/storage | # mkfs.ext4 -L STORAGE /dev/vg-storage/storage | ||
</syntaxhighlight> | </syntaxhighlight> | ||
| Line 248: | Line 298: | ||
First, create a keyfile for your secondary drive, store it safely and add it as a LUKS key: | First, create a keyfile for your secondary drive, store it safely and add it as a LUKS key: | ||
<syntaxhighlight lang= | <syntaxhighlight lang=console> | ||
dd bs=512 count=4 if=/dev/random of=/root/mykeyfile.key iflag=fullblock | # dd bs=512 count=4 if=/dev/random of=/root/mykeyfile.key iflag=fullblock | ||
chmod 400 /root/mykeyfile.key | # chmod 400 /root/mykeyfile.key | ||
cryptsetup luksAddKey /dev/sdb /root/mykeyfile.key | # cryptsetup luksAddKey /dev/sdb /root/mykeyfile.key | ||
</syntaxhighlight> | </syntaxhighlight> | ||
| Line 276: | Line 326: | ||
* [[Remote disk unlocking|Using Tor and SSH to unlock your LUKS Disk over the internet]]. | * [[Remote disk unlocking|Using Tor and SSH to unlock your LUKS Disk over the internet]]. | ||
* [[Bcachefs]], filesystem which supports native encryption | * [[Bcachefs]], filesystem which supports native encryption | ||
* [https://discourse.nixos.org/t/full-disk-encryption-tpm2/29454/2 Automatically unlock encrypted disks using | * [https://discourse.nixos.org/t/full-disk-encryption-tpm2/29454/2 Automatically unlock encrypted disks using TPM2] | ||
[[Category:Desktop]] | [[Category:Desktop]] | ||
[[Category:Server]] | [[Category:Server]] | ||