Hardware Configuration and Drivers
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-uuidCase 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/kvmThe 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), neversda/vdain production configs. Diskoby-idis the fleet version of this rule. - Microcode + redistributable firmware on real machines.
nixos-hardwareonly when the module name matches the chassis.- GPU modules only for GPUs that exist.
Try this
blkidand compare UUIDs tohardware-configuration.nix. They must match.lsinitrd /boot/EFI/nixos/*.efi 2>/dev/null | grep -i virtio(orlsinitrd $(readlink /run/current-system/initrd)) and find the disk driver.lscpu | grep -i vendorand enable that vendor’supdateMicrocode.- Browse
nixos-hardwaremodule names (nix flake show github:NixOS/nixos-hardwaremay be huge; the GitHub tree is enough). Write down the one that matches your laptop, or “none — VM.”