Install NixOS with disko disk partitioning

In this second tutorial, we will walk you through the process of installing NixOS. Unlike the first installation tutorial, we will use the command line to install NixOS manually, except for using disko to specify disk partitions declaratively in Nix itself. This is the first step toward our next tutorial, where we will automate the entire installation process.

Prepare to install NixOS

Minimal ISO image

This tutorial doesn’t use a graphical installer. Instead, it uses the minimal ISO image. This is primarily because we don’t want the installer to partion the disk for us. We will use disko to do that.

  • Download the latest NixOS ISO from here. Choose the “Minimal ISO image” for your architecture.
  • Create a bootable USB flash drive (instructions here)

Boot your computer from this USB flash drive, and expect to be greeted with a command line interface (CLI):

/nix/store/lwmy3r5lzv6g7ri95xsnz272nbign42a-global/nixos-install-disko/nixos-installer-cli.jpeg

Partition the disk

Before installing NixOS, let’s define our partition layout in Nix. We will follow the official disko documentation and include screenshots wherever necessary. Finally, we will use flakes to manage the configuration.

Choosing the disk configuration

Instead of creating our partition layout from scratch, we can choose one of the examples Disko itself provides (see here). We will use the hybrid example as it will work for both BIOS and UEFI systems.

Retrieve the disk configuration to a temporary location, calling it disko-config.nix (we will use it latter):

curl https://raw.githubusercontent.com/nix-community/disko/master/example/hybrid.nix -o /tmp/disko-config.nix

Modify the disk configuration

The above downloaded Nix file uses a hardcoded disk device. So, we need to replace it with the device name of the disk we want to install NixOS on. We can use lsblk to find it.

/nix/store/lwmy3r5lzv6g7ri95xsnz272nbign42a-global/nixos-install-disko/nixos-lsblk.jpeg

In this case, the device name is vda. The device file is located at /dev/vda. We will use this to modify disko-config.nix we downloaded earlier.

/nix/store/lwmy3r5lzv6g7ri95xsnz272nbign42a-global/nixos-install-disko/nixos-disko-config.jpeg

Run the partitioning script

The disko flake provides an app that will take our partitioning scheme defined in Nix file above, partition the specified disk device and mount it at /mnt. We want this to happen prior to installing NixOS. Let’s do that now:

sudo nix \
  --experimental-features "nix-command flakes" \
  run github:nix-community/disko -- \
  --mode disko /tmp/disko-config.nix

Once the command completes, you should see the disk partitioned and mounted at /mnt:

/nix/store/lwmy3r5lzv6g7ri95xsnz272nbign42a-global/nixos-install-disko/nixos-disko-post-partition.jpeg

Generate initial NixOS configuration

With the disk partitioned, we are ready to follow the usual NixOS installation process. The first step is to generate the initial NixOS configuration under /mnt.

sudo nixos-generate-config --no-filesystems --root /mnt
Why --no-filesystems and --root?
  • The fileSystems configuration will automatically be added by disko’s nixosModule (see below). Therefore, we use --no-filesystems to avoid generating it here.
  • --root is to specify the mountpoint to generate configuration.nix and hardware-configuration.nix in. Here, our configuration will be generated in /mnt/etc/nixos.

Flakeify the configuration

Before we can utilize disko in our generated configuration, we will convert our configuration to a flake. This is a simple process of adding a flake.nix file in /mnt/etc/nixos:

# /mnt/etc/nixos/flake.nix
{
  inputs = {
    # NOTE: Replace "nixos-23.11" with that which is in system.stateVersion of
    # configuration.nix. You can also use latter versions if you wish to
    # upgrade.
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-23.11";
  };
  outputs = inputs@{ self, nixpkgs, ... }: {
    # NOTE: 'nixos' is the default hostname set by the installer
    nixosConfigurations.nixos = nixpkgs.lib.nixosSystem {
      # NOTE: Change this to aarch64-linux if you are on ARM
      system = "x86_64-linux";
      modules = [ ./configuration.nix ];
    };
  };
}
Make sure to change a couple of things in the above snippet:
  • Replace nixos-23.11 with the version from system.stateVersion in your /mnt/etc/nixos/configuration.nix. If you wish to upgrade right away, you can also use latter versions, or use nixos-unstable for the bleeding edge.
  • x86_64-linux should be aarch64-linux if you are on ARM

