Proxmox PCI Resource Mapping Guide: Flexibly Assign GPU, USB, and NIC to VMs Using Labels on Proxmox 8

Virtualization tutorial - IT technology blog
Virtualization tutorial - IT technology blog

I ran into exactly this situation: a homelab running Proxmox with 12 VMs and containers, and one day I needed to migrate a Windows VM with a GPU attached from one node to another. The result? The VM wouldn’t boot because the PCI ID of the GPU on the new node was completely different. I had to manually edit the config, remove the old device, and re-add it — nearly 30 minutes wasted on something that should have been automatic.

That’s exactly why Proxmox 8 introduced PCI Resource Mapping as an official feature. Instead of hard-coding PCI addresses into the VM config, you define a logical label — something like gpu-rtx3060 — and the VM simply declares that label. The actual PCI ID? Proxmox handles that.

The Problem with Traditional PCI Passthrough

The old way of doing PCI passthrough on Proxmox was to directly edit the VM’s config file at /etc/pve/qemu-server/<vmid>.conf:

hostpci0: 0000:01:00.0,pcie=1,x-vga=1

The address 0000:01:00.0 is the physical PCI ID of the GPU on that host — hard-coded. Migrate the VM to another node where the same GPU model has a PCI ID of 0000:03:00.0, and the VM throws an error on startup because the device can’t be found.

Multi-node clusters make this even worse: each machine has different hardware, different slots, and PCI IDs follow no predictable pattern. One bad migration is enough to understand why this approach doesn’t scale.

The Core Concept: What Is Resource Mapping?

PCI Resource Mapping (or Device Mapping) is an abstraction layer that sits between the VM config and the physical hardware. You define a map entry with a descriptive name, such as gpu-rtx3060, then specify which physical device on each cluster node corresponds to that name.

Any VM that needs a GPU simply declares that it uses the gpu-rtx3060 mapping — Proxmox automatically resolves the correct PCI ID for whichever node the VM is running on. Migrate to another node? The VM config doesn’t change at all.

Proxmox 8 supports mapping for two device types:

  • PCI Device: GPU, NIC, sound card, storage controller, etc.
  • USB Device: USB dongles, USB-to-serial adapters, webcams, security keys, etc.

Hands-On: Configuring PCI Resource Mapping on Proxmox 8

Step 1: Identify the PCI ID of the Device on Each Node

SSH into each Proxmox node and list the PCI devices:

# List all PCI devices
lspci

# Filter for GPUs
lspci | grep -i vga
lspci | grep -i nvidia

# Filter for NICs
lspci | grep -i ethernet

# Show details for a specific device (replace ID as needed)
lspci -v -s 01:00.0

Example output on node-1:

01:00.0 VGA compatible controller: NVIDIA Corporation GA106 [GeForce RTX 3060 Lite Hash Rate]
01:00.1 Audio device: NVIDIA Corporation GA106 High Definition Audio Controller

On node-2, the same GPU model but in a different slot:

03:00.0 VGA compatible controller: NVIDIA Corporation GA106 [GeForce RTX 3060 Lite Hash Rate]
03:00.1 Audio device: NVIDIA Corporation GA106 High Definition Audio Controller

Step 2: Create a Resource Mapping via the Proxmox Web UI

Navigate to Datacenter → Resource Mappings in the left sidebar — this section appeared in Proxmox 8.0 and is not present in version 7.

Click Add in the PCI Devices tab:

  • Name: use a descriptive name, e.g. gpu-rtx3060 or nic-10g-mellanox
  • Node: select node-1
  • Device ID: enter 0000:01:00 (the function number can be omitted to map the entire device)
  • Sub-device: if the GPU includes an audio controller, add 0000:01:00.1 here

After adding node-1, click Add Node to add node-2 with its corresponding ID (0000:03:00). Proxmox will validate device compatibility — vendor ID and device ID must match across nodes.

Step 3: Create a USB Mapping (for USB Dongles or Serial Devices)

Switch to the USB Devices tab and click Add:

# Find USB devices on the host
lsusb

# Sample output:
# Bus 001 Device 003: ID 0403:6001 Future Technology Devices International, Ltd FT232 Serial
# Bus 002 Device 004: ID 1a2b:0001 Dongle Corp License Dongle

Enter the Vendor ID (0403) and Device ID (6001) in the UI. Proxmox matches USB devices by hardware ID rather than physical port — plugging into a different port after a reboot will still map to the correct device.

