Today I decided to try out NixOS. For my first steps I decided to install it within a VM. I started with the Minimal ISO image and followed the guide on their website.

The first problem I stumbled upon was setting up /etc/nixos/configuration.nix file. The documentation at section 2.4. Installation summary - Example: NixOS Configuration forgets to mention that in case you are using UEFI not only the line

boot.loader.systemd-boot.enable = true;

is needed in configuration.nix, but also the line

boot.loader.efi.canTouchEfiVariables = true;

Update 2022-07-11

The more I play around with it the more I like :). The concept of having one (or more) configuration files to set up the entire system ist very appealing. The next thing is to set up whole disc encryption...

Disclaimer: For the first 'full disc encryption' step the boot partition will not be encrypted and the password has to be typed in at boot.

The NixOS project maintains a wiki where full disc encryption is also described.

So, first thing to do is to partition the disc. For this I chose this layout.

NAME              MAJ:MIN RM  SIZE RO TYPE  MOUNTPOINTS
sda                 8:0    0    8G  0 disk  
+-sda1              8:1    0  511M  0 part  /boot
+-sda2              8:2    0  7.5G  0 part  
  +-crypted       254:0    0  7.5G  0 crypt 
    +-vg_nix-swap 254:1    0    2G  0 lvm   [SWAP]
    +-vg_nix-root 254:2    0  5.5G  0 lvm   /nix/store
                                            /

For this setup in UEFO mode I created

  1. A new GPT partition table:

    parted /dev/sda -- mklabel GPT
    
  2. New partitions (one for UEFI and the another one which will be encrypted):

    parted /dev/sda -- mkpart ESP fat32 1MiB 512MiB
    parted /dev/sda -- mkpart primary 512MiB 100%
    
  3. Mark the first partition as the boot partition:

    parted /dev/sda -- set 1 esp on
    
  4. Create the filesystem for the boot partition:

    mkfs-fat -F 32 -n boot /dev/sda1
    
  5. Now encrypt the second partition using LUKS and create the volume group (LVM) (here for the test I use the LUKS defaults):

    cryptsetup luksFormat /dev/sda2
    cryptsetup luksOpen /dev/sda2 enc
    pvcreate /dev/mapper/enc
    vgcreate vg_nix /dev/mapper/enc
    
  6. Create the logical volumes (2GB swap and the remaining space for /):

    lvcreate -L 2G -n swap vg_nix
    lvcreate -l 100%FREE -n root vg_nix
    
  7. Create the filesystems, turn on swap:

    mkswap -L swap /dev/vg_nix/swap
    mkfs.ext4 -L root /dev/vg_nix/root
    swapon /dev/vg_nix/swap
    
  8. Mount partition and generate /etc/nixos/configuration.nix:

    mount /dev/disk/by-label/root /mnt
    mkdir -p /mnt/boot
    mount /dev/disk/by-label/boot /mnt/boot
    nixos-generate-config --root /mnt
    
  9. The generated config is missing some things. I needed to add:

    boot.loader.efi.canTouchEfiVariables = true;
    boot.loader.grub = {
      enable = true;
      device = "nodev";
      version = 2;
      efiSupport = true;
      enableCryptodisk = true;
    };
    boot.loader.efi.efiSysMountPoint = "/boot/efi";
    boot.initrd.luks.devices = {
      crypted = {
        device = "/dev/disk/by-uuid/45ae009c-5418-4db0-9534-061d551a4419";
        allowDiscards = true;
        preLVM = true;
      };
    };
    };
    

    The uuid can be get with

    [root@nixos:~]$ lsblk -f /dev/sda2
    
  10. and to comment this line

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