Files
Nomarchy/docs/HARDWARE.md
Bernardo Magri a09399702d
All checks were successful
Check / eval (push) Successful in 3m44s
docs: REQUIREMENTS.md — OpenGL 4.3 floor, disk/RAM planning
Acer M5-481T fails Ghostty because Ivy Bridge HD 4000 tops out at
OpenGL 4.2 in Mesa; Ghostty needs 4.3 — a generation ceiling, not a
missing driver. Document that plus UEFI/x86_64, RAM, and storage floors
(Nix store generations + BTRFS snapper + hibernate swap≈RAM). Linked
from README, docs map, HARDWARE.md; #95 points here.
2026-07-15 09:40:17 +01:00

23 KiB
Raw Blame History

Hardware support

How Nomarchy enables CPUs, GPUs, laptops, firmware, and peripherals — and what to do when your machine is not in the happy path.

Minimum bar (OpenGL, RAM, disk, UEFI): REQUIREMENTS.md — read that before calling a machine “unsupported”; this file is the enablement stack and quirk list.

Queue: agent/BACKLOG.md (PROPOSED Hardware product). Product framing: VISION.md § A. Design history: ROADMAP.md. Docs map: README.md. Migration: MIGRATION.md.

1. Architecture (three layers)

Nomarchy does not reimplement nixos-hardware. It stacks:

┌─────────────────────────────────────────────────────────────────────┐
│  A. Always-on desktop floor                                         │
│     modules/nixos/default.nix + power.nix + audio/BT                │
│     redistributable firmware · fwupd · NM · PipeWire · PPD · ddcci  │
└───────────────────────────────┬─────────────────────────────────────┘
                                │
┌───────────────────────────────▼─────────────────────────────────────┐
│  B. nixos-hardware profiles  (via mkFlake hardwareProfile)          │
│     common-cpu-* · common-gpu-* · common-pc(-laptop|-ssd) · model   │
│     microcode · GPU media · fstrim · vendor/model quirks            │
└───────────────────────────────┬─────────────────────────────────────┘
                                │
┌───────────────────────────────▼─────────────────────────────────────┐
│  C. nomarchy.hardware.*  (modules/nixos/hardware.nix)               │
│     gap above commons: GuC · amd-pstate · VA-API env · fprintd ·    │
│     IR-webcam hide · ROCm/NPU/latestKernel · I2C/DDC/CI             │
└─────────────────────────────────────────────────────────────────────┘
Layer Who turns it on Where it lives
A Distro defaults (mkDefault) Any machine importing nomarchy.nixosModules.nomarchy
B Installer DMI/lspcihardwareProfile = [ … ] Downstream flake.nix (mkFlake)
C Installer probes → system.nix, or hand-edit Downstream system.nix

hardware-configuration.nix (from nixos-generate-config) still owns initrd modules, filesystems, and the usual generate-config flags. The installer writes a real one; the template ships a placeholder you must replace.

Unknown hardwareProfile names fail at eval with Levenshtein suggestions (lib.nix) — never silently ignored.

2. What works without thinking about it

These ship on every Nomarchy system unless you override them:

Capability Default Notes
WiFi / BT firmware blobs hardware.enableRedistributableFirmware iwlwifi, ath, rtw, brcm, SOF, …
NetworkManager on WiFi UI: System Network
PipeWire + WirePlumber on
Bluetooth + blueman on System Bluetooth
power-profiles-daemon on Menu + Waybar; TLP via nomarchy.system.power.backend = "tlp"
External monitor brightness nomarchy.hardware.i2c.ddcci on DDC/CI → backlight devices
Firmware updates (LVFS) services.fwupd.enable Never auto-flashes — see §4
SMART / UPower / pcscd (FIDO) on
earlyoom on Process-level OOM, not cgroup kill of the whole session

Not default-on (need detect or uncomment): fprintd, GuC/HuC, amd-pstate, ROCm, NPU, thermald, charge limit, snapper (installer enables snapper), latestKernel.

3. Install path (best experience)

nomarchy-install sources pkgs/nomarchy-install/hardware-db.sh and:

  1. Probes CPU vendor, GPUs (lspci), battery, SSD, fingerprint USB VIDs, RGB+IR webcam names, NPU PCI class.
  2. Looks up DMI sys_vendor × product_name in a ~60-entry model table (Framework, Dell XPS/Latitude, ThinkPad, Surface, ASUS ROG, Apple T2, System76).
  3. Emits MODULE … lines → hardwareProfile list in flake.nix.
  4. Emits NOMARCHY hardware.*=… → active + commented blocks in system.nix.
  5. Asks you to confirm profiles (or pick manually from the full nixos-hardware attr list baked into the ISO). Override with NOMARCHY_HW=auto|none|"mod1 mod2".

Live ISO is intentionally generic (no model profile): broad GPU modules as available, redistributable firmware on, no baked nomarchy.hardware.*. Tuning happens at install time.

Out of scope for the installer today: aarch64 (Pi, Snapdragon X), Steam Deck (Jovian), Apple Silicon (T2 Intel Macs only in the DB).

4. Firmware updates (deep dive)

What we ship

# modules/nixos/default.nix
services.fwupd.enable = lib.mkDefault true;

fwupd talks to the LVFS: UEFI capsule (BIOS), some SSDs, docks, Thunderbolt controllers, peripherals. It only refreshes metadata on its own. Applying an update is always an explicit user action.

What you do today (CLI)

# After first boot (and occasionally later):
fwupdmgr refresh          # optional; daemon often has metadata
fwupdmgr get-devices      # what LVFS can see
fwupdmgr get-updates      # pending
fwupdmgr update           # apply (may need reboot / battery / AC)

Disable on VMs/headless: services.fwupd.enable = false; in system.nix.

Why this is under-discovered

Present Missing
Daemon + package Doctor check (“updates available”)
README one-liner Waybar / updates panel integration
System ▸ Firmware menu (nomarchy-menu firmware)
MOTD + first-boot tip (#43)

System ▸ Firmware (shipped): a self-gated System-submenu row (present whenever fwupdmgr is on PATH, i.e. services.fwupd.enable, default-on) that opens a terminal and runs fwupdmgr refreshget-updates → confirm → fwupdmgr update. It never auto-flashes — fwupdmgr update confirms each device and prompts for the reboot a capsule needs; pillar 1 (rock-stable) forbids silent BIOS writes.

Hints (#43 / #73): MOTD cheat-sheet line + nomarchy-control-center --first-boot tip when fwupdmgr is on PATH. Fingerprint / doctor tips follow the same pattern (fingerprint MOTD only when nomarchy.hardware.fingerprint.enable).

Still queued: a Doctor “updates available” check, and Waybar/updates-panel integration.

Thunderbolt

Firmware for TB devices may appear via LVFS. There is no first-class services.hardware.bolt / security-level UI in Nomarchy — use plain NixOS options if you need bolt.

Microcode / kernel firmware

  • CPU microcode: from nixos-hardware common-cpu-* and nixos-generate-config once redistributable firmware is on — not a separate nomarchy.* toggle.
  • GPU GuC/HuC (Intel i915): nomarchy.hardware.intel.guci915.enable_guc=3. Installer turns this off when the bound driver is xe (GuC is default there; the param is ignored).
  • hardware.enableAllFirmware: not set. Oddball non-redistributable WiFi still needs a manual NixOS fix (or a broader policy decision).

5. Fingerprint (deep dive)

Detect → enable

Installer scans USB vendor IDs common to libfprint (Goodix, Synaptics, Elan, …) via lsusb or /sys/bus/usb/.../idVendor. On hit:

nomarchy.hardware.fingerprint.enable = true;  # services.fprintd
# nomarchy.hardware.fingerprint.pam = true;   # login + sudo (opt-in)
# nomarchy.hardware.fingerprint.parallel = false;  # sequential prompt instead

Enroll (menu or CLI)

Shipped #55: System Fingerprint (self-gated when fprintd-list is on PATH) — a single Fingerprint (on/off) switch, plus Enroll / List / Verify / Delete all (all usable while it's off — turning it on needs an enrolled finger). The switch writes settings.fingerprint.pam, the one state key behind both halves of "use my finger": login/sudo PAM here, and the lock-screen unlock in modules/home/idle.nix. It runs nomarchy-fingerprint, which sudos a system rebuild and then a home switch, because the two halves live in different configurations.

It does not decide whether login prompts at all: auto-login skips the greeter entirely, so this adds the finger to the prompts that actually happen — sudo, the lock screen, and the greeter only when auto-login is off.

Hints (#73): MOTD line when fingerprint.enable is on; first-boot tip when fprintd-list is on PATH (SUPER+M → System Fingerprint / fprintd-enroll). No permanent nag without a reader.

# CLI still works:
fprintd-enroll
fprintd-list "$USER"
nomarchy-fingerprint toggle     # or on | off | status — what the menu row runs

PAM stays opt-in on purpose: password-only remains the cautious default until a finger is enrolled. Full enroll on a real reader is V3/hardware.

Auto-login

settings.greeter.autoLogin (System Auto-login, or nomarchy-autologin [toggle|on|off|status]) decides whether boot goes straight to the desktop or stops at the greeter. The installer seeds it ON for LUKS-encrypted machines — the disk passphrase already gates the machine, so a greeter password is a second prompt for the same thing — and leaves it off without LUKS, where the greeter is the only thing between power-on and the desktop. It's baked into greetd at system rebuild, so the change shows on the next boot.

Auto-login and fingerprint are independent, and auto-login wins at boot: with it on you are never asked for anything at startup, whatever the fingerprint switch says. Turn auto-login off and the greeter asks — for a password, or a password or finger when fingerprint is on.

Both are in-flake state rather than lines in system.nix on purpose: a hand-set nomarchy.system.greeter.autoLogin (or nomarchy.hardware.fingerprint.pam) outranks the state and pins the setting, leaving the menu toggle unable to move it. That's the escape hatch, not the default — leave those lines commented to use the menu.

Parallel prompt (password or finger, whichever first)

With fingerprint.pam on, sudo/login/hyprlock show one prompt that accepts either factor — type the password or touch the sensor (2026-07-12; pam-fprint-grosshack, an fprintd fork, since stock PAM can't express parallel factors). This is the default; fingerprint.parallel = false restores stock pam_fprintd's sequential wait-for-the-reader-then-password. Lockout safety is structural: the module never validates passwords itself — a typed password is handed to the normal pam_unix rule, and every failure (no reader, fprintd hung, timeout) falls through to password, so finger auth can only ever add a way in. Verify the wiring with grep pam_fprintd_grosshack /etc/pam.d/sudo. Known cosmetic quirk: after a fingerprint win a leftover password prompt may linger on the console.

Doctor

nomarchy-doctor reports fprintd unit + enroll status when present.

6. NVIDIA (deep dive)

What happens at install

lspci → NVIDIA  ⇒  MODULE common-gpu-nvidia

That is the entire Nomarchy surface. Unfree packages are allowed (allowUnfree = true in the module and in mkFlake), so the proprietary path from nixos-hardware can evaluate.

There is no nomarchy.hardware.nvidia.* for:

  • hybrid / PRIME (Intel+NVIDIA, AMD+NVIDIA)
  • open vs closed kernel module
  • power management / udev / suspend quirks
  • CUDA / container toolkit packages

What a hybrid laptop user must do today

  1. Confirm common-gpu-nvidia (and often common-gpu-intel or common-gpu-amd) are in hardwareProfile.
  2. Read the relevant nixos-hardware module and NixOS NVIDIA wiki.
  3. Add plain NixOS options in system.nix, for example (illustrative — hardware-specific):
# Example only — verify against your generation and nixos-hardware module.
# hardware.nvidia.prime = { ... };
# hardware.nvidia.powerManagement.enable = true;
# hardware.nvidia.open = false;  # or true for open modules on newer cards
  1. Rebuild the system. Home Manager does not own the driver.

Live ISO note

The ISO lists nouveau among available initrd modules and does not force-load every GPU driver (avoids multi-driver panics). Proprietary NVIDIA on the live session is not the product focus; installed systems use the profile.

Product direction (shipped #59; first-class wrappers deferred for v1): when common-gpu-nvidia is in hardwareProfile, the installer emits a commented system.nix block with PRIME / power / open-module pointers (same pattern as ROCm / NPU comments). No nomarchy.hardware.nvidia.* stack for v1 — hybrid PRIME remains wiki/plain NixOS until a maintainer commits to hardware testing.

7. Day-2: “my laptop is mostly fine, make it fully fine”

Goal How Rebuild?
Power profile (perf/balanced/saver) System menu / Waybar No (PPD D-Bus)
Charge limit 80% Menu / CC — live sysfs + state; boot oneshot re-applies No rebuild for live; rebuild bakes Nix option
Thermald (Intel) Installer on for Intel laptops; else power.thermal.enable System
Fingerprint enroll fprintd-enroll No
Fingerprint login fingerprint.pam = true System
ROCm / Intel compute Uncomment opt-ins in system.nix System (large)
NPU driver Uncomment npu (+ often latestKernel) System; userspace BYO
Newer kernel for brand-new silicon nomarchy.hardware.latestKernel = true System
Hide IR “dark camera” Installer or camera.hideIrSensor System
Firmware fwupdmgr update Reboot if capsule requires
Model quirks missing Set better hardwareProfile (see §8) System
OpenRGB / printing / Steam nomarchy.services.* System

Dual-sensor webcam / IR hide

Many dual-sensor modules (e.g. ThinkPad T14s) expose colour + IR as two identically named “Integrated Camera” nodes. Picking the IR node yields a black/dark greyscale frame — the classic “my webcam is dark” symptom.

nomarchy.hardware.camera.hideIrSensor (installer-on when RGB+IR names are detected; overridable irMatch) drops the IR node from WirePlumbers v4l2 monitor so native PipeWire pickers only offer the colour camera. The kernel /dev/video* node stays open, so Howdy-style face unlock still works. Design history: ROADMAP § Webcam.

What it does not cover: apps that list cameras via libcamera or the xdg-desktop-portal / Flatpak camera path still see both sensors — a Flatpak Zoom (or similar) user can still pick the black IR “camera”. That is intentional: a blanket libcamera disable would risk external USB cams that need the libcamera path, and surgical internal-only libcamera rules could not match early enough (only device.api binds before the WirePlumber monitor rule).

Workaround: prefer the colour device in the picker (or any non-IR name). Apps that default to the first v4l2 colour source without a picker are fine.

Further engineering (needs T14s-class hardware): (b) a WirePlumber libcamera monitor rule disabling GREY-only nodes; (c) a libcamera/udev quirk at the libcamera layer. Neither is implemented — the recommended path is document-only until those can be verified on real dual-sensor hardware (see agent/HARDWARE-QUEUE.md T14s).

Theme switches never touch drivers (Home Manager only).

8. Unsupported or unlisted machines

Still good floor

Even with no DMI hit you usually get:

  • common-cpu-{intel,amd}
  • common-gpu-{intel,amd,nvidia} as applicable
  • common-pc or common-pc-laptop + optional common-pc-ssd
  • nomarchy.hardware.intel or .amd when vendor matches
  • Layer A (firmware, audio, BT, PPD, fwupd)

You lose model-specific EC/suspend/keyboard/audio quirks that only exist in a named nixos-hardware module.

Pick a profile after install

  1. List candidates:

    nix eval github:NixOS/nixos-hardware#nixosModules \
      --apply builtins.attrNames
    # or: the ISO ships hardware-modules.txt for the same list
    
  2. Set in your flake (installer already uses a list):

    hardwareProfile = [
      "common-cpu-amd"
      "common-gpu-amd"
      "common-pc-laptop"
      "common-pc-ssd"
      "lenovo-thinkpad-t14-amd-gen3"  # if it matches
    ];
    
  3. sudo nixos-rebuild switch --flake ~/.nomarchy#default

Template / migration (no installer)

See MIGRATION.md: reuse hardware-configuration.nix, set hardwareProfile, uncomment nomarchy.hardware / power in system.nix. Post-install re-probe (shipped #58):

nomarchy-detect-hw        # human report + suggested snippets
nomarchy-detect-hw --raw  # MODULE / NOMARCHY / DETAIL protocol lines

Prints suggested hardwareProfile and system.nix lines; does not rewrite the flake. Paste after review, then sudo nixos-rebuild switch.

9. Install-tested machines (hall of fame)

Models that have seen a real Nomarchy session (live ISO, install, or day-to-day QA) — not a guarantee of every feature, just a public seed list. DB coverage (hardware-db.sh) is broader; this table is the smaller “someone actually sat at it” set.

Model DMI (sys_vendor × product_name / version) Typical hardwareProfile Last noted Notes
Lenovo ThinkPad T14s Gen 4 (AMD) LENOVO × 21F8CTO1WW / ThinkPad T14s Gen 4 common AMD laptop + SSD (plus nomarchy.hardware.amd / fingerprint / IR cam as probed) 2026-07 Maintainer day-to-day + HARDWARE-QUEUE (IR portal, fingerprint, NPU). Dual-sensor webcam is the motivating IR case.
Dell Latitude 5410 Dell Latitude 5410 (Intel) common Intel laptop + SSD (+ GuC when enabled) 2026-07 Primary Intel hardware-QA host (session, themes, polkit, bar).
Dell Latitude 5310 Dell Latitude 5310 (Intel) same family as 5410 2026-07 Charge-limit / power QA sibling (see HARDWARE-QUEUE).

Send your DMI line

If you install Nomarchy on a machine and it works (or fails in an interesting way), open a PR that:

  1. Adds a row to the table above (model, DMI, profile, date, short notes).
  2. Optionally adds a HARDWARE_DB line in pkgs/nomarchy-install/hardware-db.sh when nixos-hardware has a matching module (§10).

Quick DMI grab:

printf '%s | %s | %s\n' \
  "$(cat /sys/class/dmi/id/sys_vendor)" \
  "$(cat /sys/class/dmi/id/product_name)" \
  "$(cat /sys/class/dmi/id/product_version)"
nomarchy-detect-hw   # suggested MODULE / NOMARCHY lines

10. Adding your model to the distro

For contributors (and power users who will PR):

  1. On the machine:

    cat /sys/class/dmi/id/sys_vendor
    cat /sys/class/dmi/id/product_name
    
  2. Find a matching attr in nixos-hardware (or add one upstream first).

  3. Append to pkgs/nomarchy-install/hardware-db.sh in HARDWARE_DB:

    "VendorRegex|Product regex|nixos-hardware-module-name"
    

    First match wins — put specific lines above broad fallbacks.

  4. Verify the name exists in the pinned nixos-hardware input (mkFlake will throw if not). A CI check that every DB name ∈ nixosModules is queued so lock bumps cannot silently break installs.

  5. Optional: note on-hardware QA steps in agent/HARDWARE-QUEUE.md. Install-tested status goes in the hall-of-fame table (§9).

11. Doctor and hardware health (current vs target)

Today (nomarchy-doctor): failed units, disk space, theme-state validity/git, generation age, snapper; hardware section self-gates per machine (NetworkManager, audio sink, GPU smoke, fprintd, fwupd, charge limit, battery health, hibernate/zram). All read-only; each ✖ prints one fix command.

Check Pass condition Suggested fix line
NetworkManager device connected or wifi radio on open System Network
Audio sink default sink exists System Audio
GPU accel glxinfo/vainfo smoke (if installed) check hardwareProfile / drivers
Fingerprint if USB VID matched / fprintd unit fprintd-enroll or enable option
fwupd daemon active; optional “updates pending” warn fwupdmgr get-updates
Battery threshold if laptop + limit set, sysfs reports it power docs / restart charge-limit unit
Battery health cycle_count and/or charge|energy_full÷design % when sysfs exports them report-only (warn if <70% of design)
First-boot pre-activate installer log present + no HM generation home-manager switch --flake ~/.nomarchy -b bak
Hibernate / zram disk swap + resume=; zram active docs/MIGRATION.md → Enabling hibernation

12. Option quick reference

Full tables: README § options. Hardware-shaped surface:

Option Role
mkFlake.hardwareProfile nixos-hardware name or list
nomarchy.hardware.intel.enable / .guc / .computeRuntime Intel gap layer
nomarchy.hardware.amd.enable / .pstate / .vaapi / .rocm.* AMD gap layer
nomarchy.hardware.fingerprint.enable / .pam / .parallel fprintd + PAM (parallel password-or-finger prompt by default)
nomarchy.hardware.npu.enable in-kernel NPU only
nomarchy.hardware.latestKernel linuxPackages_latest
nomarchy.hardware.camera.hideIrSensor / .irMatch dual-sensor webcams (v4l2 only; §7)
nomarchy.hardware.i2c.enable / .ddcci I2C + external backlight
nomarchy.system.power.* PPD/TLP, laptop, thermald, charge limit
nomarchy.system.bluetooth.enable BT stack
services.fwupd.enable LVFS (native NixOS, default on)

13. Ease summary

Situation Effort
Known model in DB (Framework, many ThinkPads, …) Low — install and go
Unknown modern Intel/AMD laptop Lowmedium — commons cover a lot
Firmware updates Medium — CLI only until product work lands
Fingerprint for login Medium — enroll CLI + PAM uncomment
Hybrid NVIDIA High — plain NixOS/wiki territory
ROCm / NPU userspace High — opt-in + expert
Contribute a new DMI line Medium for someone who can PR
Path Role
modules/nixos/hardware.nix nomarchy.hardware.*
modules/nixos/power.nix PPD/TLP, charge limit, thermald
modules/nixos/default.nix firmware, fwupd, ddcci default
pkgs/nomarchy-install/hardware-db.sh DMI DB + probes
pkgs/nomarchy-install/nomarchy-install.sh writes flake + system.nix
lib.nix hardwareProfile resolution
templates/downstream/system.nix commented opt-ins
agent/HARDWARE-QUEUE.md on-machine V3 checks