WolfUSB
WolfUSB lets you share USB devices connected to any server across your network. Access scanners, security dongles, cameras, printers, and any other USB device from Docker containers, LXC containers, and virtual machines — even on different physical hosts.
Key Features
- USB over TCP/IP — share any USB device from one machine to any other on the network
- Encrypted authentication — HMAC-SHA256 pre-shared key authentication protects your devices
- Custom binary protocol — length-prefixed bincode frames over TCP, optimised for low latency
- Full USB support — control, bulk, and interrupt transfer types
- Session management — exclusive device access with automatic cleanup on disconnect
- Cross-platform — Linux (x86_64, aarch64, armv7), macOS (Intel + Apple Silicon), Windows
- Single binary — server and client in one ~3 MB binary with no external dependencies
- WolfStack integration — assign USB devices to Docker, LXC, and VMs from the dashboard
How It Works
WolfUSB uses a client-server architecture where the server runs on the machine with the physical USB device connected, and clients connect over TCP to use the device remotely.
- Server shares devices — the WolfUSB server runs on any machine with USB devices and exposes them over TCP port 3240
- Client connects — any machine on the network can list available devices and attach to them
- Exclusive access — when a client attaches to a device, it gets exclusive access with a session ID. Kernel drivers are detached on the server side.
- USB transfers — the client performs control, bulk, and interrupt transfers over the network as if the device were local
- Clean disconnect — when done, the client detaches and kernel drivers are reattached automatically
WolfStack Integration
WolfUSB is integrated directly into the WolfStack dashboard under each node’s WolfUSB menu item.
Installation
Click Install WolfUSB on the WolfUSB page to automatically download and install the binary from GitHub. The installer detects your platform and architecture automatically.
Configuration
Configure the WolfUSB server directly from the dashboard:
- Bind Address — which network interface to listen on (default: 0.0.0.0 for all interfaces)
- Port — TCP port for the WolfUSB server (default: 3240)
- Auth Key — optional pre-shared key for HMAC-SHA256 authentication
- Enabled — toggle to start/stop the systemd service
Configuration is saved to /etc/wolfstack/wolfusb.json and the systemd service is managed automatically.
Device Discovery
The WolfUSB page shows all USB devices connected to the node with their vendor:product IDs, device names, and current assignment status.
Assigning to Containers & VMs
Each USB device has a target dropdown that lists all Docker containers, LXC containers, and VMs on the node. Select a target and click Assign to pass the device through:
| Target | Method | Notes |
|---|---|---|
| Docker | --device /dev/bus/usb/XXX/YYY |
Container must be recreated with the device flag. WolfStack shows the exact docker-compose config to add. |
| LXC | cgroup + bind mount | WolfStack automatically adds the lxc.cgroup2.devices.allow and lxc.mount.entry lines to the container config. Restart required. |
| VM | QEMU USB passthrough | Integrates with WolfStack’s existing USB passthrough system for native QEMU, Proxmox, and libvirt VMs. |
Protocol
WolfUSB uses a custom binary protocol over TCP, designed for low latency and reliability:
- Frame format — 4-byte big-endian payload length + bincode-encoded payload (max 16 MiB per frame)
- Serialisation — bincode v2 for compact, fast encoding/decoding
- Authentication — client sends a random 32-byte nonce, server responds with HMAC-SHA256(nonce + “wolfusb-server”, key)
- Keepalive — Ping/Pong messages to detect stale connections
Message Types
| Message | Direction | Description |
|---|---|---|
| Hello / HelloResponse | Client → Server | Handshake with HMAC-SHA256 authentication |
| ListDevices / DeviceList | Client → Server | Enumerate available USB devices |
| Attach / AttachResult | Client → Server | Claim exclusive device access (returns session ID) |
| Detach / DetachResult | Client → Server | Release device, reattach kernel drivers |
| ControlTransfer | Client → Server | USB control transfer (setup packets) |
| BulkTransfer | Client → Server | USB bulk transfer (data endpoints) |
| InterruptTransfer | Client → Server | USB interrupt transfer (HID devices, etc.) |
| Ping / Pong | Both | Connection keepalive |
CLI Usage
WolfUSB can also be used standalone from the command line:
Server
# Start the server (all interfaces, default port)
wolfusb server --bind 0.0.0.0 --port 3240
# With authentication
wolfusb server --bind 0.0.0.0 --port 3240 --key "my-secret-key"
Client
# List available devices
wolfusb list --server 192.168.1.100:3240
# Attach to a device (returns session_id)
wolfusb attach --server 192.168.1.100:3240 --bus 1 --addr 2
# Perform a control transfer
wolfusb control --server 192.168.1.100:3240 --session-id 1 \
--bus 1 --addr 2 --request-type 0x80 --request 0x06 \
--value 0x0100 --index 0x00 --length 18
# Detach when done
wolfusb detach --server 192.168.1.100:3240 --bus 1 --addr 2 --session-id 1
Installation
WolfUSB can be installed via WolfStack (recommended) or standalone:
Via WolfStack
Navigate to any node → WolfUSB → click Install WolfUSB.
Standalone
# Quick install (detects platform automatically)
curl -fsSL https://raw.githubusercontent.com/wolfsoftwaresystemsltd/wolfusb/main/setup.sh | bash
# Install as systemd service
sudo ./install-service.sh --bind 0.0.0.0 --port 3240 --key "secret"
From Source
# Requires Rust 1.85+ and libusb headers
sudo apt install libusb-1.0-0-dev # Debian/Ubuntu
cargo build --release
sudo cp target/release/wolfusb /usr/local/bin/
Supported Platforms
| Platform | Architecture | Notes |
|---|---|---|
| Linux | x86_64, aarch64, armv7 | Full support including kernel driver management |
| macOS | Intel, Apple Silicon | Works without extra permissions for most devices |
| Windows | x86_64 | Requires WinUSB driver (use Zadig) |
Use Cases
- Security dongles — share hardware security keys, licence dongles, or YubiKeys with VMs or containers
- Scanners & printers — access document scanners or label printers from containerised applications
- Cameras & capture cards — pass webcams or video capture devices to media processing containers
- Serial devices — access USB-serial adapters for IoT, industrial, or home automation from any node
- Development — share USB development boards (Arduino, ESP32, etc.) with build containers
- Backup devices — mount external USB drives in backup containers across the network
Security
- Authentication — optional HMAC-SHA256 pre-shared key prevents unauthorised access
- Exclusive access — only one client can attach to a device at a time
- Kernel driver isolation — kernel drivers are detached when a client attaches, preventing host-side interference
- Automatic cleanup — sessions are cleaned up on disconnect, reattaching kernel drivers
- No root required — with a udev rule, the server can run as a non-root user
Configuration Files
| File | Description |
|---|---|
/etc/wolfstack/wolfusb.json | WolfStack integration config (bind, port, auth key, device assignments) |
/etc/wolfusb/wolfusb.env | Systemd service environment variables |
/etc/systemd/system/wolfusb.service | Systemd service unit file |
Recovery: Diagnose & Re-attach v18.1.0
When a VM migrates between cluster nodes, a USB passthrough can end up stale — the old node still claims the device locally, the new node's usbip mount times out silently, and QEMU boots the VM with -device usb-host against a host bus that doesn't actually have the device. Symptom: the QEMU log says "passthrough" but lsusb inside the guest shows nothing.
Two buttons on the WolfUSB page per assignment:
- 🔍 Diagnose — read-only walk of the full chain: source node reachable on
:3240→ wolfusb-server exports the device → kernel modules loaded on both sides → mount unit installed + active → device present on target'slsusb. Renders a top-to-bottom checklist with green/red per step so you see exactly where the chain broke — no more tailingjournalctlacross three nodes. - 🔄 Re-attach — force-reruns the recovery. Stops any stale mount unit, calls the source node's
prepare-for-exportto ensure it'susbip binded, rerunsattach_and_passthrough, and shows per-step results in a modal. Idempotent — safe to click on a healthy assignment.
Pre-flight in start_vm
Before QEMU spawns, WolfStack now verifies every entry in the VM's USB passthrough list is actually on the host's USB bus (via lsusb). If any device is missing, the VM start is refused with a clear error pointing the operator at the Re-attach button. Better than booting a VM silently missing its hardware.