Passing a GPU to a Proxmox VM sounds intimidating — IOMMU groups, VFIO binding, driver blacklists, PCI IDs, and the dreaded NVIDIA Error 43. But the actual process is a small, well-defined set of kernel-level changes on the host plus a few VM config tweaks. Once they click into place, the GPU appears inside the VM with bare-metal performance.
This guide covers NVIDIA GPU passthrough on Proxmox VE 8.x, from BIOS settings through automated VM configuration. Whether you are offloading transcoding to a Plex LXC, running local LLMs in a GPU VM, or building a remote gaming workstation, the steps are the same.
Hardware Requirements and IOMMU Compatibility
Before touching any configs, verify your hardware supports passthrough:
- CPU: Intel with VT-d or AMD with AMD-Vi (virtually all modern desktop CPUs have this)
- Motherboard: BIOS option to enable VT-d / IOMMU and 4G decoding / Resizable BAR
- GPU: A second GPU for the Proxmox host (onboard Intel graphics is ideal) — the host needs a display output you are not trying to pass through
- Proxmox: VE 8.x or later, running kernel 6.8+
Run this quick check before proceeding:
|
|
If dmesg | grep IOMMU returns nothing, IOMMU is not enabled at the
kernel level yet. That is the first step.
Step 1: Enable IOMMU in BIOS and GRUB
BIOS Settings
Reboot your server and enter the BIOS setup. Enable:
| Setting | Intel | AMD |
|---|---|---|
| VT-d / IOMMU | Overclocking → CPU Features → Intel VT-d Tech | Advanced → IOMMU |
| Above 4G Decoding | PCI Subsystem Settings | Always enable |
| Resizable BAR | DMI/PCI Configuration | Sets correct MMIO window |
| Secure Boot | Disable | Causes driver issues with GPU |
GRUB Command Line
SSH into the Proxmox host and edit /etc/default/grub:
|
|
Find the GRUB_CMDLINE_LINUX_DEFAULT line. For Intel systems:
GRUB_CMDLINE_LINUX_DEFAULT="quiet intel_iommu=on iommu=pt"
For AMD systems:
GRUB_CMDLINE_LINUX_DEFAULT="quiet amd_iommu=on iommu=pt"
The iommu=pt flag tells the kernel to skip IOMMU mapping for devices
that are not being passed through. It reduces overhead and is safe to
include regardless of vendor.
Apply the change and reboot:
|
|
After reboot, verify IOMMU is live:
|
|
If interrupt remapping is not enabled (older hardware), you can work around it, though this reduces isolation:
|
|
Step 2: Inspect IOMMU Groups
Your GPU must be in its own IOMMU group. Devices in the same group must all be passed through together, which usually means passing both the VGA controller and the audio device as a pair.
Run this to dump every group:
|
|
Look for your GPU in its own group:
IOMMU Group 13 01:00.0 VGA compatible controller [0300]: NVIDIA ... [10de:2206]
IOMMU Group 13 01:00.1 Audio device [0403]: NVIDIA ... [10de:1aef]
If the GPU shares a group with unrelated devices (SATA controller, USB
controller, NVMe), passthrough is still possible but you must pass the
entire group — which includes those unrelated controllers. The
workaround is pcie_acs_override (detailed in the troubleshooting
section), but it weakens IOMMU isolation. For a homelab that is
usually acceptable; for a production environment, consider a different
PCIe slot.
Step 3: Bind the GPU to VFIO at Boot
Find your GPU’s PCI vendor and device IDs:
|
|
Copy both IDs (10de:2206,10de:1aef) — you need them for VFIO binding.
3.1 Blacklist Host GPU Drivers
The host must not load nvidia or nouveau for the passthrough GPU.
Blacklist both:
|
|
3.2 Load VFIO Kernel Modules at Boot
|
|
3.3 Bind the GPU PCI IDs to VFIO
Create the VFIO options file with your GPU’s IDs:
|
|
Replace 10de:2206,10de:1aef with your actual IDs. The disable_vga=1
prevents the VGA arbitration subsystem from interfering with the GPU.
3.4 Apply and Verify
|
|
After reboot, confirm VFIO has claimed the GPU:
|
|
If you see nvidia or nouveau instead, the blacklist did not take
effect. Check that your blacklist file has no typos and that
update-initramfs ran successfully.
Step 4: Create the Target VM
These settings are not optional for GPU passthrough. Deviating from them is the most common source of failures.
VM Creation Checklist
| Setting | Value | Why |
|---|---|---|
| Machine | q35 | Required for PCIe device assignment |
| BIOS | OVMF (UEFI) | Legacy BIOS cannot handle GPU ROM |
| EFI Disk | Add it | Required for OVMF; 64 MB is enough |
| CPU Type | host | Exposes host CPU features to the guest |
| Memory | Fixed amount, disable ballooning | Ballooning can conflict with GPU DMA |
You can set these from the CLI and avoid the web UI entirely:
|
|
Install the OS inside the VM normally before attaching the GPU. This way you can install NVIDIA drivers without the GPU being active yet.
Step 5: Attach the GPU to the VM
After the OS is installed and drivers are ready, shut down the VM and attach the PCI device:
|
|
Breaking down the flags:
01:00— PCI address of the GPU (vga + audio passed as pair per IOMMU group)pcie=1— Exposes the device on a PCIe bus inside the VM instead of PCI. Required for full bandwidthx-vga=on— Declares this GPU as the VM’s primary displayrombar=1— Exposes the GPU’s Option ROM to the guest
Also set vga: none so the VM does not create a virtual VGA display
that conflicts:
|
|
Start the VM and verify the GPU is visible inside the guest:
|
|
Step 6: NVIDIA Driver Installation and Error 43
Modern Drivers (465+)
NVIDIA drivers starting at version 465 no longer check the virtualization flag by default. If you are on driver 550 or newer, skip Error 43 workarounds — just install the driver normally:
|
|
Legacy or Stubborn Drivers — Hide the Hypervisor
If nvidia-smi shows “No devices were found” or Error 43, the driver
is detecting KVM and refusing to load. Hide it:
Add these lines to /etc/pve/qemu-server/$VM_ID.conf:
cpu: host,hidden=1
args: -cpu 'host,hv_vendor_id=NV43FIX,kvm=off'
hidden=1— QEMU hides the KVM signature from CPUID leaveshv_vendor_id=NV43FIX— Spoofs the Hyper-V vendor ID string (any 12-character value works)kvm=off— Clears the KVM feature bit so the driver sees a physical environment
After editing, reboot the VM. Verify with:
|
|
Windows VM — Ignore MSRs
Windows NVIDIA drivers sometimes issue unhandled Model-Specific Register (MSR) accesses that crash the VM. Prevent this on the host:
|
|
Step 7: Tesla P40 / Datacenter Cards for AI
The NVIDIA Tesla P40 is the sweet spot for homelab AI workloads. It has 24 GB of GDDR5 VRAM, costs €100–150 used, and has no display output — it is a pure compute card.
P40-Specific Configuration
|
|
The P40’s 24 GB VRAM requires a larger MMIO window than OVMF’s
default 32 GB allocation. Using cpu: host (as above) resolves this
automatically because OVMF adjusts the window based on host properties.
If you must use a different CPU type:
|
|
Attach the P40 without x-vga=on since datacenter cards have no
display output:
|
|
Install the CUDA toolkit inside the VM:
|
|
The P40 has passive cooling (no fans). In a desktop case, point a
120 mm fan directly at the card’s heatsink. In a server chassis, the
chassis fans must provide enough airflow — monitor temperatures with
nvidia-smi -l 5 during load.
Step 8: GPU Reset Fix with vendor-reset
Some NVIDIA cards (especially consumer models) cannot complete a PCIe reset after the VM shuts down. The GPU goes into a hung state and the host requires a full power cycle to recover.
Install the vendor-reset kernel module to fix this:
|
|
After reboot, verify:
|
|
With vendor-reset loaded, you can stop and start the GPU VM without needing a full server reboot. This is essential for homelabs running multiple GPU workloads that cycle VMs daily.
Automated Passthrough Setup Script
Save this as a one-shot script for future GPU installations:
|
|
Step 9: Performance Tuning
Enable Hugepages
Hugepages reduce TLB pressure when the GPU does DMA to VM memory:
|
|
Pin CPU Cores
Pin physical CPU cores to the VM to avoid NUMA migration overhead:
|
|
Use NUMA If the Host Has Multiple Sockets
|
|
This tells the VM to map its NUMA node 0 to host NUMA node 0, matching memory and CPU topology with the physical architecture. GPU DMA to remote NUMA memory is 2-3× slower.
Troubleshooting Common Failures
GPU Not Visible Inside VM
|
|
Most likely causes:
- Machine type is
i440fxinstead ofq35 - BIOS is Seabios instead of OVMF
- GPU is still claimed by
nvidiaornouveauon the host
Black Screen After VM Boot
Possible fixes:
- qm set $VM_ID --vga none
- Remove any --vga std or --vga virtio from VM config
- Ensure x-vga=on is set on the hostpci device
- Verify PCI address is correct
NVIDIA Error 43
This means the driver detected it is running in a VM and refused to load. Apply the hypervisor hiding steps from Step 6, then retry.
GPU Hangs After VM Stop / Reset Bug
Install vendor-reset (Step 8). If it still hangs:
- Check that
vendor-resetis listed inlsmod - Try
echo 1 > /sys/bus/pci/devices/0000:01:00.0/removethenecho 1 > /sys/bus/pci/rescanon the host to re-detect - As a last resort, the GPU’s PCIe slot may need a physical power cycle (cold boot)
Bad IOMMU Groups — ACS Override
If your GPU shares a group with unrelated devices, the nuclear option is PCIe ACS override. It reduces isolation but works:
Add to GRUB_CMDLINE_LINUX_DEFAULT in /etc/default/grub:
pcie_acs_override=downstream,multifunction
Then update-grub && reboot. Only use this when you cannot physically
move the GPU to another slot that isolates properly.
Summary
GPU passthrough on Proxmox is a well-trodden path with predictable steps:
- BIOS — Enable VT-d/AMD-Vi, Above 4G Decoding, disable Secure Boot
- GRUB —
intel_iommu=on(oramd_iommu=on) +iommu=pt - VFIO — Blacklist host GPU drivers, bind GPU PCI IDs to vfio-pci
- VM — Machine q35, BIOS OVMF, CPU host, disabled ballooning
- Attach —
hostpci0withpcie=1,x-vga=onandvga: none - Drivers — NVIDIA 550+ works out of the box; older drivers need hypervisor hiding
- Reset — Install vendor-reset to avoid hard-locking the GPU on VM stop
Once configured, the VM sees the GPU as a bare-metal device. AI inference, hardware transcoding, CUDA workloads, and even gaming VMs all benefit from near-native performance without dedicating an entire machine to each workload.