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>
| Part | Source |
|---|---|
<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-serviceedge:overrides it. Both accept a single public domain (edge: ny.uplink.computer) or a list (edge: [ny.uplink.computer, ldn.uplink.computer]). UPLINK_EDGEis 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 in | How to set it | Who it admits |
|---|---|---|
| Owning account | serve --account <id>; in YAML, omit account for personal or use an organization slug | Every verified member of that personal or organization account |
| Invite people | serve --share <email> (repeatable), share: [<email>] | Each invited email, after an identity login |
| Bearer token | serve --auth <token>, password: <token> | Anyone presenting the token |
| Fully public | serve --open, public: true | Anyone 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.