How to Passthrough USB to Proxmox VM (September 2026)?

I have run into this exact problem more times than I can count. A Zigbee stick works fine for weeks, then a host reboot silently swaps it with a second stick and Home Assistant stops seeing the right device. This guide is the workflow I now use to make Proxmox USB passthrough survive every reboot.

You will learn what Proxmox USB passthrough actually does, why port-based mapping breaks after restarts, and how to lock the assignment down with vendor and product IDs plus a udev rule. Both KVM/QEMU virtual machines and LXC containers are covered.

Quick Answer

To make a Proxmox USB passthrough survive every reboot:

  1. On the host, run lsusb and note the idVendor:idProduct (for example 1a86:7523).

  2. Enable USB hotplug on the VM in Options > USB Hotplug.

  3. Attach by ID: qm set 101 -usb0 host=1a86:7523 (replace 101 with your VM ID).

  4. For LXC, add lxc.cgroup2.devices.allow: c 188:* rwm plus a lxc.mount.entry for the device path.

  5. Verify with lsusb inside the guest, then reboot the host to confirm the mapping sticks.

What Is USB Passthrough in Proxmox and Why Does It Matter

USB passthrough in Proxmox is the process of handing a physical USB device connected to the Proxmox host directly to a guest, whether that guest is a full QEMU/KVM virtual machine or a lightweight LXC container. The guest sees the device as if it were physically plugged into its own virtual hardware.

There are good reasons to do this. Some devices simply do not have network alternatives:

  • Zigbee coordinators and Z-Wave sticks used by Home Assistant.

  • Fingerprint readers, YubiKeys, and hardware security modules.

  • Document scanners running SANE inside a Paperless-ngx VM.

  • USB-to-serial adapters for industrial or hobby hardware.

  • Dongles that license software and cannot share a port with the host OS.

For each of these, Proxmox USB passthrough is the difference between a working homelab and a constant stream of “device offline” errors. The trick is making the assignment permanent, because the wrong passthrough method silently breaks the moment the host reboots.

Why Port-Based USB Mapping Breaks After a Reboot?

Proxmox offers two ways to attach a USB device to a VM: by port location (for example the second port on bus 3) or by vendor and product ID. Port-based mapping is the one almost every beginner uses first, and it is the one that quietly breaks on reboot.

Here is why. Linux assigns USB devices a bus number and a device address in the order it enumerates them during boot. That order depends on how fast each device responds, what the host controller reports, and which kernel module loads first. When the system restarts, almost nothing guarantees the same order. Your Zigbee stick that was bus 003 device 004 yesterday may show up as bus 003 device 002 tomorrow, and your second stick is now sitting where the first one was. The VM configuration that pointed at the old bus and port is now pointing at a different physical device, or at nothing at all.

Forum threads confirm this. One user reported: “I pass two USB devices through my Proxmox setup to HA and frequently after system reboots, they will swap places, which breaks my integrations.” Another wrote: “Every time the Proxmox host restarted, my Yubico HSM would get a new bus and device ID.”

Mapping by vendor and product ID avoids the problem. The ID is burned into the silicon of every USB device and does not change, so 1a86:7523 (a common CH340 serial chip) always means the same physical hardware wherever the kernel happens to enumerate it. Combined with a udev rule that uses a unique serial number, you get a passthrough that survives reboots, kernel updates, and even swapping a cable between identical-looking ports.

Identify the USB Device with lsusb (Vendor:Product ID)

Before you can pass anything through, the host has to tell you what it sees. The standard tool is lsusb, which is provided by the usbutils package in Debian.

Run it on the Proxmox host shell (or via SSH):

lsusb

The output lists every USB device, for example:

Bus 002 Device 003: ID 1a86:7523 QinHeng Electronics CH340 serial converter
Bus 003 Device 002: ID 0658:0200 Silicon Labs Watchdog Demo (Z-Wave)

You want the four-hex-digit vendor ID followed by a colon and the four-hex-digit product ID. In the line above, the device to capture is 1a86:7523. If you already see device names like ttyACM0 or ttyUSB0 in your kernel logs, you are on the right track.

For an even more stable identifier, look at the by-id path. Plug and unplug the device once and watch which path stays:

ls -l /dev/serial/by-id/

You will see something like /dev/serial/by-id/usb-Silicon_Labs_Z-Wave_Stick_9000-if00-port0. That string is built from the device’s own descriptors and will not change between reboots.

If you have two identical sticks (a common Zigbee issue), you need one more piece: the serial number. Pull it with:

udevadm info -a -n /dev/ttyUSB0 | grep -E "ATTRS{serial}|ATTRS{idVendor}|ATTRS{idProduct}"

Write down the 8- or 12-character serial. You will use it in the udev rule later so the kernel can tell two identical-looking sticks apart.

Passthrough to a VM with the Vendor:Product ID (qm set)

Now attach the device to your VM by ID rather than by port. This is the core of making Proxmox USB passthrough survive reboots, because the assignment follows the hardware identity instead of its boot-time address.

