Workstation preparation; physical validation pending
Ryzen/Radeon/NVIDIA Windows workstation preparation
Radeon display, separate NVIDIA compute GPUs, Windows virtualization and safe initial installation.
Physical validation is pending. TacidOS is the permanent host. This guide prepares Ryzen 9 9950X, ASRock X870E Taichi OCF, 128 GB DDR5, two separate 4 TB NVMe SSDs, and two RTX 5080 cards with 16 GB VRAM each. Applications may distribute work across cards; this is never one physical 32 GB GPU. There is no motherboard driver: UEFI configuration, kernel drivers, microcode and firmware come through NixOS.
| Mode | Windows | Linux compute | TacidOS display |
|---|---|---|---|
| Linux AI (initial) | stopped, no active PCI ownership | both NVIDIA cards | Radeon motherboard output |
| Parallel | one complete GPU IOMMU group | other NVIDIA card | Radeon motherboard output |
| Windows Compute | both complete GPU groups | no NVIDIA card; CPU inference available | Radeon motherboard output |
Inspection findings and changes
Before this branch, workstation enabled core, Hyprland/its existing shell, CLI tools,
Bluetooth, iwd/networkd/resolved and firewall. It did not enable libvirt or AI by
itself. The reference workstation evaluated with redistributable firmware disabled;
this branch enables it in the installed workstation profile for Radeon/network
controllers. AI selected the core inference tier and llama-cpp; package acceleration
was derived from the display profile. Detection enumerated PCI display devices by
class and kept each slot separately, even for identical vendor/device IDs, but
genesis selected NVIDIA ahead of AMD. Inference permitted only /dev/nvidia0, control
and UVM nodes and an ineffective directory grant for DRM. Libvirt existed only as
a curated optional service with /var/lib/libvirt persistence.
Now AMD+NVIDIA proposes AMD display and NVIDIA compute, including a reviewed AMD PCI
address for a stable DRM symlink. The generated proposal and detected slots are shown
before installation. This is a vendor heuristic, not proof that a particular AMD
card is integrated. Use --body to override any assignment. Existing NVIDIA-only profiles
retain their display drivers and compute defaults. Radeon display places amdgpu in
the initrd; compute NVIDIA modules load in stage 2. An Aquamarine device selection
restricts Hyprland to the declared display DRM node. Plymouth/UEFI output selection
still requires a motherboard-output boot and LUKS prompt test.
Pinned nixpkgs is 3ed67ec0a4d3c7ab4ae1f04f8ee8df07bfa506a2.
Evaluation reports Linux 6.18.48, NVIDIA stable 595.99.02, CUDA runtime 12.9.79,
llama-cpp 0.3.0, OVMF 202608 and swtpm 0.10.1-unstable-2026-05-21.
CUDA uses package-local overrides, not a global rebuild of nixpkgs with CUDA enabled.
NVIDIA open kernel modules still require unfree userspace; CUDA also requires license
acceptance. This branch fixes the driver assertion to accept allowUnfreePredicate
as well as allowUnfree. A predicate must admit all required CUDA/driver packages,
not just the kernel module. The documented initial owner choice is explicit
nixpkgs.config.allowUnfree = true; Tacid does not silently make it for you.
Evaluation/build evidence and limitations are in validation.
Version availability does not establish RTX reset, CUDA execution or motherboard support.
Safe first installation: choose only one SSD
First build and write the netinstall USB. This PR’s ISO has not been built here; verify the image’s source revision before relying on its installer.
-
In UEFI enable SVM (AMD virtualization), AMD-Vi/IOMMU and integrated graphics; select integrated graphics as primary and keep it enabled with discrete cards. Connect the Linux monitor input to the motherboard. Record firmware version; firmware updates are a separate owner decision, not an installer action.
-
Boot the Tacid netinstall medium. Check wired networking first. Inventory with
lsblk -d -o NAME,SIZE,MODEL,SERIAL,WWNandls -l /dev/disk/by-id. Match the entire selected NVMe by serial/model, stable ID and size, notnvme0n1discovery order. With two equal-sized SSDs, size alone is not identity. Keep the other SSD untouched; do not supply it as a VM raw disk. Physically disconnecting the second SSD for installation is an optional additional precaution. -
Create a reviewed
workstation-owner.nixbody module on the live medium:{ lib, ... }: { # Explicit owner decision: NVIDIA driver and CUDA userspace are unfree. nixpkgs.config.allowUnfree = true; # Package-local CUDA llama.cpp through the normal package surface. tacid.packages.ai = [ "llama-cpp" ]; tacid.core.infer.profile = "core"; # Review generated gpu.profile/computeProfile/displayPciAddress first. # If correcting them here, use lib.mkForce with your actual observed values. # Optional CUDA user access; replace USER with the installer username. users.users.USER.extraGroups = [ "video" "render" "libvirtd" ]; }Membership in
libvirtdgrants broad local virtualization authority. It does not grant an agent this permission. Review it explicitly; reconnect/login again after group changes. TacidOS does not run a graphical password agent here; the reviewed libvirtd group avoids depending on an unavailable authentication dialog. Polkit remains enabled for the local management policy. -
Run
tacid install --device /dev/disk/by-id/YOUR_SELECTED_ENTIRE_NVME --body workstation-owner.nixwith the normal hostname/user/keyboard/owner-key answers. Do not add--yesyet. Read the graphics facts, PCI slots, resolved disk path, byte size, full generated configuration, disk layout, encryption and swap plan. Passphrase/PIN files follow the existing installer procedure in the CLI manual. -
Only when the serial and complete plan are correct, rerun the same command with the existing
--yesexplicit confirmation and required secret files. Keeper physical confirmation/genesis-only execution still applies. The system is built before disk operations. The second SSD is not automatically selected or modified. Change the published initial login password immediately after first boot.
Do not copy example PCI addresses from tests. Missing IOMMU information is a reason to leave passthrough disabled, never to guess addresses or groups. Model storage and VM disks start as files on the installed SSD. Provisioning the second SSD later is another explicit, reviewed storage operation, outside this preparation PR.
ISO, drivers and boot recovery
The netinstall ISO uses the existing minimal live configuration: terminal/nervous
system, installer and disk/repair tools, UEFI and BIOS medium boot, iwd/networking,
and NixOS firmware for networking/recovery. It excludes the graphical closure,
model weights, CUDA toolkit and workstation virtualization closure. NVIDIA/CUDA,
Hyprland, virt-manager, QEMU and model engines are downloaded/built into the installed
system through pinned Nix packages. Do not prune linux-firmware based on assumptions
about the motherboard’s network controller. No uncontrolled driver download is added.
AMD microcode is selected from observed AuthenticAMD CPU facts; AMD display firmware
and amdgpu are NixOS mechanisms. Confirm the actual controller IDs after assembly.
If graphics fails, switch to a TTY (Ctrl+Alt+F2), use the Tacid CLI/TUI, or boot the
previous NixOS generation in the firmware boot menu. Preserve working generations
until hardware validation is complete. SSH recovery is opt-in via the existing
tacid.services.openssh service, authorized keys and reachable-service confirmation;
password/root SSH is disabled and host keys live under /persist/etc/ssh. Verify
SSH from another machine before relying on it. If neither desktop nor TTY boots,
boot the live medium, unlock/mount the selected SSD using its stable identity and
use existing NixOS rescue/nixos-enter procedures to select/rebuild the previous
pinned generation. Do not repartition as a driver repair. Driver changes remain
boot-class transactions; a rollback restores matching kernel/module/configuration.
Inference and CUDA
tacid-infer keeps DevicePolicy=closed and admits only DRM and NVIDIA frontend/UVM
character classes. NVIDIA frontend includes all numbered card nodes and nvidiactl;
UVM includes ordinary and tools nodes. /dev/nvidia-caps is not granted as a directory;
consumer RTX cards do not need a MIG capability grant. No USB/storage devices are
admitted. Inference keeps its video/render groups and no network route.
A CUDA service must be restarted when ownership changes: stop inference before Windows starts, then start it after ownership settles. Class rules resolve at service start; zero NVIDIA cards means CPU fallback, one card means one available CUDA device, two means both. A particular model may need reducing or unloading when only one card remains. Other user CUDA jobs must also finish; they are never killed by the guard. In Parallel mode launch Linux CUDA jobs only after Windows has claimed its card. The conservative guard checks all NVIDIA character and NVIDIA DRM nodes; an active job on even the retained card blocks a new ownership transition. This costs some convenience while the hardware’s recovery behavior is unknown.
Use nvidia-smi -L and query PCI bus IDs after every ownership change; ordinals may
change. Set application GPU visibility from the currently observed devices, not
persistent assumptions about GPU index 0. On hardware run a CUDA sample on each
card and jointly, then test llama-cli -m /path/to/reviewed.gguf -ngl 99 --split-mode layer --tensor-split 1,1 -c 4096 -p 'Explain the GPU split' (confirm
these flags with the installed engine’s --help). Select a licensed, checksum-verified
GGUF whose quantized weights exceed one card’s available VRAM but leave room in the
combined separate memories for context and buffers; observe allocations on both
cards. Do not place a model or download credentials in this repository.
Model file size is disk usage; it is not a VRAM budget. Loaded tensors, temporary compute buffers and KV cache consume memory separately. KV cache grows with context, sequences and concurrency. Concurrent agents may share one server/model but require additional cache slots; separate servers often duplicate weights. Plan each card’s 16 GB limit, system RAM and concurrency independently. The existing inference capacity policy defaults to zero declared VRAM and conservatively describes the largest single-card budget, not an automatically measured sum. Do not declare 32 GB as one physical card; a distributed model needs its own per-card checks. The policy does not promise that every multi-card model will fit.
Windows 11 Pro through the virtual console first
Workstation now enables the curated libvirt service, local Polkit and
programs.virt-manager. It installs QEMU/KVM via libvirt, virt-manager (with its
existing desktop launcher), OVMF, swtpm, the VirtIO driver media package and a
read-only Windows VM/GPU status launcher. Firmware discovery in this nixpkgs is
provided by QEMU automatically; the old qemu.ovmf.enable option is removed.
No TCP/TLS management listener is enabled. Default NAT offers DNS/DHCP to guests;
the service remains marked reachable in Tacid’s allowlist. Do not bridge a physical
LAN or expose libvirt over the network as part of this procedure.
- Supply your Windows 11 Pro ISO and license outside the repository. Open
Virtual Machine Manager, connect to local QEMU/KVM system (
qemu:///system). Checkvirsh -c qemu:///system capabilitiesfor KVM, firmware withvirsh -c qemu:///system domcapabilities, and create/start the local default NAT network if absent/inactive. Do not enable VM autostart during passthrough testing. - Create domain
windows11, select Windows 11, Q35 and UEFI Secure Boot-capable OVMF. Allocate a conservative starting budget such as 16 vCPUs, 32 GB RAM and a 200 GB qcow2 disk in/var/lib/libvirt/images, leaving RAM/CPU/disk for Linux. Use host-passthrough CPU. No PCI host devices yet. - Customize before installation: virtual TPM emulated, version 2.0, model CRB; virtual display/console (SPICE and virtual video); VirtIO disk and VirtIO network on the default NAT; virtual USB keyboard/tablet for console interaction. If selecting Secure Boot firmware, verify its keys/enrollment with the actual firmware presented to the guest rather than assuming the host’s keys apply.
- Locate driver ISO with
find /run/current-system/sw/share -iname '*virtio*.iso'(or inspectnix build nixpkgs#virtio-win --print-out-paths, making sure it is your pinned nixpkgs). Attach it as a second CD-ROM. In Windows setup load the VirtIO storage driver for Windows 11/amd64, then install networking and guest tools. Windows media and its license remain yours, not shipped with TacidOS. - Complete installation and verify virtual console, storage/networking and clean
shutdown/restart before enabling GPU passthrough. Export reviewed XML with
virsh -c qemu:///system dumpxml windows11for repeatability. Back up the offline VM disk, XML, NVRAM and TPM state together; do not clone a running vTPM.
/var/lib/libvirt keeps domain/network definitions, disks, OVMF NVRAM and libvirt’s
swtpm state; /var/lib/swtpm is also explicitly persisted. Both are part of the
curated service’s /persist binds on ephemeral-root systems. Keep disks/ISOs in a
persistent location, not /tmp or ephemeral /var paths outside these directories.
Homes and the genome have their existing persistence. Firmware store paths can
change between generations: verify existing domain firmware/emulator paths during
updates; stable /run/libvirt/nix-ovmf and nix-emulators paths are regenerated by
NixOS. Persistent guest state does not itself pin an obsolete firmware store path.
Reviewed passthrough and switching modes
Passthrough is disabled by default. After assembly inspect lspci -nnk,
find /sys/kernel/iommu_groups -type l, and each card’s PCI GPU and audio functions.
Record complete groups, including bridges/other devices; do not use ACS override
to pretend an isolation group has split. If a group includes the Radeon display,
boot disk, or other host-critical devices, refuse that topology and investigate
slots/firmware. Hardware feasibility is unresolved until this inventory is done.
In owner.nix enable tacid.virtualisation.passthrough.enable = true and set
pciAddresses to the actual, owner-approved complete groups. This enables the
NixOS VFIO modules and AMD IOMMU kernel parameters; it does not pre-bind anything by
vendor/device ID or assign a GPU automatically. Stage the change through the normal
owner/boot transaction and reboot to verify AMD-Vi. A missing group or unapproved
address is refused by the libvirt prepare hook. This owner-only module is outside
the agent’s writable surface.
For each transition:
- Cleanly shut down Windows; wait for
virsh domstate windows11to sayshut off. Never edit hostdev ownership or live-hotplug a GPU into a running VM. - Finish CUDA/rendering jobs yourself, stop their autostart sources and stop
tacid-inferthrough authorized owner service administration (sudo systemctl stop tacid-inferfrom the owner account; no new agent root operation). Inspectsudo fuser -v /dev/nvidia*and the NVIDIA DRM nodes identified in/sys/class/drm/*/device/vendor, plusnvidia-smi. Radeon desktop clients are excluded by the guard. Keep new jobs from starting until the transition ends. The prepare hook refuses active device users, unknown idleness or incomplete groups; it does not terminate them. The hook is a point-in-time check, not a scheduler lock against concurrent new processes. - In virt-manager add PCI host devices for one entire RTX group (Parallel) or
both (Windows Compute), including audio functions. Use managed hostdevs; confirm
dumped XML has
managed='yes'and the reviewed source BDFs. Do not globally bind10de:deviceIDs; identical cards would both be taken. Never select Radeon. - Explicitly start Windows. Libvirt performs managed detach/bind. Retain the virtual console for administration. If start fails, inspect logs and driver state; do not force removal of an in-use module. Check the status launcher and actual sysfs driver links before restarting Linux inference on retained cards.
- Shut Windows down cleanly. Libvirt attempts managed reattach. Verify the driver
is
nvidia,nvidia-smiworks, and the CUDA sample works on every returned card. Only then restart inference/user jobs. For Linux AI leave Windows stopped. For changing one-card to two-card assignment, edit the stopped domain and repeat. - Return to Linux without reboot is unproven. If a card stays on VFIO/unbound or CUDA fails, leave inference stopped, disable Windows autostart, shut down Windows and reboot the host into the last working generation. Check both cards before resuming jobs. A hung VM may require a host reboot; forced VM termination risks guest filesystem/TPM state and is an explicit owner recovery action.
The libvirt group/Polkit path authorizes VM operations. Tacid does not gain a new agent-owned GPU control verb. Avoid automatic VM start, save/resume or GPU hotplug. NixOS is configured to shut guests down on host shutdown and not restore previously running guests at boot; disable any individual guest autostart separately.
Physical output and controls
Virtual display is a Windows console inside a TacidOS window for installation, configuration and administration. Direct gaming output is HDMI/DisplayPort from the assigned RTX card to another input on the monitor or a suitable KVM switch. Switch that input yourself. Hyprland workspaces do not switch physical GPU inputs.
Keep a Linux keyboard available for recovery. Initially use the virtual console’s keyboard/mouse and audio. For gaming explicitly configure dedicated USB devices (persistent vendor/product/serial identities), a reviewed entire USB-controller IOMMU group, or a physical USB/KVM switch. Decide between GPU HDMI/DP audio, dedicated USB audio or virtual audio; include GPU audio hostdevs for physical output. Do not pass through the only host keyboard/controller without another recovery path. Looking Glass is a future investigation, not provided here.
The status launcher reads libvirt state and PCI driver links. A stopped VM whose card is still VFIO reports recovery required, not success. Unknown authorization or missing domain is displayed as unknown. It does not switch ownership or stop jobs.
No website source exists in this checkout; no external website deployment or hardware-support claim was made. The acceptance checklist is the evidence required before promoting any physical claims.