Installing a New Workstation with NixOS


This post is half for the curious and half so that I can remember next time I get a new workstation.

Install NixOS

The first step is installing NixOS. This is made easy with my nixos-auto-install image.

First you build the image and write to to a USB drive.

% cd nixos-auto-install
% nix-build
% pv result/iso/*.iso | sudo zsh -c '>/dev/disk/by-id/usb-Generic_Flash_Disk_1729B293-0:0'

Then you plug it into the target machine and boot off of it. Odds are that it installs successfully and your system reboots into NixOS. If not there are tips in the README.

Install My Config

I keep some secrets in my Git repo encrypted to prevent them being visible to any Git hosts or backups, so I need to copy the key to the new machine. I could copy my GPG key over now but I have had trouble with the password over SSH in the past so I find it easiest to copy over the repo key for now.

% cd my-nix-config
% git crypt export-key /tmp/nix-key
% rsync /tmp/nix-key root@install.local:
% rm /tmp/nix-key

Log into the new machine.

% ssh root@install.local

Clone and decrypt my config.

install.local# git clone git@example:my-nix-config
install.local# cd my-nix-config
install.local# git crypt unlock ~/nix-key
install.local# rm ~/nix-key

Switch to My Configuration

I simply replace /etc/nixos/configuration.nix with a symlink to my Git repo. I also put the hostname in /etc/nixos/hardware-configuration.nix. I store the hostname on the system but most other host-specific changes are handled with conditionals in my config.

install.local# sed -ie '$ i\
\ = "new-hostname";
' /etc/nixos/hardware-configuration.nix
install.local# mv /etc/nixos/configuration.nix{,.bak}
install.local# ln -s ~/my-nix-config/desktop.nix /etc/nixos/configuration.nix

And finally build and apply the new config.

install.local# nixos-rebuild --upgrade boot
install.local# reboot

Set Password for Full Disk Encryption

nixos-auto-install sets up disk encryption but uses a single null byte as the key. We disable the automatic decryption attempt in preparation for setting our own password. If a rollback is needed the old config will still work because of the fallbackToPassword = true.

--- a/etc/nixos/hardware-configuration.nix
+++ b/etc/nixos/hardware-configuration.nix
@@ -18,14 +18,6 @@
-		# Set your own key with:
-		# cryptsetup luksChangeKey /dev/disk/by-label/root --key-file=/dev/zero --keyfile-size=1
-		# You can then delete the rest of this block.
-		keyFile = "/dev/zero";
-		keyFileSize = 1;
-		fallbackToPassword = true;

Set the new password. The truly paranoid may prefer to rotate the disk key in case someone can recover the key from the previous insecure key-slot, however for most people this is probably secure enough.

new-hostname% sudo cryptsetup luksChangeKey /dev/disk/by-label/root --key-file=/dev/zero --keyfile-size=1
new-hostname% sudo nixos-rebuild switch

Rebooting here isn’t necessary but it is probably a good idea just to ensure that you can still decrypt your disk. Otherwise you may waste some time in the rare case that updating the key failed for whatever reason.

Clean Up the Bootstrapping Process

At this point my personal user has been created so I move my Nix config into my own home directory.

new-hostname% mkdir p
new-hostname% sudo mv ~root/my-nix-config p
new-hostname% sudo chown -R kevincox: p/my-nix-config
new-hostname% sudo ln -s ~/p/my-nix-config/desktop.nix /etc/nixos/configuration.nix


There we go. I have a system with most of my configuration ready to go. I have all of my favourite programs installed, configurations for many tools set up and even some desktop setting tweaked to my preference. I don’t manage all of my configs and state with Nix at this point (for example my Vim config lives in a separate repo in case I need to use a non-NixOS machine in a future job) and I need to log into Firefox Sync but the system is already comfortable to me. It is really amazing to install a new system without the “oh right, I haven’t installed X yet” breaking your workflow every could of hours for the first few weeks.