--- title: Nix & NixOS date: 2020-07-06 --- {% extends 'templates/base.html' %} {% block body %}

{{ title }}

{{ subtitle }}

{% 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 %}