Files
nix-config/modules/boot/kernel.org
T
phundrak ba018ef841 refactor: change to litterate config
Configuration is now held by the `.org` files. All `.nix` files are
tangled from the org-mode files.
2026-10-06 12:40:58 +02:00

3.6 KiB
Raw Blame History

Kernel Configuration

Kernel Configuration

This module centralises everything related to the kernel: which package to boot, which extra modules to load, which KVM module the CPU needs, and a couple of modprobe quirks for specific devices. Here’s the skeleton of the nixos.kernel module.

{
  flake.modules.nixos.kernel = {
    pkgs,
    config,
    lib,
    ...
  }:
    with lib; let
      cfg = config.mySystem.boot.kernel;
    in {
      <<options>>
      <<config>>
    };
}

Declaring the Options

options.mySystem.boot.kernel = {
  <<opt-package>>
  <<opt-modules>>
  <<opt-cpu-vendor>>
  <<opt-v4l2loopback>>
  <<opt-extra-modprobe>>
};

Kernel Package

package picks which kernel to boot. I default to the Zen kernel for its desktop-tuned scheduler, but a host can override it with a hardened or hardware-specific kernel instead.

package = mkOption {
  type = types.raw;
  default = pkgs.linuxPackages_zen;
};

Extra Kernel Modules

modules lists any extra kernel modules a host needs beyond the ones this module already adds on its own.

modules = mkOption {
  type = types.listOf types.str;
  default = [];
};

CPU Vendor

cpuVendor tells the module which KVM module to load, since Intel and AMD CPUs each need their own.

cpuVendor = mkOption {
  description = "Intel or AMD?";
  type = types.enum ["intel" "amd"];
  default = "amd";
};

Virtual Webcam

v4l2loopback.enable turns on a virtual video device. I feed it a video source, and OBS Studio picks it up as if it were a webcam.

v4l2loopback.enable = mkEnableOption "Enables v4l2loopback kernel module";

Extra Modprobe Configuration

extraModprobeConfig lets a host inject raw modprobe.d lines. The example below fixes a USB sound card that otherwise misconfigures itself on boot.

extraModprobeConfig = mkOption {
  type = types.lines;
  default = "";
  example = ''
    options snd_usb_audio vid=0x1235 pid=0x8212 device_setup=1
  '';
};

Wiring It All Up

config.boot = {
  <<initrd-driver>>
  <<extra-modprobe-lines>>
  <<kernel-packages-and-modules>>
};

Choosing the Initrd Driver

Most of my machines have Intel graphics, so this module loads i915 early, in the initrd, to keep the Plymouth splash screen from flashing or glitching before the proper driver takes over. Machines with an AMD GPU instead load amdgpu early; the AMD GPU module handles that itself, so this module doesn’t need to know or care which GPU a host actually has.

initrd.kernelModules = ["i915"];

Assembling Modprobe Configuration

This concatenates whatever a host set through cfg.extraModprobeConfig with the v4l2loopback quirk line whenever v4l2loopback.enable is on.

extraModprobeConfig =
  strings.concatLines
  ([cfg.extraModprobeConfig]
    ++ lists.optional cfg.v4l2loopback.enable ''options v4l2loopback exclusive_caps=1 devices=1 video_nr=0 card_label="OBS Studio"'');

Kernel Package and Extra Modules

Finally, kernelPackages and kernelModules wire the chosen package and modules through, appending the vendor-specific KVM module.

kernelPackages = cfg.package;
kernelModules = cfg.modules ++ ["kvm-${cfg.cpuVendor}"];