Step 1: Enable USB hotplug. In the Proxmox web UI, open the VM, go to Options, and set USB Hotplug to Enabled. Without this, you cannot attach or detach USB while the VM is running.

Step 2: Add the USB device by ID. Click Hardware > Add > USB Device. Choose Use USB Vendor/Device ID and enter the values you captured from lsusb. Save. That entry survives every reboot because it refers to the chip, not the bus.

Step 3: Do the same on the command line. The Proxmox wiki and forum users both recommend the same syntax, and I prefer it because it is reproducible across hosts:

qm set 101 -usb0 host=1a86:7523

Replace 101 with your VM ID and the IDs with your real values. To pass the device as USB 3.0 (important for storage and fast serial adapters), add the XHCI argument:

qm set 101 -usb0 host=1a86:7523,usb3=1

When usb3=1 is set, Proxmox uses an XHCI controller instead of the default EHCI, which avoids the “USB 3.0 device on a USB 2.0 bus” slowdown and helps with isochronous workloads like webcams.

Step 4: Start or restart the VM. The USB device should now appear inside the guest. Confirm with:

lsusb

You should see the same idVendor:idProduct in the guest that you saw on the host. If it shows up, the ID-based passthrough is working. Reboot the Proxmox host to confirm it sticks.

Make the Mapping Survive Reboots with udev Rules

Mapping by vendor:product is good, but if you have two devices that share the same IDs (two identical Zigbee sticks is the classic example) or if you want a friendly symlink like /dev/zigbee for an application to bind to, you need a udev rule.

Create a new file in /etc/udev/rules.d/. Use a high number prefix so it runs late and wins against default rules:

nano /etc/udev/rules.d/99-usb-zigbee.rules

For a single, uniquely identifiable device, this template works:

SUBSYSTEM=="tty", ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="7523", SYMLINK+="zigbee"

For two identical sticks, use the serial number as a tiebreaker. Pull the serial with the udevadm info command in the previous section, then write one line per stick:

SUBSYSTEM=="tty", ATTRS{idVendor}=="0658", ATTRS{idProduct}=="0200", ATTRS{serial}=="A1B2C3D4", SYMLINK+="zwave_kitchen"
SUBSYSTEM=="tty", ATTRS{idVendor}=="0658", ATTRS{idProduct}=="0200", ATTRS{serial}=="E5F6G7H8", SYMLINK+="zwave_garage"

Reload and trigger the rules without rebooting:

udevadm control --reload-rules
udevadm trigger

Verify the symlink appears at /dev/zigbee or /dev/zwave_kitchen. Because udev matches against attributes baked into the hardware, the symlink follows the same physical stick no matter which port it is plugged into or what bus address the kernel happens to assign this boot.

Pass that stable path into your VM or LXC container instead of a raw /dev/ttyUSB0. The combination is what truly makes Proxmox USB passthrough survive reboots.

Passthrough to an LXC Container (Unprivileged and Privileged)

USB passthrough to an LXC container is a different beast. There is no qm set for LXC, and the web UI under Container > Resources > Add > USB Device is only a thin wrapper that writes two lines to the container’s config file at /etc/pve/lxc/<CTID>.conf. Understanding both lines is what makes the assignment permanent.

The first line is a cgroup2 device allow rule. The 188 is the major number for USB serial devices (most ttyUSB and ttyACM devices). The wildcard in the minor slot means “any sub-device on this controller”:

lxc.cgroup2.devices.allow: c 188:* rwm

If you are passing a different device class (for example an input device or a network adapter), look up its major number with grep on the host, then replace 188 accordingly.

The second line is the bind mount that exposes the actual device node into the container’s /dev tree:

lxc.mount.entry: /dev/zigbee dev/zigbee none bind,optional,create=file

I always include optional so the container still starts if the stick is unplugged at boot, and create=file for character devices. Use create=dir if you are mounting a whole subdirectory of devices.

For unprivileged containers, you must also map the device into the container’s user namespace. Add this just below the cgroup line:

lxc.idmap: u 0 100000 65536
lxc.idmap: g 0 100000 65536

And on the host, ensure the container’s rootfs has a .ugly_uids / .ugly_gids mapping that includes the device’s group. In practice, the simplest fix is to pass the device as privileged the first time you debug, then tighten the security once you know it works. Most forum-reported “permission denied” problems in LXC containers come from skipping this step.

After saving the file, restart the container. From inside it, run:

ls -l /dev/zigbee

If the symlink is there and readable by your application user, you have a working Proxmox USB passthrough to LXC. Power down and reboot the host to confirm the mapping is permanent.

Testing and Verifying Your USB Passthrough

Configuration that works on the first boot can still fail after a reboot, so verification is not optional. I run three quick checks after every change.

From inside the VM or container, confirm the kernel sees the device:

lsusb
dmesg | tail -20

