Hardware Configuration and Drivers

Updated

September 12, 2026

Hardware Configuration and Drivers

The host module is identity (hostname, users, services). Hardware is silicon (disks, CPU, GPU, firmware). The boring default is: generated hardware-configuration.nix, UUIDs not /dev/sda, CPU microcode on, and nixos-hardware when a profile exists for this chassis.

Mental model

flake
  modules = [
    ./configuration.nix          # you
    ./hardware-configuration.nix # generated
    nixos-hardware.…             # community, optional
  ]

nixos-generate-config --root /mnt (installer) or --show-hardware-config (running system) writes filesystem UUIDs and boot.initrd.availableKernelModules (nvme, virtio, ahci). If initrd lacks the disk driver, the VM boots to an emergency shell.

Piece Typical source
File systems, swap, initrd modules hardware-configuration.nix
CPU microcode hardware.cpu.intel/amd.updateMicrocode
Laptop quirks (audio, fingerprint) nixos-hardware
GPU hardware.graphics + vendor module if needed
Firmware blobs hardware.enableRedistributableFirmware = true;

Do not merge hardware into configuration.nix “to have one file.” The next disk clone will fight you.

On 26.05, GPU is hardware.graphics.enable = true; (the old hardware.opengl name is an alias). Intel/AMD usually need no extra blob beyond enableRedistributableFirmware. NVIDIA is a policy (hardware.nvidia.open, prime) — do not copy a 22.11 videoDrivers = [ "nvidia" ]; gist. Disko already owns partition UUIDs; if you use Disko, do not also hand-write fileSystems."/" in hardware-configuration for the same mount.

Worked examples

Case 1: Read the generated file; do not invent it

Save as hardware-configuration.nix (illustrative — your UUIDs come from blkid):

# hardware-configuration.nix
{ config, lib, pkgs, modulesPath, ... }:

{
  imports = [ (modulesPath + "/installer/scan/not-detected.nix") ];

  boot.initrd.availableKernelModules = [ "nvme" "xhci_pci" "ahci" "usbhid" "sd_mod" ];
  boot.kernelModules = [ "kvm-amd" ];

  fileSystems."/" = {
    device = "/dev/disk/by-uuid/a1b2c3d4-e5f6-7890-abcd-1234567890ab";
    fsType = "ext4";
  };

  fileSystems."/boot" = {
    device = "/dev/disk/by-uuid/1234-ABCD";
    fsType = "vfat";
  };

  swapDevices = [
    { device = "/dev/disk/by-uuid/f9e8d7c6-b5a4-3210-fedc-ba9876543210"; }
  ];

  nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
  hardware.cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
}

On a QEMU VM you will see virtio_pci, virtio_blk, virtio_net instead of nvme. That is correct. Do not copy an NVMe file onto a virtio VM.

blkid
ls /dev/disk/by-uuid

Case 2: Firmware and microcode

Save as firmware.nix:

# firmware.nix
{ config, ... }:

{
  hardware.enableRedistributableFirmware = true;
  hardware.cpu.intel.updateMicrocode = true;
  # hardware.cpu.amd.updateMicrocode = true;  # AMD hosts
}

Pick one CPU vendor. Enabling both is harmless-ish but noisy. Without microcode, you skip CPU bug fixes the vendor shipped as firmware.

Case 3: nixos-hardware for a known laptop

Save as flake.nix fragment (inputs + import):

# flake-hardware.nix
{
  description = "Desk laptop";

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

  outputs = { self, nixpkgs, nixos-hardware }: {
    nixosConfigurations.desk-laptop = nixpkgs.lib.nixosSystem {
      system = "x86_64-linux";
      modules = [
        ./configuration.nix
        ./hardware-configuration.nix
        nixos-hardware.nixosModules.framework-13-7040-amd
      ];
    };
  };
}

Replace the module name with the one that matches your chassis (ls the repo’s module list, or the nixos-hardware README). A ThinkPad module on a Dell is worse than no module.

Case 4: Graphics — Mesa first, vendor blobs only if needed

Save as graphics.nix:

# graphics.nix
{
  hardware.graphics = {
    enable = true;
    enable32Bit = true; # Steam / wine; skip on a headless VM
  };
}

Intel and AMD generally need this plus firmware. NVIDIA:

# nvidia.nix
{
  services.xserver.videoDrivers = [ "nvidia" ];
  hardware.nvidia.open = false; # or true, per GPU generation — read the option doc
  hardware.nvidia.modesetting.enable = true;
}

Do not enable NVIDIA modules on a VM with virtio-gpu. The guest will load a driver for hardware that is not there.

Case 5: KVM on a workstation that runs VMs

# kvm.nix
{
  virtualisation.libvirtd.enable = true;
  boot.kernelModules = [ "kvm-intel" ]; # or kvm-amd
  users.users.deskadmin.extraGroups = [ "libvirtd" "kvm" ];
}

boot.kernelModules here is host virtualisation, not initrd disk drivers. Keep disk drivers in the generated hardware file.

ls /dev/kvm

The trap

The trap is fileSystems."/".device = "/dev/sda2". Plug in a USB disk, reboot, the kernel enumerates sda as the USB stick, and the root UUID is now sdb2. Emergency shell. Always by-uuid or by-id.

The other trap is hand-editing boot.initrd.availableKernelModules out of the generated file because it “looked messy,” then cloning the disk to a machine whose storage driver you deleted.

Regenerate on the new chassis (nixos-generate-config) and keep the host module.

The boring rule

  • Generated hardware file. Your services stay in configuration.nix.
  • Filesystems by UUID (blkid), never sda/vda in production configs. Disko by-id is the fleet version of this rule.
  • Microcode + redistributable firmware on real machines.
  • nixos-hardware only when the module name matches the chassis.
  • GPU modules only for GPUs that exist.

Try this

  1. blkid and compare UUIDs to hardware-configuration.nix. They must match.
  2. lsinitrd /boot/EFI/nixos/*.efi 2>/dev/null | grep -i virtio (or lsinitrd $(readlink /run/current-system/initrd)) and find the disk driver.
  3. lscpu | grep -i vendor and enable that vendor’s updateMicrocode.
  4. Browse nixos-hardware module names (nix flake show github:NixOS/nixos-hardware may be huge; the GitHub tree is enough). Write down the one that matches your laptop, or “none — VM.”