Summary
It has been many months since I had decided to update my HTPC running NixOS. Sadly, failing to update the HTPC machine as new NixOS versions became available left my machine’s OS version too far back and now no longer compatible with the current version of my NixOS config. I was left with many errors when attempting to upgrade and some may not have been resolvable due to some packages requiring newer compilers that were not available on the system. After a couple hours of debugging I realized this was not worth the effort and decided to simply scrap the system and reinstall. This new install will be just about the simplest install possible, so it is a good starting point.
The process
For those who know installing NixOS is just not as simple as installing any more friendly distro. I have also only kept scratch notes for myself on how to handle the install process, so I decided to document it mostly for myself here. I am also writing this post install so I am aware of some steps I missed (one really big one), so there will be a round two later on.
Setting up the storage
I opted for BTRFS RAID-0 with two 1TB NVME SSDs. I used RAID-0 as redundancy is not required at all, this machine will not store any data that does not exist else where if a drive dies I simply do not care. With that in mind below are the step I went through to prepare the system.
Order of operations
- Setup boot partition
- Setup swap
- Setup bulk storage
- Setup BTRFS volumes
- Mount storage for installation
- Generate a hardware config file
- Merge new configuration into current
- Install
Setup boot partition:
First I setup just a very basic fat32 boot partition.
parted /dev/disk/by-id/nvme-eui.0025385b0140445b -- mklabel gpt
parted /dev/disk/by-id/nvme-eui.0025385b0140445b -- mkpart ESP fat32 1MiB 1GiB
parted /dev/disk/by-id/nvme-eui.0025385b0140445b -- set 1 boot on
mkfs.vfat /dev/disk/by-id/nvme-eui.0025385b0140445b-part1
Setup swap:
I setup a Swap partition on the same device, again, nothing special or new.
parted /dev/disk/by-id/nvme-eui.0025385b0140445b -- mkpart Swap linux-swap 1GiB 33GiB
mkswap -L Swap /dev/disk/by-id/nvme-eui.0025385b0140445b-part2
swapon /dev/disk/by-id/nvme-eui.0025385b0140445b-part2
Setup bulk storage:
In this step I create the third partition, on the first device, and I create a single partition on the second device. After creating both partitions and their filesystems, I mount one to /mnt
, then I add the second device’s first partition to /mnt
. After adding the two devices together I balance them and convert to RAID-1, they have no data at this point so this only takes a second.
# Setup bulk storage on first device
parted /dev/disk/by-id/nvme-eui.0025385b0140445b -- mkpart primary 33GiB 100%
mkfs.btrfs -L Butter /dev/disk/by-id/nvme-eui.0025385b0140445b-part3
# Setup second disk
parted /dev/disk/by-id/nvme-eui.0025385791b269cc -- mklabel gpt
parted /dev/disk/by-id/nvme-eui.0025385791b269cc -- mkpart primary 0% 100%
mkfs.btrfs -L Butter /dev/disk/by-id/nvme-eui.0025385791b269cc-part1
# Add second device to bulk storage
mount -t btrfs /dev/disk/by-id/nvme-eui.0025385b0140445b-part3 /mnt
btrfs device add /dev/disk/by-id/nvme-eui.0025385791b269cc-part1 /mnt -f
btrfs balance start -dconvert=raid0 -mconvert=raid0 /mnt
Setup BTRFS volumes:
With the BTRFS filesystems mounted, I create the subvolumes I intend on using, and then unmount /mnt
.
btrfs subvolume create /mnt/nix
btrfs subvolume create /mnt/etc
btrfs subvolume create /mnt/log
btrfs subvolume create /mnt/root
btrfs subvolume create /mnt/home
umount /mnt
Mount storage for installation:
Now I mount /mnt
as a tmpfs
, and create directories that correspond to the subvolumes I made above, and mount each subvolume to its respective folder.
mount -t tmpfs -o mode=755 none /mnt
mkdir -p /mnt/{boot,nix,etc,log,root,home}
mount /dev/disk/by-id/nvme-eui.0025385b0140445b-part1 /mnt/boot
mount -o subvol=nix,compress-force=zstd /dev/disk/by-id/nvme-eui.0025385b0140445b-part3 /mnt/nix
mount -o subvol=etc,compress-force=zstd /dev/disk/by-id/nvme-eui.0025385b0140445b-part3 /mnt/etc
mount -o subvol=log,compress-force=zstd /dev/disk/by-id/nvme-eui.0025385b0140445b-part3 /mnt/log
mount -o subvol=root,compress-force=zstd /dev/disk/by-id/nvme-eui.0025385b0140445b-part3 /mnt/root
mount -o subvol=home,compress-force=zstd /dev/disk/by-id/nvme-eui.0025385b0140445b-part3 /mnt/home
Generate a hardware config file:
Because I am lazy I use nixos-generate-config
to create a hardware-configuration.nix
file.
nixos-generate-config --root /mnt
Merge new configuration into current:
This is where I will leave new users in the dark. I already have a working version controlled Nix config, I only want the hardware-configuration.nix
for this host. Steps below are missing, but the goal is to show I took the config off the live install system, merged the config into my working Nix config on my desktop, then copied it all back to the live system.
scp -r root@<ip>:/mnt/etc/nixos/*.nix /etc/nixos
After getting the hardware-configuration.nix
file merged into my working config I needed to edit the file to add compress=zstd
to each mounted BTRFS volumes options
, like below:
fileSystems."/home" = {
device = "/dev/disk/by-uuid/e67b5ff4-835c-41ab-bc7b-4d6dde2c4254";
fsType = "btrfs";
options = [ "subvol=home" "compress=zstd" ];
};
After everything was merged, I pushed it all back to the live system.
scp -r /etc/nixos root@<ip>:/mnt/etc/nixos/*.nix
Install:
Finally I installed the system.
nixos-install
Round two fixes
I only had a couple hours to install NixOS and that was not enough to decipher my scratch notes entirely, as a result I noticed I missed one CRITICAL issue: I forgot to encrypt BTRFS. While the data on the machine is mostly unimportant, I do want to put my private SSH key on it for pushing and pulling config updates from my git repository. I wont do that unless at least /home
is encrypted. Round two will resolve this.