Migrate Default NixOS Configuration to Flake

Published by Philipp Schuster on

Screenshow: Basic flake.nix for a NixOS System Configuration

Although Nix flakes are still marked as unstable, they became the de facto standard for managing reproducible NixOS system configurations. Regarding NixOS system configurations, the major benefit of flakes is that they bundle nixpkgs (and possibly further dependencies) along with the configuration files. The nixpkgs version and the configuration files are no longer separate as they used to be! This is a major benefit and enables you to properly manage your NixOS system configuration(s) in a single directory, which might live in a Git repository.

About this Guide

⚠️ As always: Caution! Especially if you are less experienced.

This guide helps you to migrate your fresh NixOS installation (from the default installer) to a Nix flake, so that you can have your configuration files anywhere and no longer in /etc/nixos. The latter is optional but recommended – for example, put all files in a Git repository living in your home directory!

⚠️ If you already have your NixOS system for a while with a more sophisticated configuration, you might have to adapt the guide – if you are familiar with NixOS and its concepts, I’m confident you can manage that!

Further, the guide focuses on the way the official installers of NixOS 23.05, NixOS 23.11, and NixOS 24.05 set up the system. This might be different or equal in other versions, but I can’t make clear statements at this point.

TL;DR: Most likely your system right now has /etc/nixos/configuration.nix and /etc/nixos/hardware-configuration.nix. Further, $ sudo nix-channel --list lists one global Nix channel. We combine all of that in a single Flake.

Add flake.nix to /etc/nixos

In /etc/nixos you have two NixOS modules: configuration.nix and hardware-configuration.nix describing your NixOS system. By default, these files belong to root. At first, for convenience, run the following commands in a shell so that we do not need sudo all the time in the following:

# Ensure that admins (wheel group) can edit this file without sudo.
sudo chgrp -R wheel /etc/nixos
sudo chmod -R g+rw /etc/nixos

This privilege loosening is fine for the following reasons:

  • $ nixos-rebuild still needs sudo
  • Eventually, you will move the NixOS configuration to a Git repository in your
    HOME directory anyway.
  • Once you are done with that guide and have a new location for your files, you can delete /etc/nixos.

Now perform the following steps to init the flake:

# We need "--extra-experimental-features" as flakes are not stable as of nix@v2.18
cd /etc/nixos
nix flake init --extra-experimental-features nix-command --extra-experimental-features flakes

⚠️ You could also just create a flake.nix file with the content that follows anyway, but I want to show how you can generate a flake in general. Generating a flake just means that a flake.nix and a corresponding flake.lock are generated.

This generates /etc/nixos/flake.nix and /etc/nixos/flake.lock. flake.nix
looks somehow like this:

{
  description = "A very basic flake";

  inputs = {
    nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable";
  };

  outputs = { self, nixpkgs }: {
   packages.x86_64-linux.hello = nixpkgs.legacyPackages.x86_64-linux.hello;

   packages.x86_64-linux.default = self.packages.x86_64-linux.hello;
  };
}

Replace the file content with the following flake, which describes a minimal
yet valid flake-based NixOS system configuration using the existing NixOS modules
/etc/nixos/configuration.nix and /etc/nixos/hardware-configuration.nix:

{
  description = "NixOS System Configuration";

  inputs = {
    # If you want to use the latest upstream version, I recommend using
    # branch "nixos-unstable" instead of "23.11" (the latest stable release).
    nixpkgs.url = "github:nixos/nixpkgs/23.11";
  };

  outputs = { self, nixpkgs }: {
    nixosConfigurations = {
      # This should correspond to the hostname of the machine
      testmachine = nixpkgs.lib.nixosSystem {
        system = "x86_64-linux";
        modules = [
          ./configuration.nix
          ./hardware-configuration.nix
        ];
      };
    };
  };
}

After that, apply the following patch to /etc/nixos/configuration.nix, as we
do not need that import twice:

8,11c8
<   imports =
<     [ # Include the results of the hardware scan.
<       ./hardware-configuration.nix
<     ];
---
>   imports = [ ];
18c15
<
---
>

⚠️ Note: This just means that you remove hardware-configuration.nix from the imports list in configuration.nix.

Refresh flake.lock

We just changed the nixpkgs input of the flake. We want the flake.lock to reflect that. So we execute:

$ nix flake update --extra-experimental-features nix-command --extra-experimental-features flakes

Build the NixOS System using the Flake

Congratulations. Now you have a flake-based NixOS system. From now on, you can
build your NixOS configuration using

$ sudo nixos-rebuild switch --flake /etc/nixos#testmachine
⚠️ Note: On first invocation, this will update your system to the latest nixpkgs version (thus, NixOS) referenced in flake.nix/flake.lock. This might be newer than the version originating from the Nix channel you (implicitly) used before to set up the system.

Once the networking.hostName option matches the NixOS configuration name in
flake.nix, you just can use:

$ sudo nixos-rebuild switch --flake /etc/nixos.
⚠️ It might be necessary to reboot your system once you changed the hostname.

Post Cleanup and Outlook

Remove now useless Nix channels

Run $ sudo nix-channel --remove nixos. You do not need Nix channels on a
Flake-based system anymore.

Optional: If you still want to use import <nixpkgs> {} in Nix files in your flake-based system, i.e., having a proper NIX_PATH, there are better ways to do that:

Tweaks to configuration.nix

Add nix.settings.experimental-features = "nix-command flakes" to your configuration.nix. Then you can just run $ nix flake update without the --extra-experimental-commands option.

Remove /etc/nixos

Once you verified that you can build your system from the flake (and also reboot into it after building it 😊), you should consider moving all files (/etc/nixos/{configuration.nix, hardware-configuration.nix, flake.nix, flake.lock}) files to ~/my-nixos-configs or so. I also highly recommend to versionize them using Git.

I hope that helps you. Have fun with your flake-based NixOS system.


Philipp Schuster

Hi, I'm Philipp and interested in Computer Science. I especially like low level development, making ugly things nice, and de-mystify "low level magic".

0 Comments

Leave a Reply

Your email address will not be published. Required fields are marked *