How to install NixOS from NixOS

When the last semester came to an end, I noticed that my Thinkpad behaved weird. I couldn’t nix-store --optimize it, and some other things began to fail silently. I suspected the SSD was dying, a Crucial C400 with 256GB. So I ran the smart tools with a short test - But it told me everything was alright. Then I ran the extended self-test on the drive and after 40% of the check (60% remaining) it told me about dead sectors, nonrecoverable.

So I got a new SSD and installed NixOS from my old installation. Here’s how.

So I got a nice new Samsung EVO 850 PRO with 256 GB. I was really amazed how light these things are today. No heavy metal in there like in a HDD!

Preparation

First of, you need to prepare your current installation. Make some backups, be sure everything is fine with them.

Then, verify that your configuration.nix and your hardware-configuration.nix file list your partitions not by UUID, but by /dev/sda1 and so on. That could be really helpful later.

If you have some crypto keys you need to keep, maybe make another backup of them.

The installation

First of, we need to format the new drive. Use gdisk for this if you have a UEFI setup like with an Thinkpad X220. Format your partitions after that. Make sure that your boot partition is formatted as vfat (fat16). I don’t know why, but it is only possible to boot from vfat, according to the nixos documentation. Also, do your cryptsetup.

For simplicity, I refer to the boot partition by /dev/sda1 and to the root/home partition as /dev/sda2 - you can, of course, have more partitions, maybe for a seperate /home. But I saw no need for it. With only one partition I do not have to take care of the size of the /nix/store and if I have few things in the store I can grow my music collection a bit - so I’m really flexible. And yes, I know about LVM, but I really don’t need these things, do I?

Now, mount the partitions as follows:

  • /dev/sda2 in /mnt
  • /dev/sda1 in /mnt/boot (you might need to mkdir this directory first)

Ensure things are properly mounted. This broke my neck twice during my installation, as /mnt/boot wasn’t mounted properly and I failed to rebuild the system. Took me some time to see this, actually.

Now you can nixos-generate-config --root /mnt. After that you might want to modify your configuration.nix file in the newly generated setup under /mnt/etc/nixos/configuration.nix - I did not! I nixos-install --root /mnted to get a minimal bootable system.

Then I rsync -aed my /home/$USER to /mnt/home/ and symlinked the configuration.nix (which lives in /home/$USER/config/nixos/$HOSTNAME.nix on my machines) to /etc/nixos/configuration.nix. I renamed the host as well, to avoid confusion.

Then, I shutdowned, removed the old SSD, assembled the new one and booted. I had some problems with failing mounts during boot (because I had mount operations specified by UUID rather than via /dev/sdaX). I got a rescue shell and was able to fix things up. After several reboots I was able to get my system up and running.

When I was able to boot my minimal installation, I just followed the manual and created my user and so on. Then, I nixos-rebuild switched. And because I copied my whole configuration.nix setup from my old drive, everything got build for me.

After some more nix-env -iA calls (because some things only live in my user environment), I fully restored my system. Awesome!

Conclusion

Installing NixOS from NixOS works really nice. You have to be careful with some things, UUIDs and so on, but overall it is rather simple.

Anyways, you benefit if you really know your system. I wouldn’t necessarily recommend this to an inexperienced NixOS user - hacking things into the TTYs and getting a rescue shell for fixing the installation is no thing that a newbie really wants to do - except for learing and if backups are at hand!

Because of the awesomeness of NixOS and the configuration.nix file, I was able to rebuild my complete system within a few minutes. Despite my extensive adaptions in my configuration.nix file - speaking of container setup, custom compile flags for packages, custom vim setup with plugins compiled into the vim derivation (and the same again for neovim), hundreds of packages and stuff - I was able to rebuild my system without much effort.

Overall, leaving out the UUID fail, I think I am able to redo a complete setup (including syncing /home, which was ~100GB data, and reinstalling everything) in maybe 90 minutes, depending on how fast the internet connection is for downloading binaries.

One could even mount the old /nix/store from the old installation and copy over derivations, which would be a hell lot faster and would result in a reinstallation without the need for internet access. But I don’t know how to do it, so I leave it as exercise to the reader.