Skip to content
Fuse
Esc
navigateopen⌘Jpreview
On this page

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 /login with {"token": "..."}: on success, sets an HttpOnly fuse_session cookie (SameSite=Lax, Secure when serving TLS or when ORCH_SECURE_COOKIES=true, 7-day max-age).
  • POST /logout: clears the cookie.
  • BearerAuth accepts either the Authorization header or (if absent) the fuse_session cookie. 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 default fc-agent token.
  • QEMU_AGENT_TOKEN: set on the GPU host itself, the orchestrator never reads it, it receives the per-host token at registration time via fuse host register --token. A stored per-host token that drifts from the agent’s env produces http 401 at 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.

Was this page helpful?