Getting Started
Uplink lets you share a local port — with the world or just your team — in one command.
uplink login # sign in once (an emailed code)
uplink serve 3000 --open # public: https://app3000-<device><namespace>.<edge-domain>
uplink serve 3000 # private: same URL, only you + people you share it with
uplink up # serve everything declared in ./uplink.yaml
Public URLs are as easy as ngrok. Private apps are reachable through the same URL but
gated: only you and the accounts you share with can open them, after a one-tap email
login — no VPN, no client to install. The same uplink login is all you need.
Identity is the only thing that’s centralized, and even that is optional when you
self-host; the edges that serve your traffic run anywhere — in the cloud or on
your own infrastructure — and hold no shared database.
Uplink is the app — an intuitive CLI and desktop client for serving local apps. Under it runs OpenTunnels, an open, robust tunneling protocol: a mutually-authenticated QUIC transport with TLS 1.3, per-connection channel binding, and a strict registration/stream wire format.
Install
cargo build --workspace
./tools/install.sh # installs `uplink` to ~/.cargo/bin
Quick start
uplink login # emailed one-time code
uplink serve 3000 --open # publish → prints the public URL
uplink share app3000 teammate@example.com # (private apps) let a teammate in
uplink status # who you are + what you're serving
A served app is reachable at
https://<name>-<device-slug><namespace>.<edge-domain>, where <namespace> is
yours (set at login), <device-slug> defaults to a short stable id, and
<edge-domain> is owned by the edge you serve through. The default <name> is
app<port>; override it with --name.
Serving a formation
For anything richer than a single port — saved access policies, firewall rules,
sharing lists, per-service edges, or many services at once — declare it in
uplink.yaml and serve it with uplink up:
services:
blog:
port: 3000
access: public # private (default) | password | public | policy:<name>
api:
port: 8080
access: password
password: ${API_TOKEN} # raw bearer; hashed locally before it is sent
uplink up # serve everything in ./uplink.yaml (foreground)
uplink up -d # detach: run in the background and return
Next steps
- Run any command with no arguments to see its usage line.
- Add
--jsontostatus,tunnels, oredgesfor machine-readable output. - Self-host an edge with no hosted identity using an API key (
uplink-edge setup).