Step 4: Assign the Resource Mapping to a VM

Go to the target VM → HardwareAddPCI Device.

In the dropdown, select Mapped Device instead of Raw Device. You’ll see a list of the mappings you created. Select gpu-rtx3060 and configure the additional options:

  • PCIe: enable if the card supports it (most modern GPUs do)
  • Primary GPU: enable to pass through all display output
  • All Functions: enable to also pass through the GPU’s companion audio controller

Step 5: Configure via CLI (for Automation)

When managing many VMs or scripting the setup — especially when combined with Python-based Proxmox automation — use pvesh directly:

# Create a PCI mapping via the API
pvesh create /cluster/mapping/pci \
  --id gpu-rtx3060 \
  --description "NVIDIA RTX 3060" \
  --map node=node-1,path=0000:01:00,id=10de:2504 \
  --map node=node-2,path=0000:03:00,id=10de:2504

# List all existing mappings
pvesh get /cluster/mapping/pci

# Show details for a specific mapping
pvesh get /cluster/mapping/pci/gpu-rtx3060

After creating the mapping, assign it to a VM using qm:

# Assign the PCI mapping to VM ID 101
qm set 101 --hostpci0 mapping=gpu-rtx3060,pcie=1,x-vga=1

# Assign the USB mapping
qm set 101 --usb0 mapping=usb-dongle

# View the current VM config
qm config 101

The resulting VM config file is much cleaner — no hard-coded PCI IDs anywhere:

hostpci0: mapping=gpu-rtx3060,pcie=1,x-vga=1
usb0: mapping=usb-dongle

Step 6: Verify and Debug

Before starting the VM, confirm that IOMMU is enabled — this is a prerequisite for all PCI passthrough, not just Resource Mapping:

# Check IOMMU on the host
dmesg | grep -e DMAR -e IOMMU

# View IOMMU groups (all devices in a group must be passed through together)
for d in /sys/kernel/iommu_groups/*/devices/*; do
  n=${d#*/iommu_groups/*}; n=${n%%/*}
  printf 'IOMMU Group %s ' "$n"
  lspci -nns "${d##*/}"
done

If the GPU doesn’t have its own isolated IOMMU group (i.e., it shares a group with other devices), you’ll need to enable pcie_acs_override as a kernel parameter — a technique covered in detail in our guide to handling IOMMU groups with the ACS Override Patch.

Once the VM starts, the Proxmox log clearly shows which device was resolved:

# View the VM's log
journalctl -u qmeventd --since "5 minutes ago"

# Or view the task log directly
tail -f /var/log/pve/tasks/active

Practical Notes from the Homelab

I run a homelab with Proxmox VE managing 12 VMs and containers — a playground to test everything before pushing to production. After switching to Resource Mapping, here are a few things worth knowing:

  • Validation happens at mapping creation time: Proxmox checks vendor ID and device ID across nodes. If you map an RTX 3060 on node-1 but node-2 has a GTX 1080 (different ID), it warns you but still allows it. The VM will fail to start on node-2. Make sure the hardware is genuinely identical.
  • USB mapping is more stable than by-port: Previously I used usb0: host=2-1.3 to target a physical port — after a reboot or replug, the VM would lose the device. Mapping by vendor+device ID completely solves that problem.
  • NIC passthrough for pfSense/OPNsense: Creating a mapping for a 10G NIC and assigning it to a firewall VM means migrating between nodes no longer requires touching the VM’s network config.
  • GPU sharing with MIG: Resource Mapping doesn’t yet support NVIDIA MIG partitions through the UI. If you’re using A100/H100 with MIG, you’ll still need to configure that manually. For sharing an Intel integrated GPU across multiple VMs simultaneously, Intel GVT-g on Proxmox offers a complementary virtualization approach.

Conclusion

PCI Resource Mapping is something Proxmox cluster users have needed for a long time. The idea is elegant: a VM simply declares a label like gpu-rtx3060 without caring about the underlying PCI ID or which node it’s on. Proxmox handles the resolution.

Adding a new node to the cluster? Just map its devices to the existing labels and you’re done. Migrating a VM at 2 AM? No need to sit there editing configs half-asleep. This is exactly the kind of improvement you feel the very first time you use it.

If you’re still hard-coding PCI IDs on Proxmox 7, this is a compelling reason to consider upgrading to version 8. And if your setup involves an integrated GPU rather than a discrete card, the iGPU passthrough guide for Proxmox covers a complementary workflow worth knowing.

Share: