Skip to content

Instantly share code, notes, and snippets.

@martijnvermaat
Last active March 24, 2024 11:42
Star You must be signed in to star a gist
Save martijnvermaat/76f2e24d0239470dd71050358b4d5134 to your computer and use it in GitHub Desktop.
Installation of NixOS with encrypted root

Installation of NixOS with encrypted root

These are my notes on instaling NixOS 16.03 on a Lenovo ThinkPad X1 Carbon (4th generation) with an encrypted root file system using UEFI.

Most of this is scrambled from the following pages:

Preparing installation media

I installed from a USB stick using the NixOS minimal ISO (this one to be precise).

$ dd bs=4M if=nixos-minimal-16.03.678.2597f52-x86_64-linux.iso of=/dev/sdb

Booting the installer

  • Disable Secure Boot Control
  • Disable USB legacy boot
  • Enable Launch CSM

Due to this kernel bug, we have to boot with the following kernel parameter: intel_pstate=no_hwp. Seems like this will be fixed soon.

Partitioning

We create a 500MB EFI boot partition (/dev/sda1) and the rest will be our LUKS encrypted physical volume for LVM (/dev/sda2).

$ gdisk /dev/sda
  • o (create new empty partition table)
  • n (add partition, 500M, type ef00 EFI)
  • n (add partition, remaining space, type 8300 Linux LVM)
  • w (write partition table and exit)

Setup the encrypted LUKS partition and open it:

$ cryptsetup luksFormat /dev/sda2
$ cryptsetup luksOpen /dev/sda2 enc-pv

We create two logical volumes, a 8GB swap parition and the rest will be our root filesystem

$ pvcreate /dev/mapper/enc-pv
$ vgcreate vg /dev/mapper/enc-pv
$ lvcreate -L 8G -n swap vg
$ lvcreate -l '100%FREE' -n root vg

Format the partitions:

$ mkfs.fat /dev/sda1
$ mkfs.ext4 -L root /dev/vg/root
$ mkswap -L swap /dev/vg/swap

Installing NixOS

We mount the partitions we just created under /mnt so we can install NixOS on them.

$ mount /dev/vg/root /mnt
$ mkdir /mnt/boot
$ mount /dev/sda1 /mnt/boot
$ swapon /dev/vg/swap

Configure WPA supplicant so we can use WIFI:

$ cat > /etc/wpa_supplicant.conf
network={
  ssid="****"
  psk="****"
}
^D
$ systemctl start wpa_supplicant

Now generate a NixOS configuration and modify it to our liking. The following is the configuration I started with.

$ nixos-generate-config --root /mnt
$ cat > /mnt/etc/nixos/configuration.nix
{ config, pkgs, ... }:

{
  imports =
    [ # Include the results of the hardware scan.
      ./hardware-configuration.nix
    ];

  # https://bugzilla.kernel.org/show_bug.cgi?id=110941
  boot.kernelParams = [ "intel_pstate=no_hwp" ];

  # Supposedly better for the SSD.
  fileSystems."/".options = [ "noatime" "nodiratime" "discard" ];

  # Use the GRUB 2 boot loader.
  boot.loader.grub.enable = true;
  boot.loader.grub.version = 2;
  boot.loader.grub.device = "nodev";
  boot.loader.grub.efiSupport = true;
  boot.loader.efi.canTouchEfiVariables = true;

  # Grub menu is painted really slowly on HiDPI, so we lower the
  # resolution. Unfortunately, scaling to 1280x720 (keeping aspect
  # ratio) doesn't seem to work, so we just pick another low one.
  boot.loader.grub.gfxmodeEfi = "1024x768";

  boot.initrd.luks.devices = [
    {
      name = "root";
      device = "/dev/disk/by-uuid/06e7d974-9549-4be1-8ef2-f013efad727e";
      preLVM = true;
      allowDiscards = true;
    }
  ];

  # Enables wireless support via wpa_supplicant.
  networking.wireless.enable = true;

  # Etcetera ...
}

If we're happy with the configuration, install NixOS and reboot.

$ nixos-install
$ reboot

Troubleshooting

