Pure-Go reimplementation of USB/IP userspace for Linux. Ships three artefacts from a single code base:
pkg/usbip— embeddable library for importers (client) and exporters (server).usbip-go— operator/client CLI (cobra + jsonlines).usbipd-go— production daemon with socket activation, Prometheus metrics, status UDS, and graceful drain.
No cgo, no dependencies on usbip-utils. Upstream wire compatibility
is pinned by conformance tests against real captures.
The upstream reference is the C client/daemon shipped under
linux/tools/usb/usbip (built and packaged as usbip /
usbipd / libusbip). usbip-go re-uses the same wire format and
the same kernel sysfs interface, so it interoperates with upstream
peers in either direction. What differs is the userspace surface
around the protocol:
| Capability | upstream usbip-utils |
usbip-go |
|---|---|---|
Wire-compatible with usbip-utils peers |
✅ | ✅ |
Uses kernel vhci_hcd / usbip_host / usbip_vudc |
✅ | ✅ |
| Pure Go, no cgo | ❌ | ✅ |
| Cross-compile to all Linux arches in one command | ❌ | ✅ |
Embeddable as a library (pkg/usbip) |
❌ | ✅ |
| Auto-reconnect on detach (exponential backoff + jitter) | ❌ | ✅ |
Concurrent-attach deduplication (per (remote, busid)) |
❌ | ✅ |
Per-attach MaxAttempts / OnReconnect callback |
❌ | ✅ |
Graceful drain + bounded ShutdownTimeout |
❌ | ✅ |
Structured logging (slog JSON / text) |
❌ | ✅ |
| Prometheus metrics on importer + exporter | ❌ | ✅ |
| Event subscription API (port / session / reconnect) | ❌ | ✅ |
systemd socket activation (usbipd-go.socket) |
❌ | ✅ |
| Status UDS for live introspection | ❌ | ✅ |
| JSON output mode with versioned schema | ❌ | ✅ |
| Allow-list CIDR / rate-limit / session caps | ❌ | ✅ |
TCP_NODELAY on dialed connections |
✅ | ✅ |
| Configurable connect timeout | ❌ | ✅ |
| Tunable TCP keepalive (idle / interval / probes) | ❌ | ✅ |
Tunable SO_SNDBUF / SO_RCVBUF for WAN bandwidth-delay |
❌ | ✅ |
Static read / write deadlines per Importer / Exporter |
❌ | ✅ |
| Tolerance for high-latency / lossy links (50–800 ms RTT) | ❌ | ✅ |
Reproducible builds (-trimpath, no cgo) |
❌ | ✅ |
Static analysis + vuln scanning (CodeQL, golangci-lint, govulncheck, Trivy) |
❌ | ✅ |
| Conformance tests against real wire captures | ❌ | ✅ |
| Fuzz targets on the wire codec | ❌ | ✅ |
| Mutation testing on protocol-critical packages | ❌ | ✅ |
| Coverage gate (90%+ for pure-logic packages) | ❌ | ✅ |
SBOM + cosign keyless signed releases |
❌ | ✅ |
| SLSA Build Provenance on every release | ❌ | ✅ |
| OpenSSF Scorecard / Best Practices | ❌ | ✅ |
| TLS or authentication on the wire (out of scope — tunnel via WG/SSH/Tailscale) | ❌ | ❌ |
The underlying invariant — wire-compatible with upstream — does not change as new features land.
USB/IP is a plaintext, unauthenticated protocol.
Anyone who can TCP-connect to port 3240 can list exported devices and attach them. usbip-go does not wrap the wire in TLS — TLS is out of scope (see
docs/security.md). Deploy only over already-trusted networks: private LAN, Wireguard, Tailscale, or SSH tunnels. Never expose port 3240 on the public internet.The daemon ships defence-in-depth flags —
--allow-cidr,--max-sessions,--accept-rate-limit— but these are enforcement seams, not authentication. Readdocs/security.mdbefore deploying.
Prebuilt binaries, .deb, and .rpm packages are published to
GitHub Releases.
VERSION=1.0.0 # replace with the tag you want; see the Releases page
curl -LO "https://github.com/abilisoft/usbip-go/releases/download/v${VERSION}/usbip-go_${VERSION}_linux_amd64.tar.gz"
tar xzf "usbip-go_${VERSION}_linux_amd64.tar.gz"
sudo install -m 0755 usbip-go usbipd-go /usr/bin/
GoReleaser archive names follow
usbip-go_<version>_<os>_<arch>.tar.gz (see .goreleaser.yml). Pick
the architecture that matches your host (amd64, arm64, or
armv7).
Every release ships a SLSA Build Provenance bundle
(multiple.intoto.jsonl) and a cosign keyless signature on the
checksums file (Sigstore bundle format). Verify both before
installing — name_template in .goreleaser.yml produces the
checksum filename as usbip-go_<version>_checksums.txt, so the
matching cosign bundle is usbip-go_<version>_checksums.txt.sigstore.json:
VERSION=1.0.0
ARCHIVE=usbip-go_${VERSION}_linux_amd64.tar.gz
CHECKSUMS=usbip-go_${VERSION}_checksums.txt
BUNDLE=${CHECKSUMS}.sigstore.json
BASE=https://github.com/abilisoft/usbip-go/releases/download/v${VERSION}
curl -LO "${BASE}/${ARCHIVE}"
curl -LO "${BASE}/${CHECKSUMS}"
curl -LO "${BASE}/${BUNDLE}"
curl -LO "${BASE}/multiple.intoto.jsonl"
# 1. Provenance: prove the artifact came out of the abilisoft/usbip-go
# GitHub Actions release workflow at the matching tag.
slsa-verifier verify-artifact "${ARCHIVE}" \
--provenance-path multiple.intoto.jsonl \
--source-uri github.com/abilisoft/usbip-go \
--source-tag "v${VERSION}"
# 2. Checksum signature: prove the checksums file was signed by a
# Sigstore keyless cert whose OIDC subject is the
# .github/workflows/release.yml workflow at the same v*.*.* tag —
# matches the exact workflow path so a different workflow in this
# repo cannot satisfy the check. The Sigstore bundle (--bundle)
# carries the leaf certificate, the signature, and the rekor
# inclusion proof in a single file.
cosign verify-blob \
--bundle "${BUNDLE}" \
--certificate-identity-regexp '^https://github\.com/abilisoft/usbip-go/\.github/workflows/release\.yml@refs/tags/v[0-9]+\.[0-9]+\.[0-9]+$' \
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
"${CHECKSUMS}"
# 3. Per-binary integrity: confirm the archive's sha256 is in the
# checksums file.
sha256sum -c --ignore-missing "${CHECKSUMS}"
Install slsa-verifier
and cosign
once; both are statically linked single binaries.
The release archive and packages both include systemd units. Drop them in place and enable the socket unit:
sudo install -Dm 0644 contrib/systemd/usbipd-go.service /etc/systemd/system/usbipd-go.service
sudo install -Dm 0644 contrib/systemd/usbipd-go.socket /etc/systemd/system/usbipd-go.socket
sudo systemctl daemon-reload
sudo systemctl enable --now usbipd-go.socket
Socket activation means the daemon starts on the first inbound
connection. See docs/ops.md for the full systemd
hardening recipe, metrics wiring, and drain procedure.
go install github.com/abilisoft/usbip-go/cmd/usbip-go@latest
go install github.com/abilisoft/usbip-go/cmd/usbipd-go@latest
Requires Go 1.26 or newer.
Every host running usbipd-go (exporter) or the usbip-go client needs
the relevant kernel modules:
sudo modprobe usbip_core vhci-hcd usbip-host
echo -e 'usbip_core\nvhci_hcd\nusbip_host' \
| sudo tee /etc/modules-load.d/usbip-go.conf
package main
import (
"context"
"log/slog"
"github.com/abilisoft/usbip-go/pkg/domain"
"github.com/abilisoft/usbip-go/pkg/usbip"
)
func main() {
imp, _ := usbip.NewImporter(usbip.WithImporterLogger(slog.Default()))
defer imp.Close()
remote, _ := domain.ParseRemote("10.0.0.5:3240")
busid, _ := domain.ParseBusID("1-1.2")
port, _ := imp.Attach(context.Background(), remote, busid, usbip.AttachOptions{
AutoReconnect: true,
})
_ = port // detach later with imp.Detach(ctx, port.ID)
}More patterns under examples/ — client, server,
events, reconnect, metrics.
sudo usbip-go attach 10.0.0.5 1-1.2
sudo usbip-go port
sudo usbip-go detach 0
sudo systemctl enable --now usbipd-go.socket
sudo usbip-go bind 1-1.2 # export a local device
sudo systemctl status usbipd-go
Metrics, drain, and readiness endpoints are in
docs/ops.md.
The dev toolchain is hermetic: the only host-side prerequisites are
Docker and Task. Go, linters,
formatters, and every release tool (goreleaser, syft, cosign, nfpm,
git-cliff) are pinned in flake.nix and delivered through a Nix
container — task setup seeds the store once, then task test,
task lint, and friends reuse it.
See CONTRIBUTING.md for the full
onboarding flow, the hermetic-cache layout under ./build/, and
the microVM path that runs integration tests against a real Linux
kernel without requiring the USBIP modules on your host.
docs/architecture.md— layering and package responsibilities.docs/protocol.md— USB/IP wire byte layouts.docs/security.md— threat model, privilege, allow-CIDR,setcap.docs/ops.md— daemon install, systemd, status UDS, metrics, drain.docs/troubleshooting.md— decision tree for attach failures.docs/wire-trace.md— pcap recipe for bug reports.docs/json-schema.md— v1 JSON schema contract.CONTRIBUTING.md— dev setup, TDD discipline, commit conventions.
v1 surface is under active development. APIs under pkg/usbip and
pkg/domain are guarded by apidiff baselines and require a
BREAKING: commit for any incompatible change — see
CONTRIBUTING.md.
Apache-2.0. See LICENSE.