LAN access: tokens and the web surface
Minting bearer tokens and serving the TLS web and phone approval surface, separate from the loopback state backend.
The browser dashboard and phone approval surface reach the LAN over a bearer-token-gated TLS listener that is separate from the loopback state backend. The model is Decision 0009.
Two listeners, two auth stories
| Listener | Bind | Auth |
|---|---|---|
| State backend | 127.0.0.1 only |
Per-workspace bearer derived from the envelope; never a LAN token |
| Web + API surface | Non-loopback, TLS | A LAN access token, exchanged for a session cookie |
The state backend is the OpenTofu HTTP backend; it stays on loopback and takes no LAN token. The web surface is the only thing that binds a routable address, and it always requires a token: a non-loopback bind refuses to start unless at least one active token exists.
Minting and managing tokens
Tokens are minted only from the box (the data dir is the root of trust):
exocomp token new laptop --scope operator --expires 720h
exocomp token new node.lan --scope host --host node.lan
exocomp token list
exocomp token revoke laptop
token new prints the token exactly once (kit discipline). token list shows name,
scope, expiry, last-used, and a non-secret prefix. Revoking a token is immediate and
invalidates every session it bootstrapped.
Serving the surface
Run the surface as its own process, or alongside the daemon:
exocomp web --addr 0.0.0.0:8443
exocomp serve --web-addr 0.0.0.0:8443
With serve --web-addr, the daemon runs both listeners in one process sharing one engine,
so an approval decided in a browser releases the job into that daemon's queue. On first
bind the listener generates a self-signed certificate (key 0600 in the data dir) and
prints its SHA-256 fingerprint for trust-on-first-use pinning; the fingerprint also shows
in doctor.
A browser presents the token once and receives an HttpOnly, SameSite=Strict session
cookie bound to the token row. --insecure-http exists, is loud at startup and in the UI
footer, and is never the documented path — front the surface with Tailscale Serve or
Caddy+ACME where available.
To hand a token to a phone by scanning instead of pasting, see Device pairing (QR).
Related: Running the daemon · Reacting to alerts.