Skip to content

Instantly share code, notes, and snippets.

@walkermalling
Last active July 16, 2024 10:59
Show Gist options
  • Save walkermalling/23cf138432aee9d36cf59ff5b63a2a58 to your computer and use it in GitHub Desktop.
Save walkermalling/23cf138432aee9d36cf59ff5b63a2a58 to your computer and use it in GitHub Desktop.
Nix Setup with LUKS encrypted root

Setting up NixOs with LUKS encrypted root

Here are my working notes on getting a system up and running.

WARNING: You can run into a hidden problem that will prevent a correct partition setup and /etc/nixos/configuration.nix from working: if you are setting up a UEFI system, then you need to make sure you boot into the NixOS installation from the UEFI partition of the bootable media. You may have to enter your BIOS boot selection menu to verify this. For example, if you setup a NixOS installer image on a flash drive, your BIOS menu may display several boot options from that flash drive: choose the one explicitly labeled with “UEFI”.

References

I used these resources:

-

Prep Disk

Start by taking a look at block devices and identify the name of the device you’re setting up. Note that adding the --fs flag will show the UUID of each device.

lsblk

Wipe existing fs. on my machine the primary disk is /dev/sda, but it may be different on different machines. Note that Cryptsetup FAQ suggests we use cat /dev/zero > [device target]

sudo wipefs -a /dev/sda

Partition

Create a new partition table

sudo parted /dev/sda -- mklabel gpt

Create the boot partition at the beginning of the disk

sudo parted /dev/sda -- mkpart ESP fat32 1MiB 512MiB
sudo parted /dev/sda -- set 1 boot on

Create primary partition

sudo parted /dev/sda -- mkpart primary 512MiB 100%

Now /dev/sda1 is our boot partition, and /dev/sda2 is our primary.

Encrypt Primary Disk

Setup luks on sda2 (crypted is the label). This will prompt for creating a password.

sudo cryptsetup luksFormat /dev/sda2
sudo cryptsetup luksOpen /dev/sda2 crypted

Map the physical, encrypted volume, then create a new volume group and logical volumes in that group for our nixos root and our swap.

sudo pvcreate /dev/mapper/crypted
sudo vgcreate vg /dev/mapper/crypted
sudo lvcreate -L 8G -n swap vg
sudo lvcreate -l '100%FREE' -n nixos vg

Format Disks

The boot volume will be fat32. The filesystem will be ext4. Also creating a swap.

sudo mkfs.fat -F 32 -n boot /dev/sda1
sudo mkfs.ext4 -L nixos /dev/vg/nixos
sudo mkswap -L swap /dev/vg/swap

Mount

Mount the target file system to /mnt

sudo mount /dev/disk/by-label/nixos /mnt

Mount the boot file system on /mnt/boot for UEFI boot

sudo mkdir -p /mnt/boot
sudo mount /dev/disk/by-label/boot /mnt/boot

Activate swap

sudo swapon /dev/vg/swap

Resulting Disk

Expect the following result:

NAME           MAJ:MIN RM   SIZE RO TYPE  MOUNTPOINT
loop0            7:0    0   1.1G  1 loop  /nix/.ro-store
sda              8:0    0 232.9G  0 disk
├─sda1           8:1    0   511M  0 part  /mnt/boot
└─sda2           8:2    0 232.4G  0 part
  └─crypted    254:0    0 232.4G  0 crypt
    ├─vg-swap  254:1    0     8G  0 lvm   [SWAP]
    └─vg-nixos 254:2    0 224.4G  0 lvm   /mnt

Configure boot

generate configuration

sudo nixos-generate-config --root /mnt

Edit configuration. Here is the part pertinent to luks setup:

{ config, pkgs, ... }:

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

  nixpkgs.config.allowUnfree = true;

  # Use the systemd-boot EFI boot loader.
  boot.loader.systemd-boot.enable = true;
  boot.loader.efi.canTouchEfiVariables = true;

  # grub
  boot.loader.grub = {
    enable = true;
    version = 2;
    efiSupport = true;
    enableCryptodisk = true;
    device = "nodev";
  };

  # luks
  boot.initrd.luks.devices = {
    crypted = {
      device = "/dev/disk/by-uuid/<the uuid of /dev/sda2 in this example>";
      preLVM = true;
    };
  };

  boot.kernelParams = [ "processor.max_cstate=4" "amd_iomu=soft" "idle=nomwait"];
  boot.kernelPackages = pkgs.linuxPackages_latest;
  boot.extraModulePackages = [ config.boot.kernelPackages.nvidia_x11 ];

  ##
  # ...
  ##

  system.stateVersion = "20.03";
}

Note the line boot.loader.grub.device = "nodev"; this is a special value: https://nixos.org/nixos/manual/options.html#opt-boot.loader.grub.device

“The device on which the GRUB boot loader will be installed. The special value nodev means that a GRUB boot menu will be generated, but GRUB itself will not actually be installed.”

Note the absence of boot.loader.efi.efiSysMountPoint = "/boot/efi"; my installation would not succeed if I specified this.

Note that the name of the encrypted filesystem in boot.initrd.luks.devices is the name used in cryptsetup luksOpen and in vgcreate.

Install NixOs

Run the install

sudo nixos-install

If install is successful, you’ll be prompted to set password for root user. Then reboot, and remove installation media.

Login to root, and add add user:

useradd -c 'Me' -m me
passwd me
@ivankovnatsky
Copy link

ivankovnatsky commented Oct 29, 2020

@walkermalling thanks for this, though i've omitted grub section in full for my installation.

@ppenguin
Copy link

@walkermalling thanks, still works for 20.09. For me also without the grub section

@akaihola
Copy link

akaihola commented Dec 2, 2021

The Full Disk Encryption page on the NixOS Wiki says:

  • mount your EFI partition (here /dev/sda1) as /boot/efi.

whereas this Gist does

sudo mount /dev/disk/by-label/boot /mnt/boot

which causes this for me:

# nixos-install
[...]
/nix/store/h9zba9afaxcnpmhvas9cp6hc3lvrjigp-grub-2.06/sbin/grub-install: error: failed to get canonical path of `/boot/efi'.
/nix/store/5fpw2zwv6a03l9ydmh797jhd5ivk93fy-install-grub.pl: installation of GRUB EFI into /boot/efi failed: No such file or directory

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