Uplink Docs
Access Control
Documentation

Access Control

Uplink is private by default — every verified member of the app’s owning account gets in. For a personal account, that is just you. For an organization account, that is everyone in the organization. Access is additive: invited email addresses and a bearer token each add another independent way in, while --open opens the route to everyone. The edge compiles them into one policy per route and evaluates it before any traffic reaches your app; unknown hosts collapse to a generic not-found.

This page covers the semantics of each way in. An IP allowlist can further restrict these gated access modes; the tunnel’s base request limit remains a first-class firewall setting. For the flags and YAML fields, see Serve a Port and Formations.

Identity and private routes

Private routes are served through the same public edge URL as everything else, but the edge requires visitor identity before forwarding. Access is admitted for:

  • every verified member of the owning account, and
  • anyone added by email with uplink share <app> <email> or share: in uplink.yaml.

A visitor opens the URL, completes a one-time emailed-code login at the edge, and is admitted if their identity is on the list — no VPN and no client install. Because the edge must verify who the visitor is, account-based access (owning-account membership and share) requires a managed, auth-backed edge and a control plane. Key-mode self-hosted edges can’t gate on account identity; use a bearer token there instead.

uplink share demo contractor@example.com    # invite one person
uplink unshare demo contractor@example.com  # revoke

Share with an organization

Users can belong to any number of organizations. To share an app with one of them, make that organization the app’s owning account. Every organization member can then open the private app; there is no separate per-app team switch.

Create an organization and invite its members from Accounts in the web dashboard. In the desktop app, choose Organizations → Use account before creating a tunnel. That selection affects new tunnels only; existing tunnels keep their owner. From the CLI, list the account IDs available to your login, then choose one explicitly:

uplink status --output=json
uplink serve 3000 --name dashboard --account acct_acme

In uplink.yaml, omitting account uses your personal account; an organization-owned service names the organization’s stable slug. share: remains useful for granting access to people outside that account:

services:
  dashboard:
    account: acme
    port: 3000
    share: [contractor@ext.com] # organization members, plus this person

Bearer tokens

A bearer token is a non-account way in — good for webhooks, scripts, and simple shared secrets, and the way to gate a route on a self-hosted key-mode edge:

uplink serve 3000 --auth s3cr3t
services:
  api:
    account: acme
    port: 8080
    password: ${API_TOKEN}      # a bearer-token way in (hashed locally)

The raw token is hashed locally with SHA-256 before storage or edge registration. Non-browser clients send Authorization: Bearer <token>; browsers get an edge token-entry page whose unlock grant (up_bearer) is separate from account session cookies. A token is additive — it stacks with owning-account membership and share on the same route.

Restrict access by IP

Choose Restrict to IPs beside Invite emails and Add API token in the Access panel, then add exact IPv4 or IPv6 addresses and CIDR ranges. Requests must come from one of those sources before the owning-account, invite, or token policy is evaluated. The field autosaves on an existing tunnel.

services:
  admin:
    account: acme
    port: 3000
    allow_ips: [203.0.113.0/24]

IP restriction is a gated-access option, so it is unavailable while Public access is enabled. Public access temporarily bypasses the saved restriction; turning it off restores the allowlist.

Choosing how to share

You want…Use
Only you to reach an internal appOwn it with your personal account; add no extra access keys
Every member of an organization to reach itMake the organization the owning account
A specific person outside the owning account to reach itshare: [<email>]
A webhook or script with a shared secretpassword: (bearer token)
Access only from trusted networksallow_ips: [<IP-or-CIDR>]
Gated access on a self-hosted key-mode edgepassword: (account keys need a managed edge)
A public demo or callback URLpublic: true

These combine: an organization-owned route can invite someone outside the organization and carry a token, while allow_ips restricts all of those ways in. Only public: true is exclusive — it temporarily bypasses the gated access settings.

For the protocol-level guarantees behind enforcement — holder-of-key binding, fail-closed routing — see the security model.

Search across 15 pages.
↑↓ navigate openEsc close