Fork me on GitHub

grpc-transports

Custom gRPC transports in pure Go — tunnel gRPC over a WireGuard overlay, an SSH connection, the host↔guest AF_VSOCK family, or a WebSocket (full bidi gRPC in the browser via js/wasm). Each transport hands you a net.Listener for grpc.Server and a matching client dialer.

net.Listener + client dialer inter-VM RPC WireGuard overlay SSH tunnel AF_VSOCK host↔guest WebSocket / wasm no sidecar proxy
zsh
$ go get github.com/grpc-transports/wireguard@latest
$ go get github.com/grpc-transports/ssh@latest
$ go get github.com/grpc-transports/vsock@latest
$ go get github.com/grpc-transports/websocket@latest
$ go get github.com/grpc-transports/webrtc@latest
$ go get github.com/grpc-transports/control@latest
One organisation, 6 repositories

Four transports, one shape. Each repo is a Go library that adapts standard google.golang.org/grpc to a different carrier: the server exposes a net.Listener you pass straight to grpc.Server.Serve, and the client provides a dialer that routes every channel through the same tunnel. No protobuf changes, no service-mesh sidecar — the transport is the only moving part you swap.

Pick the carrier that matches the trust model. wireguard targets inter-VM RPC across hosts and zones — a WireGuard overlay with a privilege-free userspace backend (wireguard-go + gVisor netstack) and a line-rate Linux kernel backend brought up through pure-Go netlink, no iproute2 in the rootfs. ssh targets human-driven clients, reusing Ed25519 host keys and SSH agent forwarding for authentication. vsock targets host↔guest RPC on one machine — the AF_VSOCK address family used by KVM/QEMU and Apple VZ, addressed by (context id, port) with no IP stack in the guest. websocket targets the browser — the client compiles to js/wasm and speaks full gRPC, including client-streaming and bidirectional streaming, over a WebSocket with no grpc-web sidecar.

Repositories

wireguard libwireguard

gRPC over a WireGuard overlay (net.Listener + grpc.DialOption)

userspace (wireguard-go + gVisor netstack) or kernel WireGuard

Tunnels gRPC between VMs over a WireGuard overlay regardless of host. Two backends ship side by side: a default userspace data path (wireguard-go + gVisor netstack, no privileges, any OS) and a Linux kernel-WireGuard backend (CAP_NET_ADMIN, line-rate) brought up via pure-Go netlink + wgctrl — no iproute2 or wireguard-tools in the rootfs.

ssh libssh

gRPC over an SSH tunnel (net.Listener + grpc.DialOption)

Ed25519 host keys + SSH agent forwarding

Wraps inbound SSH connections as gRPC-ready net.Conn for a standard grpc.Server, and dials gRPC channels over SSH from the client. Ed25519 host-key auto-generation and SSH agent forwarding for client auth. Suited to human-driven CLI clients where SSH's per-user key model fits.

vsock libvsock

gRPC over AF_VSOCK (net.Conn Dialer + net.Listener)

Linux virtio-vsock (KVM/QEMU or Apple VZ); amd64 · arm64 · riscv64 · loong64 · ppc64le · s390x

Host↔guest gRPC over the AF_VSOCK address family, addressed by (context id, port) with no IP stack in the guest. Listen returns a net.Listener whose connections report the peer CID; Dialer.DialContext matches grpc.WithContextDialer. Dependency-free pure Go (CGO=0); the syscall layer is seamed for 100% coverage, error branches included, on all six 64-bit arches. Linux-only, with a portable non-Linux stub so cross-platform callers still build.

websocket libwebsocket

gRPC over a WebSocket — the carrier that works inside the browser (net.Listener + grpc.DialOption)

native (coder/websocket) + js/wasm (syscall/js, zero deps); amd64 · arm64 · riscv64 · loong64 · ppc64le · s390x

Tunnels gRPC over a WebSocket, so the same client compiles and runs under GOOS=js/GOARCH=wasm and speaks full gRPC in the browser — including client-streaming and bidirectional streaming — with no Envoy/grpc-web sidecar. grpc-go runs its HTTP/2 framing in userspace over a net.Conn wrapping the WebSocket; the server is a plain grpc.Server behind net.Listener. Two client backends behind one signature (coder/websocket native, syscall/js on wasm). 100% native coverage plus a Node-driven js/wasm end-to-end test.

webrtc libwebrtc

gRPC between two peers that cannot reach each other (net.Listener + grpc.DialOption)

pion/webrtc; DTLS end to end, no relay and no sidecar

gRPC assumes one side can listen and the other can dial. Two peers behind household routers can do neither, and there is nothing in between that either controls. The server exposes a net.Listener over an RTCPeerConnection and the client a grpc.DialOption over a data channel; everything above stays ordinary gRPC. It deliberately does NOT do signalling: the two have to swap a session description first, and how — a mail, a chat window, a QR code, a rendezvous somebody already runs — is not a transport's business, and is usually already decided by whatever the peers are doing together.

control libcontrol

the admin plane, not a transport

unix socket (0600) or TCP with mandatory mTLS

Where a daemon's own control surface listens, and who is allowed to call it. A unix socket created 0600 so the filesystem answers the question, or TCP that REQUIRES client certificates -- there is no third option, because an admin plane reachable without proof is the one listener nobody meant to open. The caller's identity reaches the handler, so a method can refuse by name rather than by trust in the listener.

Each transport is a small Go library over standard google.golang.org/grpc — a net.Listener on the server side and a grpc.DialOption on the client side, so existing gRPC services move across without touching their protobuf or handlers.