Uplink Docs
Serve a Port
Documentation

Serve a Port

uplink serve <port> is the quick path for a single local loopback port. It serves in the foreground until interrupted (add -d to detach).

uplink serve 3000                 # private — selected account members only
uplink serve 3000 --open          # public — anyone with the URL
uplink serve 3000 --auth s3cr3t   # add a bearer-token way in
uplink serve 3000 --share a@x.com # invite someone by email
uplink serve 3000 --account acct_acme # own it with an organization
uplink serve 3000 --name api      # set the URL prefix
uplink serve 3000 --edges ny.uplink.computer # pin a region (changes the URL)
uplink serve 3000 -d              # keep serving in the background

Reach for uplink.yaml and uplink up when you need more than one service, IP or request-rate controls, reusable firewall rules, per-service edges, or custom domains.

App URLs

Served apps use this host shape:

https://<name>-<device-slug><namespace>.<edge-domain>
PartSource
<name>--name, the default app<port>, or the services.<name> key in uplink.yaml.
<device-slug>Your local profile (a short, stable device id).
<namespace>Your account namespace, from the identity token in managed login. In self-hosted key mode there is no namespace segment — the host is <name>-<device-slug>.<edge-domain>.
<edge-domain>The public domain of the region or self-hosted edge you serve through — the nearest region by default, or the one you pinned with --edges, edge: in uplink.yaml, or UPLINK_EDGE. See Regions & edge selection.

Need your own hostname? On a managed edge, add and verify an account alias in the dashboard, then assign it with custom_domain in uplink.yaml. On a standalone edge, its operator creates an edge-side YAML alias instead. See Custom Domains.

Regions & edge selection

By default edge selection is Auto: each serve measures latency fresh and lands on the nearest region for where the device is now — there is no persisted default edge. Naming an edge or region pins it, and because the edge domain is part of every app URL, pinning also changes the public URL.

  • uplink serve … --edges <domain> pins for one serve (comma-separate to name several).
  • In uplink.yaml, edge: at the top level sets the default for all services and a per-service edge: overrides it. Both accept a single public domain (edge: ny.uplink.computer) or a list (edge: [ny.uplink.computer, ldn.uplink.computer]).
  • UPLINK_EDGE is the environment fallback, below both.

For a formation, the full precedence is: per-service edge: → file-level edge:UPLINK_EDGE → the set the service is already running on (so an unrelated edit never re-homes it on reload) → a freshly probed nearest region for a genuinely new service. uplink edges lists the regions and self-hosted edges available to you.

Access

A route is private by default — every verified member of the owning account gets in. Access is additive: each key below adds an independent way in, and they combine (OR’d). The edge compiles them into a single policy per route and evaluates it before proxying.

Way inHow to set itWho it admits
Owning accountserve --account <id>; in YAML, omit account for personal or use an organization slugEvery verified member of that personal or organization account
Invite peopleserve --share <email> (repeatable), share: [<email>]Each invited email, after an identity login
Bearer tokenserve --auth <token>, password: <token>Anyone presenting the token
Fully publicserve --open, public: trueAnyone with the URL

--open / public: true opens the route to everyone and overrides the gating keys. The other keys stack: an organization-owned app with --share a@x.com --auth s3cr3t admits organization members, a@x.com, and any token holder.

Pick the smallest set that fits. Account-based access (owning-account membership and share) needs a managed edge — the edge must verify visitor identity. Token and public access run on self-hosted key-mode edges too.

Bearer tokens

--auth (or password: in uplink.yaml) adds a bearer-token way in:

uplink serve 3000 --auth s3cr3t

The raw token is hashed locally before it leaves your device, and it stacks with the owning account or invited emails on the same route. See Access Control for the request and browser-unlock mechanics.

Sharing with people and organizations

share invites someone by email. To share with a whole organization, make that organization the app’s owning account; all of its members can use the private app. A visitor proves that identity and enters through the same public URL. Both forms of identity access need a managed edge.

uplink status --output=json                        # inspect accounts[].id
uplink serve 9000 --name admin --account acct_acme # organization-owned
uplink share admin contractor@example.com          # invite someone else
uplink unshare admin contractor@example.com        # revoke

share/unshare edit the app’s saved access; re-serve the app for the change to take effect on the edge.

In uplink.yaml, set the owning account and use share: for additional people:

services:
  admin:
    account: acme
    port: 9000
    share: [contractor@example.com] # organization members, plus this person

Foreground vs. background

uplink serve runs in the foreground until interrupted. For a one-off background serve, add -d/--detach — the app keeps serving after the command returns; stop it with uplink stop <name>. For anything you serve routinely, declare it in uplink.yaml and run uplink up — it hands the whole formation to the local agent and returns. Manage either with uplink status, uplink stop <name>, and uplink down. See Formations.

Search across 15 pages.
↑↓ navigate openEsc close