Apr 28, 2026 Infrastructure

NixOS: Installation Guide with RAID 1, encryption, and TPM unlock (part 1)

5 reading minutes
Output of the lsblk and parted commands

It is time to migrate from Ubuntu to NixOS!

For a long time, I have been using Nix on Ubuntu through Home Manager, and I have been automating my dotfiles more and more, steadily removing my custom setup and using Nix instead. Recently, I adopted the new System Manager project, whose goal is to bring system-level configuration to operating systems other than NixOS, where it was previously only available.

After quite a while on that journey, and after already migrating my home servers, it is time to move to NixOS and leave Ubuntu behind.

I want to live on the edge of what is new and configure my Linux exactly the way I want, and NixOS will let me do that. I have also come to really like the way it keeps configuration in versioned file systems that I can control in detail.

This post will show how to meet what I consider the bare minimum for security: I am going to create a NixOS system with an encrypted disk, mirrored with RAID 1, using the most modern file system available right now (btrfs), and use the TPM to decrypt the system without human interaction.

Already know NixOS, TPM, btrfs, and the rest, and just want the code? It is free and available in a repository on my Codeberg. The README explains what is going on, but I will go into more detail here on the blog, explaining the concepts in more depth. This will be a series of posts, where I intend to explain each piece.

The plan is to do something like this:

  1. Creating the VM and the initial partitions (this post)
  2. More information about Disko, LUKS and btrfs
  3. Installing NixOS
  4. Preparing Secure Boot
  5. Using the TPM to decrypt the disks
  6. Mitigating the volume-swapping attack
  7. Mitigating the OS-swapping attack
  8. Review and conclusions

I am sure the plan will fall apart, but it gives you an idea of what I intend to cover.

In this first part, we will prepare the VM and the initial partitions.

Preparing the virtual machine

I am on Ubuntu 24, using Virtual Machine Manager 5.1, installed through NixOS. Adapt this to your own OS setup.

Download the NixOS ISO. I used the graphical ISO, but I imagine the minimal image should work just fine too.

I chose to create the disks ahead of time with qemu-img, because it creates disks that do not consume all the reserved space right away; they grow as needed (sparse files). I noticed that when creating the disks through the VMM UI, it creates them with the full size by default, unless you go through the custom storage option, where there is a checkbox for “Allocate entire volume now”. In any case, I prefer the command line, so I will leave it here for reference. In my case, I will keep the VM files under /mnt/data/vms/vmm, so adapt that to whatever directory you prefer.

cd /mnt/data/vms/vmm
qemu-img create -f qcow2 nixos1-1.qcow2 200G
qemu-img create -f qcow2 nixos1-2.qcow2 200G

Copy the downloaded .iso into that same directory.

Create the virtual machine with those two disks and with the NixOS ISO. Configure the TPM for version 2. Enable the boot menu. Configure the network as NAT. If you want to see my configuration, it is available in nixos.xml.

Delete all Secure Boot keys and disable Secure Boot in the VM, because the installer does not have a signed .efi file and will not boot with Secure Boot enabled.

To do that: when the VM starts, press ESC to enter the boot menu. Then choose “Device Manager” and “Secure Boot Configuration”. Select “Reset Secure Boot Keys” and confirm. That will disable Secure Boot as well. Go back to the main menu and choose “Reset”, which will restart the boot process. It is possible that during this process it will eject the virtual installation CD (.iso); add it back in the VM settings and restart it.

Starting the installation

Choose one of the installation options. I went with Gnome and the latest Kernel, but I imagine it will make little difference; all we need is a shell. When the installer opens, close it and open a terminal.

From that point on, you can continue from that terminal.

Tip: I preferred to connect via SSH, since that makes it easier to copy and paste commands into the terminal. To do that, create a password with passwd. Find the VM IP with ip a and connect to it from the host with ssh nixos@<ip>.

Declarative partitioning with Disko

First, check the current partition status with lsblk -f.

I am using Disko to create the partitions and file systems.

Clone the repository into ~/nixos: https://codeberg.org/giggio/nixos_raid_btrfs_luks_tpm

git clone https://codeberg.org/giggio/nixos_raid_btrfs_luks_tpm.git ~/nixos
cd ~/nixos
git checkout 397fb28 # checkout the commit with message "Updated config"
# create the partitions
sudo nix --experimental-features "nix-command flakes" run github:nix-community/disko/latest -- --mode destroy,format,mount ~/nixos/disko.nix
# check the results
lsblk -f
sudo fdisk -l /dev/vd{a,b}
# or
sudo parted /dev/vda print all

See the file used by Disko: disko.nix. Note that the password is luks, and it comes from the file luks-password.txt.

In the next post, I will explain in more detail what Disko did. For now, I can say that it already created two partitions on each disk: one partition for EFI (ESP) and another for Linux, which will be encrypted using LUKS, and will internally use btrfs, with subvolumes already created. I will explain all of that later.

For now, enjoy figuring out how Disko managed to do all that with just one file. That is the beauty of NixOS: no endless command typing in the terminal, everything is versioned and declarative.

See you in the next post.



Did you find a problem in the text? Send me an improvement suggestion. This code is free.

Fork me on Codeberg