✦ Encrypted P2P Pipes · HTTP + raw TCP/TLS · No cloud proxy required

Share local services
with exact invites and Access Leases

Tubo attaches to a local service, mints a one-time exact invite, and grants authorized peers encrypted connectivity from anywhere — even behind NAT. Every remote open requires a short-lived, cryptographically verifiable Access Lease; access is revocable at any moment.

Latest release: v0.13.0 — architecture-driven reimplementation: exact sharing, durable bindings, lease renewal, revocation.

Get started See quickstart View on GitHub
$ curl -fsSL https://www.tubo.click/install.sh | sh
Architecture

How Tubo works

A minimal set of roles connect over an encrypted libp2p swarm. No central server sees your traffic — streams are end-to-end encrypted and routed peer-to-peer.

flowchart LR Client(["🖥️ Client\nHTTP or TCP"]) Connect["tubo connect\nrenews Access Lease"] Relay(["tubo relay\ncircuit v2 · reachability only"]) Attach["tubo attach + share\nexact invite → Exact Authority"] Origin(["⚙️ Origin Service\nHTTP or TCP/TLS"]) Client -- "HTTP or TCP" --> Connect Connect -- "libp2p stream\n🔒 lease-authorized" --> Attach Attach -- "HTTP or raw TCP" --> Origin Connect -. "NAT traversal\nfallback" .-> Relay Relay -. "NAT traversal\nfallback" .-> Attach style Connect fill:#2563eb,color:#fff,stroke:#1d4ed8 style Attach fill:#2563eb,color:#fff,stroke:#1d4ed8 style Relay fill:#7c3aed,color:#fff,stroke:#6d28d9 style Client fill:#0f172a,color:#e2e8f0,stroke:#334155 style Origin fill:#059669,color:#fff,stroke:#047857
1

Reachability without trust

A relay provides NAT traversal only — never authorization. A verified, signed public bootstrap bundle is embedded in the binary for zero-config sharing.

2

Attach and share

Run tubo attach next to any HTTP API or raw TCP/TLS service, then tubo share mints a one-time exact invite under a dedicated Exact Pipe Authority key.

3

Redeem the invite once

The recipient redeems the invite exactly once — proving identity with a challenge response — and receives a durable accepted binding plus a short-lived Access Lease.

4

Every open is lease-checked

Leases expire in minutes and renew through the durable binding; revocation fences old access immediately. Raw duplex bytes flow after the authorized handshake — no cloud proxy in the data path.

Features

Everything you need, nothing you don't

Tubo is small, self-hosted, and built on open standards.

🔒

End-to-end encrypted

All traffic travels over libp2p Noise-encrypted streams. No relay or gateway sees plaintext data — only the origin service and the authorized client do.

🌐

Works behind NAT

Uses libp2p circuit relay v2 and hole punching to traverse NAT and firewalls. No inbound ports required on service hosts.

🔑

One-time exact invites

Every share mints a single-use, owner-signed invite bound to one exact Pipe. Redemption requires a fresh challenge-response proof of identity — and an invite can be revoked even before it is redeemed.

🏗️

Private swarm (PSK)

Generate a swarm key with tubo keygen swarm and share it among your nodes for a fully isolated private network.

🎟️

Short-lived Access Leases

Every remote Pipe open requires a verifiable Access Lease with a lifetime of minutes, minted by a dedicated Exact Pipe Authority. Pipe IDs, routes, and invites alone never authorize anything.

🗂️

Durable bindings, instant revocation

Accepted relationships survive restarts and invite expiry, renewing short-lived leases per open. tubo revoke fences invites, sessions, or all Pipe access at an advancing authorization epoch.

⚡

HTTP and raw TCP/TLS

Publish classic HTTP APIs or raw tcp://... targets. TLS passthrough works end-to-end because Tubo can expose a local raw TCP listener instead of forcing HTTP bridging.

🔄

Fail-closed by design

Invalid signatures, wrong subjects, expired or revoked leases, stale epochs, or unavailable revocation state always deny. Bound decoders and raw duplex bytes after the handshake keep the data plane lean.

🤖

AI & LLM ready

Expose LM Studio, Ollama, or any OpenAI-compatible API to collaborators. Streams and WebSocket upgrades work transparently.

