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.

Built into WolfStack: WolfUSB is fully integrated into the WolfStack dashboard. Install it from the node’s WolfUSB page, configure the server, and assign USB devices to any container or VM with a dropdown picker.

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.

  1. Server shares devices — the WolfUSB server runs on any machine with USB devices and exposes them over TCP port 3240
  2. Client connects — any machine on the network can list available devices and attach to them
  3. 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.
  4. USB transfers — the client performs control, bulk, and interrupt transfers over the network as if the device were local
  5. Clean disconnect — when done, the client detaches and kernel drivers are reattached automatically
Automatic cleanup: If a client disconnects without explicitly detaching, the server automatically cleans up the session and reattaches kernel drivers.

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:

TargetMethodNotes
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

MessageDirectionDescription
Hello / HelloResponseClient → ServerHandshake with HMAC-SHA256 authentication
ListDevices / DeviceListClient → ServerEnumerate available USB devices
Attach / AttachResultClient → ServerClaim exclusive device access (returns session ID)
Detach / DetachResultClient → ServerRelease device, reattach kernel drivers
ControlTransferClient → ServerUSB control transfer (setup packets)
BulkTransferClient → ServerUSB bulk transfer (data endpoints)
InterruptTransferClient → ServerUSB interrupt transfer (HID devices, etc.)
Ping / PongBothConnection keepalive

CLI Usage

WolfUSB can also be used standalone from the command line:

Server

bash
# 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

bash
# 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

bash
# 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

bash
# 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

PlatformArchitectureNotes
Linuxx86_64, aarch64, armv7Full support including kernel driver management
macOSIntel, Apple SiliconWorks without extra permissions for most devices
Windowsx86_64Requires 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
Network security: WolfUSB traffic is not encrypted at the transport level. For production use across untrusted networks, run it over WolfNet or another VPN for end-to-end encryption.

Configuration Files

FileDescription
/etc/wolfstack/wolfusb.jsonWolfStack integration config (bind, port, auth key, device assignments)
/etc/wolfusb/wolfusb.envSystemd service environment variables
/etc/systemd/system/wolfusb.serviceSystemd 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's lsusb. Renders a top-to-bottom checklist with green/red per step so you see exactly where the chain broke — no more tailing journalctl across three nodes.
  • 🔄 Re-attach — force-reruns the recovery. Stops any stale mount unit, calls the source node's prepare-for-export to ensure it's usbip binded, reruns attach_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.

Esc