Search docs

Search the Beamd documentation

Naming & project config

How Beamd picks a tunnel's subdomain, including the port default, --as and --from, the one-label rule, and a committed beamd.yaml file.

A tunnel's public name is a single subdomain label on your edge's base domain: apihttps://api.beam.example.com. Beamd gives you three ways to set it, and a project file so you rarely set it by hand.

The subdomain label

By default the label is the port number: beamd open 3000https://3000.beam.example.com. That's fine for a quick look, but real apps want a stable name.

--as and --from

Set the label explicitly, or derive it from your project:

beamd open 3001 --as api       # literal label   → api.<base>
beamd open 3001 --from repo     # derive it        → <repo-name>.<base>

--from sources:

SourceLabel becomes
port (default)the port number
dirthe current folder name
repothe git repository name
branchthe current git branch
worktree<branch>-<repo> in a linked git worktree on a non-default branch, else the repo name

--as (a literal) wins if you pass both. A good default for branch-based previews is --from branch; set it once as a naming default.

The one-label rule

The wildcard certificate is exactly one DNS label deep: *.<base> (flat) or *.<slug>.<base> (namespaced). So a tunnel name must be a single RFC 1123 label: lowercase letters, digits, and hyphens. Encode structure with hyphens, not dots:

  • api, web-api, proj-ab12-web
  • a.b (nested labels don't get a cert and won't resolve)

This matters most for multi-app and worktree workflows: name a worktree's API and web as proj-ab12-api and proj-ab12-web, not api.proj-ab12.

Hosted vs self-host. The hosted service folds your org into the label as a hyphen suffix (api-acme.beamd.run), so every tunnel stays under one *.beamd.run certificate. A self-hosted edge instead namespaces with a dotted slug (api.turing.beam.example.com), backed by a per-slug *.turing.beam.example.com cert. Either way, the name you choose is still a single label.

Project config (beamd.yaml)

Commit a beamd.yaml at the repo root so the right edge, scope, and name come from context. Then open and run need zero flags. Create it with beamd link, or by hand:

# beamd.yaml
server: acme.com    # which edge (account)
scope: acme         # which org (hosted; omit for a self-hosted edge)
from: repo          # how to name the tunnel (or `name: <literal>`)

Beamd walks up from the current directory to find it. A gitignored beamd.local.yaml overrides it for your machine, following the .env / .env.local pattern. A beamd.yaml references an edge and scope, never a token, so it's safe to commit. (More on server / scope in Accounts & scopes.)

Multiple apps: services

A repo with more than one server (say an API and a web app) lists them under services:, mapping a name to its local port:

# beamd.yaml
server: acme.com
scope: acme
services:
  api: 3000
  web: 8080

Now each gets its own URL by name. The service name becomes the label, and the shared server + scope are reused:

beamd open api     # → api-acme.acme.com   (port 3000)
beamd open web     # → web-acme.acme.com   (port 8080)
beamd open         # lists the services to pick from

--as still overrides the label. beamd link --services api=3000,web=8080 writes the block for you.

Precedence

The label resolves in this order, first match wins:

1. --as <literal>            # this command
2. --from <source>           # this command
3. beamd.yaml  name: / from: # this repo (committed)
4. your naming default       # ~/.beamd/config, e.g. { from: branch }
5. the port number           # fallback