hardware.nix
1 # Hardware configuration for rig.lan 2 # Based on actual hardware: AMD Ryzen 9 8945HS, 3x RTX 3090 via Thunderbolt PCIe 3 4 { config, lib, pkgs, modulesPath, ... }: 5 6 { 7 imports = [ 8 (modulesPath + "/installer/scan/not-detected.nix") 9 ]; 10 11 # ── Kernel ─────────────────────────────────────────────────────────── 12 boot.initrd.availableKernelModules = [ 13 "nvme" "xhci_pci" "ahci" "usbhid" "sd_mod" "thunderbolt" 14 ]; 15 boot.kernelModules = [ "kvm-amd" ]; 16 17 # ── CPU ────────────────────────────────────────────────────────────── 18 hardware.cpu.amd.updateMicrocode = true; 19 20 # ── Thunderbolt ───────────────────────────────────────────────────── 21 # GPUs 1 & 2 (bus 08:00.0, 68:00.0) are behind Intel JHL6340 22 # Thunderbolt 3 PCIe switches. Without authorization they stay powered 23 # down and invisible to nvidia-smi. 24 services.hardware.bolt.enable = true; 25 26 # Auto-authorize all Thunderbolt devices on connect (security = none). 27 # Required for headless GPU operation — no user session to approve. 28 # The udev rule fires before nvidia-persistenced starts. 29 services.udev.extraRules = '' 30 ACTION=="add", SUBSYSTEM=="thunderbolt", ATTR{authorized}!="1", ATTR{authorized}="1" 31 ''; 32 33 # After Thunderbolt devices are authorized, rescan PCI so the nvidia 34 # driver binds to the newly-visible GPUs. 35 systemd.services.thunderbolt-pci-rescan = { 36 description = "Rescan PCI bus after Thunderbolt GPU authorization"; 37 after = [ "bolt.service" ]; 38 wants = [ "bolt.service" ]; 39 before = [ "nvidia-persistenced.service" "nvidia-container-toolkit-cdi-generator.service" ]; 40 wantedBy = [ "multi-user.target" ]; 41 serviceConfig = { 42 Type = "oneshot"; 43 RemainAfterExit = true; 44 ExecStartPre = "${pkgs.coreutils}/bin/sleep 3"; 45 ExecStart = "${pkgs.bash}/bin/bash -c 'echo 1 > /sys/bus/pci/rescan'"; 46 }; 47 }; 48 49 # ── Filesystem mounts ──────────────────────────────────────────────── 50 # disko handles these — see disk-config.nix 51 }