If for whatever reason the system doesn't boot, we can go back to the installation environment by booting from the installation media and remounting all partitions:

$ cryptsetup luksOpen /dev/sda2 enc-pv
$ lvchange -a y /dev/vg/swap
$ lvchange -a y /dev/vg/root
$ mount /dev/vg/root /mnt
$ mount /dev/sda1 /mnt/boot
$ swapon /dev/vg/swap
$ cp /mnt/etc/wpa_supplicant.conf /etc
$ systemctl start wpa_supplicant

We can now make further modifications to the configuration and try again.

@timstott
Copy link

In the context of this installation the device UUID is the is the UUID of the partition on /dev/sda2.

[root@nixos:/etc/nixos]# lsblk --fs
NAME                 FSTYPE      LABEL UUID                                   FSAVAIL FSUSE% MOUNTPOINT
sda                                                                                          
├─sda1               vfat              71D0-533E                               468.8M     6% /boot
└─sda2               crypto_LUKS       06e7d974-9549-4be1-8ef2-f013efad727e                  
  └─root             LVM2_member       cPI2OD-d9Kg-d9Zq-VY9W-kPUu-zFY7-wtrZ1N                
    ├─vg-swap swap               swap  8656d2a4-ebf8-4603-854e-ed34fdfb1b3f                  [SWAP]
    └─vg-root ext4               root  fab073dd-d0ee-4855-a897-5327a3b7b3ce    213.7G     2% /
boot.initrd.luks.devices = [
    {
      name = "root";
      device = "/dev/disk/by-uuid/06e7d974-9549-4be1-8ef2-f013efad727e";
      preLVM = true;
      allowDiscards = true;
    }
  ];

@walkermalling
Copy link

Thanks for this write up, and for all the helpful comment, it was invaluable. After running into several issues, I kept my own notes on the step by step commands needed to set this up correctly: https://gist.github.com/walkermalling/23cf138432aee9d36cf59ff5b63a2a58 . These steps are closer to the nixos installation manual, and I've tried to add more annotations. One big issue I ran into was that I had not booted the UEFI boot option on the installation media, and, even though the partitioning and nix config were correct, I had to go into the BIOS boot selection menu and explicitly select the UEFI boot option on my flash drive.

@ErnestKz
Copy link

ErnestKz commented Jan 8, 2021

If nixos-install is not recognising boot.initrd.luks.devices, then NixOS must be 20.04 or over, in that case the updated syntax is:

boot.initrd.luks.devices.luksroot = { device: "..."; preLVM = true; allowDiscards = true; };

@cideM
Copy link

cideM commented Feb 11, 2021

Just in case someone stumbles over this, the UUID for luksroot is the one for the unencrypted luks device, not the volume inside of that. luksroot is what NixOS will use during stage 1 of the boot process to unlock the encrypted device. If you give it the UUID of an actual volume inside the luks container then it'll just say it can't find that device.

@RobWalt
Copy link

RobWalt commented Feb 21, 2022

@cideM Thanks! This helped me a lot!

@stefanDeveloper
Copy link

Thanks!! I have tested it on NixOS 21.11 with the following configuration https://github.com/stefanDeveloper/nixos-lenovo-config and it worked fine for me. As @ErnestKz, I had to adapt the boot.initrd.luks.device.

@jottr
Copy link

jottr commented Feb 21, 2024

  • n (add partition, remaining space, type 8300 Linux LVM)

This is the type code for Linux filesystem. The type code for Linux LVM is 8e00.

@andersk
Copy link

andersk commented Feb 21, 2024

@jottr No, 8e00 is for unencrypted LVM. I commented above about why using 8e00 for an encrypted LUKS partition (that happens to contain LVM) is dangerous.

Beware, using 8e00 “Linux LVM” for an LUKS-encrypted LVM partition might confuse the Debian installer into destroying your partition in certain circumstances! In the apparent absence of a dedicated LUKS code, I went for 8301 “Linux reserved”.

It seems that 8309 has since been assigned to Linux LUKS, so probably use that.

@jottr
Copy link

jottr commented Feb 22, 2024

@andersk thank you for the clarification!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment