feat(macpro31): NVIDIA Quadro P400 driver and CUDA-enabled Docker
CI / flake (push) Skipped
CI / flake (pull_request) Successful in 4m11s

The stock GPU has been replaced with a Quadro P400 (Pascal, GP108). Add
hosts/MacPro31/nvidia.nix:

- Driver branch 580 (nvidiaPackages.legacy_580), not the nixpkgs default
  production branch (595.x). 580 is the last branch supporting
  Maxwell/Pascal/Volta and is an LTS branch until Aug 2028; a newer one
  does not drive this card.
- modesetting.enable for Wayland (nvidia-drm.modeset=1), open = false
  (the open kernel modules need Turing or later), and sway
  --unsupported-gpu, which wlroots requires with the proprietary driver.
- Docker with GPU access via CDI (hardware.nvidia-container-toolkit),
  rather than the deprecated virtualisation.docker.enableNvidia runtime
  wrapper. Containers run with --device=nvidia.com/gpu=all and must ship
  a CUDA 12.x or older runtime: CUDA 13 dropped sm_61.

The driver packages are unfree, so allowlist them in unfreePackages; they
are not cached and the kernel module builds on the host.

Also declare features.cpu.microarchLevel = 1 for this machine: the
Harpertown Xeons have SSE4.1 but no SSE4.2/POPCNT, which switches off
Claude Code through the fleet-wide gate.
This commit is contained in:
Emma Thorpe
2026-08-17 20:35:39 +01:00
parent 0d13581896
commit 0f7fb7f78a
3 changed files with 77 additions and 22 deletions
+6
View File
@@ -111,8 +111,14 @@
]; ];
# Unfree packages permitted to be built (replaces blanket allowUnfree). # Unfree packages permitted to be built (replaces blanket allowUnfree).
# The NVIDIA entries are for the Mac Pro's Quadro P400 (hosts/MacPro31/
# nvidia.nix); unfree packages are not in the binary cache, so the
# kernel module is compiled on the host.
unfreePackages = [ unfreePackages = [
"claude-code" "claude-code"
"nvidia-x11"
"nvidia-kernel-modules"
"nvidia-settings"
]; ];
# Per-user identity, keyed by username. See README "Users". # Per-user identity, keyed by username. See README "Users".
+62 -11
View File
@@ -1,7 +1,7 @@
# Mac Pro 3,1 (Early 2008) — install notes # Mac Pro 3,1 (Early 2008) — install notes
Flake host: `lyrathorpe-macpro31`. Desktop (`portable = false`, imports Flake host: `lyrathorpe-macpro31`. Desktop (`portable = false`, imports
`../../modules/desktop.nix`). Files: `configuration.nix`, `../../modules/desktop.nix`). Files: `configuration.nix`, `nvidia.nix`,
`hardware-configuration.nix`. `hardware-configuration.nix`.
## Hardware configuration ## Hardware configuration
@@ -27,18 +27,69 @@ either
Partition the disk GPT with an ESP (vfat). Partition the disk GPT with an ESP (vfat).
## Graphics ## Graphics — NVIDIA Quadro P400
The stock card varies between units — **ATI Radeon HD 2600 XT** or **NVIDIA The stock card (**ATI Radeon HD 2600 XT** or **NVIDIA GeForce 8800 GT**,
GeForce 8800 GT**. No proprietary driver is hardcoded; Sway relies on in-tree KMS: depending on the unit) has been replaced with an **NVIDIA Quadro P400** (Pascal,
GP108). Everything driver-related lives in [`nvidia.nix`](./nvidia.nix):
- ATI Radeon HD 2600 XT → `radeon` (or `amdgpu`) KMS - **Driver branch 580** (`nvidiaPackages.legacy_580`), _not_ the nixpkgs default
- NVIDIA GeForce 8800 GT → `nouveau` KMS (`production`, currently 595.x). 580 is the last branch that supports
Maxwell/Pascal/Volta and is maintained as an LTS branch until Aug 2028; a
newer branch does not drive this card at all.
- `modesetting.enable = true` — mandatory for Wayland (sets
`nvidia-drm.modeset=1`); without it wlroots gets no GBM device and both Sway
and the greeter fail to start.
- `open = false` — the open kernel modules require Turing or later.
- Sway runs with `--unsupported-gpu` (`programs.sway.extraOptions`); wlroots
refuses the proprietary driver otherwise. `cage`/ReGreet needs no such flag.
- nouveau and `nvidiafb` are blacklisted automatically by the NVIDIA module.
These come up automatically. If a card needs forcing, set The driver is unfree, so it is **not in the binary cache**: the kernel module is
`services.xserver.videoDrivers` and/or add the module to compiled on the machine, which on these 2008 Xeons is slow — budget for a long
`boot.initrd.kernelModules` for early KMS (see the comment in first rebuild and again after every kernel bump. The package names are
`configuration.nix`). allowlisted in `unfreePackages` in [`flake.nix`](../../flake.nix).
Note the Mac Pro shows no EFI boot screen with a stock PC card (no Apple EFI
ROM): the machine boots blind until KMS brings the display up. That is expected,
not a fault.
Verify after a rebuild:
```sh
nvidia-smi
```
## Docker with CUDA
`nvidia.nix` also enables Docker and gives containers GPU access via **CDI**
(`hardware.nvidia-container-toolkit.enable`), which generates device specs from
the host driver at boot (regenerated by a udev rule when the `nvidia` device
appears) and turns on the daemon's CDI feature:
```sh
docker run --rm --device=nvidia.com/gpu=all nvidia/cuda:12.9.1-base-ubuntu24.04 nvidia-smi
```
- Use the `--device=nvidia.com/gpu=all` form. `--gpus all` is the legacy
runtime-wrapper path (`virtualisation.docker.enableNvidia`), which is
deprecated upstream and deliberately not enabled here.
- **CUDA version matters.** The P400 is compute capability 6.1 (`sm_61`); CUDA
13 dropped Maxwell/Pascal/Volta, so container images must ship a **CUDA 12.x
or older** runtime. The 580 driver itself is happy with either.
- 2 GB of VRAM, 256 CUDA cores — fine for encode/decode and small models, not
for training anything serious.
- Docker socket is local-only (no TCP listener, unlike the Pi). Users need the
`docker` group; the registry already grants it.
## Claude Code — not installed here
The dual Harpertown Xeons are **x86-64-v1** (SSE4.1, but no SSE4.2/POPCNT) and
the Node runtime Claude Code ships on requires x86-64-v2. `configuration.nix`
declares `features.cpu.microarchLevel = 1`, which switches the tool off through
the fleet-wide gate in [`../../modules/features.nix`](../../modules/features.nix)
— see the root README. Forcing `features.claudeCode.enable` on here is an
evaluation error, not a broken install.
## Networking ## Networking
@@ -52,7 +103,7 @@ Graphical login via a Wayland greeter — `greetd` running ReGreet inside the
every Sway host (gated on `features.swayDesktop.enable`). The greeter is forced every Sway host (gated on `features.swayDesktop.enable`). The greeter is forced
to the Dvorak layout to match the console and Sway session. Set the user to the Dvorak layout to match the console and Sway session. Set the user
password (`passwd lyrathorpe`) after install, or the greeter cannot password (`passwd lyrathorpe`) after install, or the greeter cannot
authenticate. Requires working KMS (radeon/nouveau — see Graphics). authenticate. Requires working KMS (NVIDIA modesetting — see Graphics).
## Apply ## Apply
+9 -11
View File
@@ -7,8 +7,14 @@
{ {
imports = [ imports = [
./hardware-configuration.nix ./hardware-configuration.nix
./nvidia.nix
]; ];
# Dual quad-core Xeon (Harpertown/Penryn): SSE4.1 but no SSE4.2 or POPCNT,
# i.e. x86-64-v1. Declaring it here switches off the fleet flags that need a
# newer CPU -- currently features.claudeCode (see ../../modules/features.nix).
features.cpu.microarchLevel = 1;
# The Mac Pro 3,1 has 64-bit EFI (confirmed by the owner), so boot via # The Mac Pro 3,1 has 64-bit EFI (confirmed by the owner), so boot via
# systemd-boot like the MBP -- no GRUB/BIOS shim needed. # systemd-boot like the MBP -- no GRUB/BIOS shim needed.
boot.loader.systemd-boot.enable = true; boot.loader.systemd-boot.enable = true;
@@ -33,17 +39,9 @@
# enabled in workstation.nix. # enabled in workstation.nix.
hardware.cpu.intel.updateMicrocode = true; hardware.cpu.intel.updateMicrocode = true;
# GPU note: the stock card varies between units -- ATI Radeon HD 2600 XT or # GPU: the stock card (ATI Radeon HD 2600 XT / NVIDIA GeForce 8800 GT) has
# NVIDIA GeForce 8800 GT. Sway needs a working KMS/modesetting driver; do NOT # been replaced with an NVIDIA Quadro P400. Driver, Wayland quirks and
# install a proprietary blob here. Depending on the installed card, rely on # GPU-enabled Docker live in ./nvidia.nix.
# the open kernel driver:
# - ATI Radeon HD 2600 XT -> "radeon" (older) or "amdgpu" KMS
# - NVIDIA GeForce 8800 GT -> "nouveau" KMS
# These come up automatically via the in-tree drivers + KMS, and the graphics
# stack itself is enabled by modules/sway.nix. If a card needs to be forced, add it
# here, e.g. `services.xserver.videoDrivers = [ "radeon" ];` (or "nouveau"),
# and/or `boot.initrd.kernelModules = [ "radeon" ];` in
# hardware-configuration.nix for early KMS.
# See `man configuration.nix` / the stateVersion docs before changing. # See `man configuration.nix` / the stateVersion docs before changing.
system.stateVersion = "26.05"; system.stateVersion = "26.05";