<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Passthrough on rHomelab</title><link>https://rhomelab.com/tags/passthrough/</link><description>Recent content in Passthrough on rHomelab</description><generator>Hugo</generator><language>en-US</language><lastBuildDate>Thu, 03 Sep 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://rhomelab.com/tags/passthrough/index.xml" rel="self" type="application/rss+xml"/><item><title>Proxmox GPU Passthrough: VM PCIe Passthrough vs LXC Device Passthrough</title><link>https://rhomelab.com/proxmox/gpu-passthrough-vm-vs-lxc/</link><pubDate>Thu, 03 Sep 2026 00:00:00 +0000</pubDate><guid>https://rhomelab.com/proxmox/gpu-passthrough-vm-vs-lxc/</guid><description>How to actually get a GPU into a Proxmox guest, the real difference between full VM PCIe passthrough and simple LXC device passthrough, and which one fits Plex, Frigate, or a gaming VM.</description><content:encoded><![CDATA[<p>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&rsquo;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&rsquo;t need to have, or a container that can&rsquo;t do what you needed a full GPU for. Here&rsquo;s what each path actually requires, and how to pick between them.</p>
<h2 id="two-different-things-called-gpu-passthrough">Two different things called &ldquo;GPU passthrough&rdquo;</h2>
<ul>
<li><strong>Full PCIe passthrough to a VM.</strong> 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&rsquo;s own drivers.</li>
<li><strong>Device passthrough to an LXC container.</strong> Instead of handing over the whole PCIe device, you expose specific device nodes (<code>/dev/dri/renderD128</code> for Intel/AMD hardware encode, <code>/dev/nvidia*</code> 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.</li>
</ul>
<p>These aren&rsquo;t two settings on the same feature, they&rsquo;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.</p>
<h2 id="when-each-one-is-actually-the-right-call">When each one is actually the right call</h2>
<ul>
<li><strong>Use LXC device passthrough for transcoding and inference workloads:</strong> Plex, Jellyfin, Frigate&rsquo;s object detection, Immich&rsquo;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.</li>
<li><strong>Use full VM passthrough when a guest genuinely needs the whole card:</strong> a Windows gaming VM, a workload that needs the card&rsquo;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&rsquo;re signing up for hotplug scripts or a reboot between mode switches, plan for that up front rather than discovering it after the fact.</li>
</ul>
<p>If you&rsquo;re not sure which one you need, ask whether you actually need the host to lose access to the card while it&rsquo;s running. If the answer is no, you almost certainly want LXC passthrough, it&rsquo;s less setup and doesn&rsquo;t sacrifice a GPU that could otherwise be shared.</p>
<h2 id="what-both-paths-need-first-iommu">What both paths need first: IOMMU</h2>
<p>Whether you&rsquo;re doing full VM passthrough or LXC device passthrough, IOMMU (Intel VT-d or AMD-Vi) needs to be enabled, since it&rsquo;s what lets the hypervisor safely map a device&rsquo;s memory access for a guest, or in the LXC case, what makes device isolation and cgroup-based access control possible at all.</p>
<ol>
<li>Enable VT-d (Intel) or AMD-Vi (AMD) in the motherboard&rsquo;s BIOS/UEFI. This is off by default on plenty of consumer boards.</li>
<li>Add <code>intel_iommu=on</code> or <code>amd_iommu=on</code> to the kernel command line. On a standard Proxmox install with GRUB, that&rsquo;s <code>/etc/default/grub</code>&rsquo;s <code>GRUB_CMDLINE_LINUX_DEFAULT</code> line, followed by <code>update-grub</code>. On a ZFS-root install using systemd-boot instead, it&rsquo;s <code>/etc/kernel/cmdline</code> followed by <code>proxmox-boot-tool refresh</code>, easy to get wrong if you assume every Proxmox box uses GRUB.</li>
<li>Reboot, then confirm it actually took with <code>dmesg | grep -e DMAR -e IOMMU</code>. You want to see IOMMU being enabled, not a message saying it&rsquo;s not supported.</li>
</ol>
<h2 id="full-vm-passthrough-the-extra-steps-and-the-gotchas">Full VM passthrough: the extra steps and the gotchas</h2>
<p>Past IOMMU, VM passthrough needs the GPU bound to the generic <code>vfio-pci</code> driver instead of whatever driver Proxmox would normally load for it, so the host never touches the card and it&rsquo;s free to hand to the VM cleanly.</p>
<ul>
<li><strong>Check IOMMU groups</strong> with a script that walks <code>/sys/kernel/iommu_groups/</code>. Every device sharing a group with your GPU (often its HDMI audio function, sometimes unrelated onboard devices depending on your board&rsquo;s PCIe topology) has to be passed through together or isolated from the group, you can&rsquo;t split a group&rsquo;s devices between host and guest. Poor IOMMU grouping is one of the most common reasons passthrough fails on consumer motherboards, and there&rsquo;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&rsquo;t be your first move.</li>
<li><strong>Bind the GPU to vfio-pci</strong> at boot, before any other driver claims it, by adding its PCI vendor:device ID to <code>/etc/modprobe.d/vfio.conf</code> (<code>options vfio-pci ids=xxxx:yyyy,xxxx:zzzz</code> for the GPU and its audio function) and blacklisting the normal driver (<code>nouveau</code>, <code>amdgpu</code>, or the Nvidia driver) so it never grabs the card first.</li>
<li><strong>Add the PCI device to the VM config</strong>, either through the web UI&rsquo;s Hardware tab (Add &gt; PCI Device) or directly in the VM&rsquo;s config file, with <code>pcie=1</code> set if your board and the VM&rsquo;s machine type support PCIe passthrough properly rather than falling back to legacy PCI.</li>
<li><strong>Consumer NVIDIA cards have a known reset bug.</strong> Many GeForce cards don&rsquo;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 <code>vendor-reset</code> kernel 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.</li>
<li><strong>Single-GPU passthrough</strong> (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.</li>
</ul>
<h2 id="lxc-device-passthrough-the-simpler-path">LXC device passthrough: the simpler path</h2>
<p>For sharing a GPU across containers instead of dedicating it to one VM, you&rsquo;re not touching IOMMU groups or vfio-pci at all, you&rsquo;re just exposing device nodes into the container.</p>
<ul>
<li><strong>Intel/AMD (VAAPI, via <code>/dev/dri</code>):</strong> on the Proxmox host, confirm <code>/dev/dri/renderD128</code> (and <code>card0</code>) exist and that the right host driver (<code>i915</code> for Intel, <code>amdgpu</code> for AMD) is loaded. In the container&rsquo;s config (<code>/etc/pve/lxc/&lt;vmid&gt;.conf</code>), add the device passthrough lines mapping those device nodes in, and make sure the container&rsquo;s user has the matching group ID for <code>video</code>/<code>render</code> so it actually has permission to use them, not just see them.</li>
<li><strong>NVIDIA (via <code>/dev/nvidia*</code>):</strong> this needs the NVIDIA driver installed on the Proxmox host itself, plus matching device nodes (<code>/dev/nvidia0</code>, <code>/dev/nvidiactl</code>, <code>/dev/nvidia-uvm</code>, 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.</li>
<li><strong>Unprivileged containers add one more wrinkle:</strong> 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 <code>lxc.idmap</code> entries, or explicitly allow the relevant device major/minor numbers via <code>lxc.cgroup2.devices.allow</code>. This is the single most common &ldquo;I passed the device in and it still says permission denied&rdquo; issue with unprivileged LXCs.</li>
<li><strong>Multiple containers, one GPU:</strong> unlike VM passthrough, several containers can point at the same <code>/dev/dri/renderD128</code> at once, that&rsquo;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 &ldquo;owns&rdquo; the GPU.</li>
</ul>
<h2 id="bottom-line">Bottom line</h2>
<p>Don&rsquo;t default to full PCIe passthrough because it&rsquo;s the more commonly documented path online, it&rsquo;s the wrong tool for most homelab GPU use cases. If you&rsquo;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&rsquo;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.</p>
]]></content:encoded></item></channel></rss>