The lsusb line proves the guest enumerated it; the dmesg tail proves the right driver loaded and no errors occurred during attach. If the device is not there, the passthrough did not happen.

Next, do a functional test for your actual use case. For Zigbee and Z-Wave sticks, run the vendor’s discovery tool. For a scanner, run scanimage -L. For a YubiKey, run ykman list. If the application-level tool sees the device, the kernel-level passthrough worked and the user-space permissions are correct.

Finally, reboot the Proxmox host. This is the only way to actually prove that your Proxmox USB passthrough survives reboots. Watch the host console during boot to spot any “device busy” or “failed to attach” messages. Inside the VM after the host is back up, run lsusb again. The same device should still be there, in the same guest.

Troubleshooting Common USB Passthrough Issues

Even with a correct configuration, real hardware introduces real problems. These are the failure modes I have hit, and the fixes that have worked.

The device swaps with another stick after reboot. This is the headline problem for this guide. The fix is to stop relying on bus numbers. Switch to vendor:product mapping for the VM and add a udev rule with the serial number for anything that needs a friendly symlink. After the change, both reboots and physical port swaps are handled.

USB passthrough is slow, especially for storage. You are almost certainly using EHCI (USB 2.0) for a USB 3.0 device. Reattach with usb3=1 in the qm set command so Proxmox instantiates an XHCI controller. For RAID enclosures and SSDs, also check whether the host controller supports UASP and whether it is plugged into a USB 3.x port on the machine itself.

LXC container still cannot see the device. Three things to check, in order. First, does /dev/zigbee exist on the host after udevadm trigger? If not, fix the udev rule. Second, is the lxc.mount.entry syntax correct, with no quotes around the bind path? Third, for an unprivileged container, is the device accessible from the container’s mapped UID range? Switch to a privileged container temporarily to isolate which layer is failing.

Hotplug does nothing after I plug a device in. Confirm that USB Hotplug is enabled under VM Options. Without it, the QEMU monitor cannot run device_add while the VM is running, so the device only ever shows up at boot.

“Permission denied” when reading the device inside the guest. Most Proxmox installs run guests as root or with full cgroup access, so this is rare. If you see it, add your application user to the dialout group inside the guest, or chmod the device temporarily to confirm it is a permissions problem and not a passthrough problem.

Two identical USB sticks, only one survives reboot. Add the unique serial number from udevadm info to your udev rule as shown in the udev section above. Without a tiebreaker, the kernel picks deterministically but not predictably, so one stick always gets the symlink you wanted and the other does not.

FAQ

How do I pass through a USB device to a Proxmox VM that survives reboots?

Find the device’s vendor and product ID using lsusb on the host, then attach it by ID with qm set: qm set 101 -usb0 host=1a86:7523. With USB hotplug enabled in the VM’s Options, this assignment follows the hardware identity and survives every reboot.

How to permanently assign USB device to Proxmox VM?

Use the vendor:product ID rather than the USB port when adding the device. For multiple identical devices, add a udev rule in /etc/udev/rules.d/ that uses ATTRS{serial} to give each one a stable symlink, then pass that symlink into the VM.

How to use USB Vendor/Device ID in Proxmox instead of port?

In the web UI, click Hardware u0026gt; Add u0026gt; USB Device and choose Use USB Vendor/Device ID. On the command line, run qm set -usb0 host=:, optionally with usb3=1 for USB 3.0 speeds. The assignment is then tied to the hardware chip and will not break when the kernel renumbers buses on reboot.

How to keep Proxmox VM USB passthrough devices from swapping after reboot?

Port-based passthrough swaps because the kernel renumbers USB bus and device addresses at boot. Switch the passthrough to vendor:product ID mapping and, if you have identical hardware, layer a udev rule using the device’s serial number on top. Rebooting the host will then no longer change which physical device each VM sees.

How to pass through USB device to Proxmox LXC container?

Edit /etc/pve/lxc/.conf and add two lines: lxc.cgroup2.devices.allow: c 188:* rwm to permit the device class, and lxc.mount.entry: /dev/ dev/ none bind,optional,create=file to expose the node inside the container. Restart the container and verify with ls -l /dev/ from inside.

How to troubleshoot USB passthrough not working in Proxmox?

Start by checking lsusb on the host, then lsusb inside the guest. Confirm USB hotplug is enabled on the VM. For LXC, confirm both the cgroup2 allow rule and the lxc.mount.entry are present and that /dev/ exists on the host. Always reboot the host after a change to confirm the passthrough survives a restart.

Conclusion

Proxmox USB passthrough that survives reboots comes down to two ideas. First, attach devices by their vendor and product ID rather than by USB port, so the assignment follows the silicon instead of the kernel’s enumeration order. Second, when you need a friendly name or have two identical sticks, add a udev rule keyed on the device’s serial number, and pass that stable symlink into your VM or LXC container. Run the post-change reboot test, and your passthrough will quietly keep working through every kernel update and power event.

Leave a Comment