Buying the right GPU for your homelab is one decision. Getting Proxmox to actually hand that GPU to a VM or container is a separate one, and it’s where a lot of people get stuck, because Proxmox actually supports two completely different ways to do it, and picking the wrong one for the job means either a fight with IOMMU groups you didn’t need to have, or a container that can’t do what you needed a full GPU for. Here’s what each path actually requires, and how to pick between them.
Two different things called “GPU passthrough”
- Full PCIe passthrough to a VM. The GPU is handed to one virtual machine as if it were physically installed inside it. The host can no longer see or use the card while the VM is running. This is real hardware isolation, the VM gets full driver access, full performance, and the ability to do anything the card supports, including things like CUDA compute or a Windows gaming setup with the card’s own drivers.
- Device passthrough to an LXC container. Instead of handing over the whole PCIe device, you expose specific device nodes (
/dev/dri/renderD128for Intel/AMD hardware encode,/dev/nvidia*for NVIDIA) into one or more containers. The host keeps its own driver loaded and keeps using the card too. Multiple containers can share the same GPU this way, each getting a slice of its encode/decode or compute capability.
These aren’t two settings on the same feature, they’re architecturally different. VM passthrough gives one guest exclusive hardware ownership. LXC device passthrough gives many guests shared access to a GPU the host still controls. Picking the right one up front saves you from setting up IOMMU groups and vfio-pci binding for a Jellyfin transcode job that never needed exclusive hardware access in the first place.
When each one is actually the right call
- Use LXC device passthrough for transcoding and inference workloads: Plex, Jellyfin, Frigate’s object detection, Immich’s ML features, Ollama for a small local model. None of these need the whole GPU to themselves, and sharing across containers means one card can serve several services at once instead of sitting idle between requests. This is also the simpler setup by a wide margin, no IOMMU groups, no vfio-pci binding, no reset bugs to work around.
- Use full VM passthrough when a guest genuinely needs the whole card: a Windows gaming VM, a workload that needs the card’s own vendor drivers and tooling with no host driver in the way, or GPU compute work that wants guaranteed, undivided access. If you only have one GPU and want it in a gaming VM sometimes and available to the host or other containers other times, you’re signing up for hotplug scripts or a reboot between mode switches, plan for that up front rather than discovering it after the fact.
If you’re not sure which one you need, ask whether you actually need the host to lose access to the card while it’s running. If the answer is no, you almost certainly want LXC passthrough, it’s less setup and doesn’t sacrifice a GPU that could otherwise be shared.
What both paths need first: IOMMU
Whether you’re doing full VM passthrough or LXC device passthrough, IOMMU (Intel VT-d or AMD-Vi) needs to be enabled, since it’s what lets the hypervisor safely map a device’s memory access for a guest, or in the LXC case, what makes device isolation and cgroup-based access control possible at all.
- Enable VT-d (Intel) or AMD-Vi (AMD) in the motherboard’s BIOS/UEFI. This is off by default on plenty of consumer boards.
- Add
intel_iommu=onoramd_iommu=onto the kernel command line. On a standard Proxmox install with GRUB, that’s/etc/default/grub’sGRUB_CMDLINE_LINUX_DEFAULTline, followed byupdate-grub. On a ZFS-root install using systemd-boot instead, it’s/etc/kernel/cmdlinefollowed byproxmox-boot-tool refresh, easy to get wrong if you assume every Proxmox box uses GRUB. - Reboot, then confirm it actually took with
dmesg | grep -e DMAR -e IOMMU. You want to see IOMMU being enabled, not a message saying it’s not supported.
Full VM passthrough: the extra steps and the gotchas
Past IOMMU, VM passthrough needs the GPU bound to the generic vfio-pci driver instead of whatever driver Proxmox would normally load for it, so the host never touches the card and it’s free to hand to the VM cleanly.
- Check IOMMU groups with a script that walks
/sys/kernel/iommu_groups/. Every device sharing a group with your GPU (often its HDMI audio function, sometimes unrelated onboard devices depending on your board’s PCIe topology) has to be passed through together or isolated from the group, you can’t split a group’s devices between host and guest. Poor IOMMU grouping is one of the most common reasons passthrough fails on consumer motherboards, and there’s no software fix for bad grouping beyond an ACS override patch, which is a real security tradeoff (it weakens the isolation IOMMU groups exist to provide) and shouldn’t be your first move. - Bind the GPU to vfio-pci at boot, before any other driver claims it, by adding its PCI vendor:device ID to
/etc/modprobe.d/vfio.conf(options vfio-pci ids=xxxx:yyyy,xxxx:zzzzfor the GPU and its audio function) and blacklisting the normal driver (nouveau,amdgpu, or the Nvidia driver) so it never grabs the card first. - Add the PCI device to the VM config, either through the web UI’s Hardware tab (Add > PCI Device) or directly in the VM’s config file, with
pcie=1set if your board and the VM’s machine type support PCIe passthrough properly rather than falling back to legacy PCI. - Consumer NVIDIA cards have a known reset bug. Many GeForce cards don’t cleanly reset their state when a VM shuts down, so the next VM start (or the host trying to reclaim the card) fails until a full host reboot. The community fix is the
vendor-resetkernel module for AMD cards, and various workarounds for NVIDIA depending on the specific card generation, worth checking before you commit to a specific used card for passthrough, since this is a real, well-documented limitation, not a rare edge case. - Single-GPU passthrough (no second GPU or iGPU for the host to fall back on) is possible but adds real complexity: you need the host to release the card cleanly when the VM starts and reclaim it when the VM stops, usually via hookscripts that unbind/rebind the driver around VM start/stop. If you have an iGPU available for the host to use instead, use it, it removes an entire category of problems.
LXC device passthrough: the simpler path
For sharing a GPU across containers instead of dedicating it to one VM, you’re not touching IOMMU groups or vfio-pci at all, you’re just exposing device nodes into the container.
- Intel/AMD (VAAPI, via
/dev/dri): on the Proxmox host, confirm/dev/dri/renderD128(andcard0) exist and that the right host driver (i915for Intel,amdgpufor AMD) is loaded. In the container’s config (/etc/pve/lxc/<vmid>.conf), add the device passthrough lines mapping those device nodes in, and make sure the container’s user has the matching group ID forvideo/renderso it actually has permission to use them, not just see them. - NVIDIA (via
/dev/nvidia*): this needs the NVIDIA driver installed on the Proxmox host itself, plus matching device nodes (/dev/nvidia0,/dev/nvidiactl,/dev/nvidia-uvm, and so on) passed into the container, and typically the NVIDIA container toolkit or matching userspace libraries installed inside the container too so it can actually talk to the driver, not just see the device files. - Unprivileged containers add one more wrinkle: the UID/GID mapping between container and host means the device permissions that work fine in a privileged container can silently fail in an unprivileged one until you add the right
lxc.idmapentries, or explicitly allow the relevant device major/minor numbers vialxc.cgroup2.devices.allow. This is the single most common “I passed the device in and it still says permission denied” issue with unprivileged LXCs. - Multiple containers, one GPU: unlike VM passthrough, several containers can point at the same
/dev/dri/renderD128at once, that’s the whole appeal for something like running Jellyfin and Frigate on the same box, both hardware-accelerated, off one card, without needing to decide which one “owns” the GPU.
Bottom line
Don’t default to full PCIe passthrough because it’s the more commonly documented path online, it’s the wrong tool for most homelab GPU use cases. If you’re running Plex, Jellyfin, Frigate, or a small local AI workload, LXC device passthrough gets you hardware acceleration with a fraction of the setup and none of the reset-bug headaches, and it lets several services share one card instead of locking it to a single VM. Reach for full VM passthrough only when a guest genuinely needs the whole GPU: a gaming VM, or a workload that specifically needs the card’s own drivers with nothing else in the way. Either path starts with IOMMU enabled in BIOS and the kernel command line, everything after that forks based on which kind of access the workload actually needs.