For details, see Convert configuration.nix to be a flake.

Add the disko nixosModule

Our NixOS configuration still does not know anything about filesystems. Let’s teach it just that by using the previously downloaded disko example. We do this by adding the disko flake input, importing its NixOS module before importing our /tmp/disko-config.nix.

  • Add the disko flake input in /mnt/etc/nixos/flake.nix:

    # In `/mnt/etc/nixos/flake.nix`
    {
      inputs = {
        disko.url = "github:nix-community/disko";
        disko.inputs.nixpkgs.follows = "nixpkgs";
      };
    }
    Why the “follows”?

    disko.inputs.nixpkgs.follows = "nixpkgs"; is to ensure that disko uses the same version of nixpkgs as specified in the current flake. This avoids having two different sources of nixpkgs and saves space.

  • Add the disko nixosModule:

    {
      # In `outputs` of `/mnt/etc/nixos/flake.nix`
      nixosConfigurations.nixos = {
        # ...
        modules = [
          ./configuration.nix
          inputs.disko.nixosModules.disko
        ];
      };
    }
    /nix/store/lwmy3r5lzv6g7ri95xsnz272nbign42a-global/nixos-install-disko/nixos-flake-with-disko.jpeg
  • Move the disko-config.nix to the flake directory:

    mv /tmp/disko-config.nix /mnt/etc/nixos
  • Add the disk configuration and use GRUB:

    {
      # In `/mnt/etc/nixos/configuration.nix`
      imports = [
        ./hardware-configuration.nix
        ./disko-config.nix
      ];
      #boot.loader.systemd-boot.enable = true;
      #boot.loader.efi.canTouchEfiVariables = true;
      boot.loader.grub.enable = true;
      boot.loader.grub.efiSupport = true;
      boot.loader.grub.efiInstallAsRemovable = true;
    }
    /nix/store/lwmy3r5lzv6g7ri95xsnz272nbign42a-global/nixos-install-disko/nixos-configuration-nix-with-disko-config.jpeg
    Info

    The boot loader configuration above is compatible with both BIOS and UEFI systems. Additionally, BIOS also requires boot.loader.grub.device to be set which is done by disko’s nixosModule.

Let’s check that our final configuration is correct by using nix repl. In particular, we test the fileSystems set by disko:

# First, create a flake.lock
sudo nix --experimental-features "nix-command flakes" flake lock

# Start repl
nix --experimental-features "nix-command flakes" repl
/nix/store/lwmy3r5lzv6g7ri95xsnz272nbign42a-global/nixos-install-disko/nixos-disko-filesystems.jpeg

If you see something similar to the above, everything’s good and we are ready to perform the actual installation.

Install NixOS

With our NixOS configuration in place, we will use the nixos-install program to install NixOS:

sudo nixos-install --root /mnt --flake '/mnt/etc/nixos#nixos'
# NOTE: You will be prompted to set the root password at this point.
sudo reboot

Once rebooted, you should be greeted with the NixOS login screen, allowing you to login to the machine using the root password you had set.

Bonus steps

This tutorial focused mostly on disko, but left some of the things covered in the previous tutorial which you might want to consider:

Video walkthrough

Recap & next steps

You now have a reproducible disk partitioning scheme. This does come at the cost of a few extra manual steps, but you can automate them with a script. Which is what we will do in the next tutorial. We will use nixos-anywhere to automate the steps above and eliminate the need for a USB flash drive (assuming you have a working Linux system or are booted into a rescue image).

Links to this page