{% markdown %}
This article contains tips & tricks for using [NixOS](https://nixos.org).
[TOC]
## Installing NixOS
This guide lays out how to install NixOS with an encrypted root and swap disk.
The resulting system will have 2 physical partitions:
- `/boot`.
- `/dev/mapper/cryptroot`, an encrypted partition with 2 virtual partitions:
- `/dev/vg/root`, mounted as `/`.
- `/dev/vg/swap`, used for swap.
### Physical partitions
First, determine if your machine supports UEFI (most modern PCs), or only has BIOS (e.g. my Thinkpad X201).
If it has UEFI, the below snippet creates a 512MiB UEFI boot partition, which has to be FAT32, and uses the rest of the disk for our cryptroot.
$ parted /dev/sda
> mklabel gpt
> mkpart ESP fat32 1MiB 512MiB
> set 1 boot on
> mkpart primary 512MiB 100%
> quit
For machines without UEFI, the procedure is similar, but needs to use BIOS and MBR formats.
$ parted /dev/sda
> mklabel msdos
> mkpart primary 1MiB 512MiB
> set 1 boot on
> mkpart primary 512MiB 100%
> quit
To set up [LUKS](https://en.wikipedia.org/wiki/Linux_Unified_Key_Setup) disk encryption, first encrypt the second partition (`/dev/sda2`), then unlock it and map it at `/dev/mapper/cryptroot`:
$ cryptsetup luksFormat /dev/sda2
$ cryptsetup open /dev/sda2 cryptroot
### Virtual Partitions
To split our LUKS-encrypted partition into two virtual partitions, we will use [LVM](https://en.wikipedia.org/wiki/Logical_Volume_Manager_(Linux)) to create a _Physical Volume_ containing a _Volume Group_ containing 2 _Logical Volumes_.
Create a Physical Volume (`pv`):
$ pvcreate /dev/mapper/cryptroot
Create a Volume Group (`vg`) on that `pv`:
$ vgcreate vg /dev/mapper/cryptroot
Create two Logical Volumes (`lv`) on that `vg`, one for swap and one for data:
$ lvcreate -L 8G -n swap vg
$ lvcreate -l '100%FREE' -n root vg
### Formatting & Mounting
For UEFI, format the boot partition as FAT32:
$ mkfs.fat -F 32 -n boot /dev/sda1
For BIOS / MBR, format the boot partition as EXT4:
$ mkfs.ext4 -L boot /dev/sda1
For both, format `/` and the swap partition:
$ mkfs.ext4 -L root /dev/vg/root
$ mkswap -L swap /dev/vd/swap
Then mount them all:
$ mount /dev/vg/root /mnt
$ mkdir /mnt/boot
$ mount /dev/sda1 /mnt/boot
$ swapon /dev/vg/swap
### Actually installing NixOS
We will need to make sure that our encrypted physical partition is unencrypted early in boot, so that the virtual partitions can be mounted.
Generate an initial `configuration.nix`:
$ nixos-generate-config --root /mnt
The file `/mnt/etc/nixos/hardware-configuration.nix` should reference the UUIDs for the physical `/dev/sda1` and _logical_ `/dev/vg/root` and `/dev/vg/swap`.
To mount the encrypted LVM partitions early in boot, we need to pass the UUID of the physical partition `/dev/sda2` to `initrd`.
This can be found with `ls -l /dev/disk/by-uuid` and seeing which UUID is pointing to `/dev/sda2`:
$ ls -l /dev/disk/by-uuid
... b2bacfda-0929-43ef-9f8f-c326c41d9126 -> ../../sda1
... 4e906a20-63fc-4aec-93de-8502f24daa91 -> ../../sda2
... 97650361-78bc-4026-962d-0774fc388d63 -> ../../dm-1
... fa099f4f-38b8-4ebc-914c-86b11598128d -> ../../dm-2
This value must then be
$ cat /mnt/etc/nixos/configuration.nix
...
boot.loader.grub.device = "/dev/sda";
boot.initrd.luks.devices.root = {
device = "/dev/disk/by-uuid/4e906a20-63fc-4aec-93de-8502f24daa91";
preLVM = true; # we need to decrypt the physical partition before LVM mounts our logical partitions.
allowDiscards = true; # enables TRIM, optional.
};
Continue NixOS installation, rebooting after:
$ nixos-install
$ reboot
After rebooting, you will need to type your LUKS password, and it should boot normally from there on.
{% endmarkdown %}
{% endblock %}