Quickstart

Up and running in minutes

Three commands on two machines and you have a working encrypted tunnel.

# — Machine A: attach, then share a one-time exact invite —
$ tubo attach http://127.0.0.1:8080 --name myapi -d

✓ pipe/myapi ready
$ tubo share pipe/myapi
one-time invite; expires in 10m0s

# — Machine B: redeem the invite, get a local endpoint —
$ tubo connect --token <invite> --local 127.0.0.1:9000 -d

✓ http://127.0.0.1:9000  →  myapi  (Access Lease per open)

$ curl http://127.0.0.1:9000/healthz
OK
# — Relay host (public IP): start the relay —
$ tubo keygen swarm --out swarm.key   # generate once, share to all nodes
$ tubo relay --listen /ip4/0.0.0.0/tcp/4001 --public-addr /ip4/1.2.3.4/tcp/4001 --swarm-key ./swarm.key

# — Service host: join the overlay, attach, share —
$ tubo join overlay --relay /ip4/1.2.3.4/tcp/4001/p2p/12D3... --swarm-key ./swarm.key
$ tubo attach http://127.0.0.1:8080 --name myapi -d
$ tubo share pipe/myapi

# — Client host: join, redeem the invite, connect —
$ tubo join overlay --relay /ip4/1.2.3.4/tcp/4001/p2p/12D3... --swarm-key ./swarm.key
$ tubo connect --token <invite> --local 127.0.0.1:9000 -d
# — On the machine running LM Studio (port 1234) —
$ tubo attach http://127.0.0.1:1234 --name lmstudio -d

✓ Service published   name=lmstudio
✓ Share token         tubo connect --token eyJ...

# — On the client machine —
$ tubo connect --token eyJ... --local 127.0.0.1:51234 -d

# Use the OpenAI-compatible endpoint as if it were local
$ curl http://127.0.0.1:51234/v1/chat/completions \
    -H "Content-Type: application/json" \
    -d '{"model":"local-model","messages":[{"role":"user","content":"Hello"}]}'

# Works with Ollama too
$ tubo attach http://127.0.0.1:11434 --name ollama -d

# And raw TLS/TCP passthrough is first-class too
$ tubo attach tcp://127.0.0.1:8443 --name tlsdemo -d

Want the full picture? Read the Getting Started guide →

Use cases

What people build with Tubo

🤖

Share local AI models

Run LM Studio or Ollama on your workstation and give teammates a working API endpoint — no cloud GPU required, and no central proxy in the data path.

LM StudioOllamaOpenAI API
🔧

Webhook development

Receive webhooks from Stripe, GitHub, or any SaaS directly to your local dev server without ngrok or open firewall rules.

WebhooksDevLocal
🏠

Self-hosted API access

Expose a Home Assistant, Nextcloud, or Gitea instance to trusted users without touching your router.

Self-hostedHome network
🧪

Remote staging environments

Share a local staging build with a remote reviewer via a one-time signed token. No deployment needed.

StagingPreviewTokens
🏢

Revoke-and-regrant access

Grant a teammate access with one invite; when they leave, revoke Pipe access instantly and re-authorize someone else with a fresh invite at the new epoch.

RevocationEpochsTeam
🔬

Edge & IoT services

Publish sensor APIs or edge compute endpoints from devices behind carrier-grade NAT — no static IPs needed.

IoTEdgeNAT
Comparison

Tubo vs alternatives

See how Tubo compares to similar tunneling and overlay tools.

Capability Tubo ngrok Tailscale Cloudflare Tunnel
Self-hostable ✓ Fully ~ Partial ~ Headscale ✗
No cloud proxy in data path ✓ ✗ ✓ ✗
P2P NAT traversal ✓ libp2p ✗ ✓ WireGuard ✗
Signed invites + access leases ✓ Ed25519 ✗ ✗ ✗
Invite-only / revocable access ✓ ~ ✗ ~
HTTP API tunneling ✓ ✓ ~ ✓
Private swarm (PSK) ✓ ✗ ✗ ✗
Open source ✓ ✗ ✓ ✗

See full comparison →

Documentation

Explore the docs

Everything from a 5-minute quickstart to the full security model.