My NixOS Journey - Flakes

Intro

As per Notion AI

Nix Flake is a new way of defining and composing Nix packages. It allows users to define a package in a declarative way that is easily shareable and reproducible across different systems. With Nix Flake, users can create atomic and composable packages that can be easily combined to create more complex systems.

I strongly recommend you to read both NixOS wiki page and this blog post to understand what problems Nix flakes solve.

From my experience, flakes helps me to store all configs in a single folder on GitHub. If I ever need to rebuild my system, I just copy the folder to my new machine and then a single command will rebuild my whole system including application configurations to the same state.

As mentioned in the previous post, you can choose to use home manager as nixos module or standalone mode. In today’s post, I would reuse configurations from previous posts to show you how to migrates those configurations to flakes.

If you use git to manage flakes folder, you need to add the files to staging are. Otherwise nix won’t find the file.

Let’s get started.

NixOS Module

Preparation

Let’s start by creating some folders and copy existing config to the folder.

1
2
3
4
5
6
mkdir -p my-nix-flake/nixos
mkdir -p my-nix-flake/home-manager
cp /etc/nixos/configuration.nix my-nix-flake/nixos
cp /etc/nixos/hardware-configuration.nix my-nix-flake/nixos
cp /etc/nixos/home.nix my-nix-flake/home-manager
cp -r /etc/nixos/apps/ my-nix-flake/home-manager

Create flakes

Next, let’s save below to my-nix-flake/flake.nix.

Please remember to update

  • to the one that on your configurations.nix. The default host name for Nixos is nixos.
  • to the username that you want to manage configurations for.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
{
description = "Your new nix config";

inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
home-manager = {
url = github:nix-community/home-manager;
inputs.nixpkgs.follows = "nixpkgs";
};
};

outputs = { nixpkgs, home-manager, ... }:
let
system = "x86_64-linux";
in
{
nixosConfigurations = {
<your_host_name> = nixpkgs.lib.nixosSystem {
inherit system;
modules = [
./nixos/configuration.nix
home-manager.nixosModules.home-manager
{
home-manager = {
useUserPackages = true;
useGlobalPkgs = true;
users.<your_user_name> = ./home-manager/home.nix;
};
}
];
};
};
};
}

Modify config

As we can see, some of the home manager config are already on flake.nix. We need to remove the duplicate ones from my-nix-flake/nixos/configuration.nix.

Let’s open my-nix-flake/nixos/configuration.nix and remove

  1. <home-manager/nixos> from imports.
    1
    2
    3
    4
    5
    6
    {
    imports =
    [ # Include the results of the hardware scan.
    ./hardware-configuration.nix
    <home-manager/nixos>
    ];
  2. home-manager settings.
    1
    2
    3
    4
    5
    6
    ...
    home-manager = {
    useGlobalPkgs = true;
    useUserPackages = true;
    users.<your_user_name> = import ./home.nix;
    };

Apply Changes

After that we can run sudo nixos-rebuild switch --flake './my-nix-flake#<your_host_name>' to build the config.

This my-nix-flake folder will be the source of truth of your system. You can take this folder to a new computer and a single nixos-rebuild switch command will build your new system to the exact same state.

Standalone installation

Let’s start by creating some folders and copy existing config to the folder.

1
2
3
4
5
6
mkdir -p my-nix-flake/nixos
mkdir -p my-nix-flake/home-manager
cp /etc/nixos/configuration.nix my-nix-flake/nixos
cp /etc/nixos/hardware-configuration.nix my-nix-flake/nixos
cp ~/.config/nixpkgs/home.nix my-nix-flake/home-manager
cp -r ~/.config/nixpkgs/apps/ my-nix-flake/home-manager

Create flakes

Next, let’s save below to my-nix-flake/flake.nix.

Please remember to update

  • to the one that on your configurations.nix. The default host name for Nixos is nixos.
  • to the username that you want to manage configurations for.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
{
description = "Your new nix config";

inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
home-manager = {
url = "github:nix-community/home-manager";
inputs.nixpkgs.follows = "nixpkgs";
};
};
outputs = { nixpkgs, home-manager, ... }:
let
system = "x86_64-linux";
pkgs = nixpkgs.legacyPackages.${system};
in {
nixosConfigurations = {
<your_host_name> = nixpkgs.lib.nixosSystem {
modules = [
./nixos/configuration.nix
];
};
};
homeConfigurations = {
<your_user_name> = home-manager.lib.homeManagerConfiguration {
inherit pkgs;
modules = [
./home-manager/home.nix
];
};
};
};
}

Apply changes

We need to enable flakes by putting below to the bottom of ./nixos/configuration.nix file.

1
2
  nix.settings.experimental-features = [ "nix-command" "flakes" ];
}

Then we can run sudo nixos-rebuild switch --flake './my-nix-flake#<your_host_name>' to apply system wide configuration changes and home-manager switch --flake ./my-nix-flake#<USERNAME> to apply home manager changes.

(Optional) New flake users

If you are building a new flakes, you need to do below two steps to enable home manager.

Self-manager HM

We can create ./my-nix-flake/home-manager/home.nix as below

1
2
3
4
5
6
7
8
{ config, pkgs, ... }:

{
home.username = "<username>";
home.homeDirectory = "/home/<username>";
home.stateVersion = "22.11";
programs.home-manager.enable = true;
}

This will install home manager to manager itself.

Activate HM

Then we can activate home manager with below two commands.

1
2
nix build --no-link <flake-uri>#homeConfigurations.<username>.activationPackage
"$(nix path-info <flake-uri>#homeConfigurations.<username>.activationPackage)"/activate

Once home-manager CLI is installed, we can simple run home-manager switch --flake <flake-uri>#<USERNAME> to apply home manager config changes.

That’s all I want to share with you today. I did not expect it would take so long to write these 3 posts. I hope these posts help you to start using Nix.

Thank you for reading and see you next time.