Skip to content

Minimal flake NixOS host

Overview

This walkthrough wires one NixOS machine through a flake: pinned nixpkgs, a nixosConfigurations output, a host module tree, and the commands to build, check, and switch. It is a file-layout story—not a tour of every NixOS option. For module semantics and activation modes, follow the links in Domains composed instead of treating this page as the only reference.

Details

What you get

One repository directory with three Nix files and a lockfile after the first nix flake lock. The flake output name (hostname in the snippets below) is what you pass after # in rebuild and build commands. Evaluating that output produces a closed system generation you can activate with nixos-rebuild switch --flake .#hostname.

Domains composed

This example pulls together teaching pages from several domains:

File layout

.
├── flake.nix
├── flake.lock              # after nix flake lock
├── configuration.nix       # host policy you edit
└── hardware-configuration.nix   # machine facts (generated on real installs)

On a real install, hardware-configuration.nix comes from nixos-generate-config (filesystem UUIDs, initrd modules, platform). The stub below is enough for the walkthrough; do not copy it to bare metal without replacing disk and boot facts.

Annotated pieces

flake.nix — pin nixpkgs, expose one nixosConfigurations entry, pass flake inputs into modules:

{
  description = "Minimal single-host NixOS flake";

  inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-26.05";

  outputs = { self, nixpkgs, ... }@inputs: {
    nixosConfigurations.hostname = nixpkgs.lib.nixosSystem {
      specialArgs = { inherit inputs; };
      modules = [ ./configuration.nix ];
    };
  };
}

Prefer setting nixpkgs.hostPlatform in hardware-configuration.nix (see stub) over the legacy top-level system argument to nixosSystem. See NixOS configurations in flakes for modules, specialArgs, and multiple hosts.

configuration.nix — ordinary NixOS module; imports hardware facts and sets host policy. The option set matches the checked-in corpus fixture minimal-configuration.nix:

{ config, pkgs, ... }: {
  imports = [ ./hardware-configuration.nix ];

  boot.loader.systemd-boot.enable = true;
  boot.loader.efi.canTouchEfiVariables = true;

  networking.hostName = "hostname";
  networking.networkmanager.enable = true;

  users.users.alice = {
    isNormalUser = true;
    extraGroups = [ "wheel" ];
  };

  environment.systemPackages = with pkgs; [ git vim ];

  # Set once at install to the release you started on; do not bump casually.
  system.stateVersion = "26.05";
}

hardware-configuration.nix (stub) — placeholder only; replace with generator output on real hardware:

{ config, lib, pkgs, modulesPath, ... }: {
  imports = [ (modulesPath + "/installer/scan/not-detected.nix") ];

  boot.initrd.availableKernelModules = [ "xhci_pci" "ahci" "nvme" "usb_storage" "sd_mod" ];
  boot.initrd.kernelModules = [ ];
  boot.kernelModules = [ "kvm-intel" ];
  boot.extraModulePackages = [ ];

  fileSystems."/" = {
    device = "/dev/disk/by-uuid/REPLACE-ME";
    fsType = "ext4";
  };

  nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
}

Activate / verify

Enable experimental features (once per machine), then lock, check, build, and switch:

# nix.conf or --extra-experimental-features 'nix-command flakes'
nix flake lock
nix flake check
nix build .#nixosConfigurations.hostname.config.system.build.toplevel
sudo nixos-rebuild switch --flake .#hostname

nix flake check validates that each nixosConfigurations.<name>.config.system.build.toplevel evaluates to a valid derivation. nix build …toplevel produces the same closure without changing the running system or boot default. For test, boot, and rollback semantics, see rebuild actions.

Failure modes

Symptom Likely cause
experimental Nix feature 'flakes' is disabled Enable flakes and nix-command
error: flake '…' does not provide attribute 'nixosConfigurations.…' Wrong #name after --flake; name must match the nixosConfigurations key
Services break after bumping system.stateVersion stateVersion is a compatibility default for existing state, not a target release to chase
Boot fails or root cannot mount Stub or stale hardware-configuration.nix; regenerate with nixos-generate-config on the target machine
Eval succeeds on laptop, fails on CI Missing platform or hardware module facts; set nixpkgs.hostPlatform and real fileSystems for each host

Examples

End-to-end picture: three files from File layout and Annotated pieces (flake.nix, configuration.nix, hardware stub), then:

nix flake lock
nix flake check
nix build .#nixosConfigurations.hostname.config.system.build.toplevel
sudo nixos-rebuild switch --flake .#hostname

Match networking.hostName, the nixosConfigurations key, and the # suffix (hostname here). On that machine, nixos-rebuild switch --flake . omits # when the hostname matches. Corpus twin: minimal-configuration.nix.

References

See also