Authentication
How the orchestrator authenticates callers, across the CLI, SDKs, and browser
Fuse’s orchestrator uses a single shared bearer token model. Self-hosted, single operator. There are no users, roles, or JWTs; whoever holds the token is the operator.
The master token
Set via ORCH_AUTH_TOKEN (env) or --auth-token (flag) on the orchestrator. Every
API request sends it as a standard bearer header:
Authorization: Bearer <token>
The server compares it with a constant-time comparison (no timing leak). An empty
token is a no-op pass-through (insecure/dev mode, useful for local exploration
only) only when no API key store is configured (no DATABASE_URL). This is
what the Quickstart relies on. With Postgres wired up,
an empty ORCH_AUTH_TOKEN does not disable auth, it leaves API keys as the only
accepted credential and there is no bootstrap path to mint one. Set
ORCH_REQUIRE_AUTH=true in production to fail fast on this.
Revocable API keys
For anything beyond a single shared secret, the orchestrator also accepts revocable API keys, issued and managed by the master token holder:
fuse apikeys create --label "ci-runner"
fuse apikeys list
fuse apikeys revoke <id>
apikeys commands themselves require the master token. Connect with --master
to mark a context’s token as the master token:
fuse connect http://orchestrator:8080 --token <master-token> --master
Keys are shown once at creation (fuse apikeys create prints the raw secret) and
are unrecoverable afterward; they’re stored hashed. Both the master token and any
API key are accepted interchangeably as a bearer token on most /v1/* routes.
Master-token-only operations
These return 403 for an API-key principal:
| Operation | Route |
|---|---|
| Key management | /v1/api-keys (all methods) |
| Exec in a guest | POST /v1/environments/{id}?action=exec |
| Attach to a guest | GET /v1/environments/{id}/attach |
| Register or update a host | POST /v1/hosts |
| Cordon / uncordon a host | POST /v1/hosts/{id}?action=cordon|uncordon |
| Remove a host | DELETE /v1/hosts/{id} |
API keys carry no scopes today, so these are the operations where a key would otherwise be equivalent to the master token. Host registration takes a caller-supplied agent URL and token and can replace the provider details of an existing host id, which decides where the orchestrator sends every subsequent VM operation.
Host reads (GET /v1/hosts, GET /v1/hosts/{id}) stay open to any
authenticated caller. They return topology and capacity, never a host’s agent
token.
Registration also validates the agent URL before anything is dialled: http or
https only, no embedded credentials, no query string, no fragment. Redirects
from a host agent are never followed, so a compromised or misconfigured agent
cannot forward the orchestrator (and the token it carries) to another origin.
Browser / session auth
For a browser-based frontend (Fuse’s optional dashboard), the token is exchanged for an HttpOnly session cookie so the browser’s JS never holds the secret after login:
POST /loginwith{"token": "..."}: on success, sets an HttpOnlyfuse_sessioncookie (SameSite=Lax,Securewhen serving TLS or whenORCH_SECURE_COOKIES=true, 7-day max-age).POST /logout: clears the cookie.BearerAuthaccepts either theAuthorizationheader or (if absent) thefuse_sessioncookie. The header always wins if both are present.
Deployment constraint: this only works for a same-origin deployment (SPA served
through the same reverse proxy as the API). Genuine cross-origin (SPA on a different
origin than the API) isn’t supported yet. It would need credentialed CORS plus
SameSite=None; Secure (neither of which is implemented). Front the SPA same-origin.
Host agent tokens (separate concern)
The tokens above authenticate callers of the orchestrator. A completely separate token pair authenticates the orchestrator to each host agent:
FIRECRACKER_TOKEN: read by the orchestrator as the defaultfc-agenttoken.QEMU_AGENT_TOKEN: set on the GPU host itself, the orchestrator never reads it, it receives the per-host token at registration time viafuse host register --token. A stored per-host token that drifts from the agent’s env produceshttp 401at env-create time.
These never reach the CLI, SDKs, or browser. They’re purely orchestrator-to-host. See Firecracker host setup and GPU host setup.
Per-VM secrets (a third, unrelated concern)
Secrets you pass to fuse up --secret key=value or fuse environment create --secret ... are yet another layer: per-VM credentials, generated and encrypted at rest
(TOKEN_ENCRYPTION_KEY), scoped to a single environment. Not an auth mechanism for
the API itself. See Fusefile for how
they’re declared and resolved.