Authentication in jaque is opt-in. A process started with no -auth-config behaves exactly as it always has: reads are open, and -api-token optionally gates the RPCs that change state. Setting -auth-config turns on real identity, named humans and services, three roles, a browser session, in front of both the read and the write API. Neither mechanism is required, and only one may be configured at a time. Every other surface, the dashboard, /metrics, Livestatus and the external command FIFO, stays open to whatever can reach it regardless of which you turn on, and secrets arrive as flags or environment variables that anything inspecting the process can read. The posture is this: the network a jaque process listens on is the perimeter, and a reverse proxy is where TLS happens. Read this page before deciding which network a jaque process is allowed to sit on.

Status: there is no whole-system authentication story and no TLS in the binary. The gap is architectural rather than a missing flag, and it changes as the project matures. See project status.

1. The token-only gate, off by default

-api-token puts a bearer-token check in front of CommandService only: the RPCs that change state, ProcessCheckResult, AcknowledgeProblem, ScheduleDowntime and the rest of the write surface. With it set, every command call needs a matching Authorization: Bearer <token> header, compared in constant time. Left empty, the default, the command API is open. -api-token and -auth-config are two different auth models; jaque refuses to start with both configured at once.

2. Everything else is unauthenticated by design

/metrics and /healthz are unauthenticated HTTP endpoints on the same listener as the dashboard.

The dashboard's own files (/) are served without any check. What they show is a different question. Every figure on the page comes from the read API, so with no -auth-config the dashboard loads and displays everything, and with one set it asks for a sign-in and shows nothing until it gets one. The files being open is not a way around the block.

Livestatus (-livestatus-listen and -livestatus-socket) has no authentication at all, -auth-config set or not. Anything that can open the TCP address or the UNIX socket can query it. This is the protocol as Nagios, Thruk and NagVis already use it; jaque adds nothing to it in either direction. Both listeners also accept COMMAND, so a reachable Livestatus TCP listener is a command surface exactly as a writable FIFO directory is.

The external command FIFO (-command-file) is created mode 0660, inherited unchanged from Nagios, and no -auth-config reaches it either. File permissions and group ownership are the entire access-control story, and anyone able to write the file can drive jaque's state.

Event handlers run whatever command or module the handlers block names, on every state change that matches the trigger table, with no gate of their own: a legacy or command handler carries exactly a legacy check's trust (a binary the operator installed, run without a shell unless the handler sets shell: true), and a wasm handler runs in the same closed sandbox a wasm check does, with no network and no filesystem beyond what is mounted (ADR-032). See Event handlers for the config shape.

Notification adapter secrets, -smtp-pass, -telegram-token and the rest, arrive via flags or their JAQUE_-prefixed env vars. They are visible to anything that can read the process's environment or command line: /proc/<pid>/environ, ps, a container platform's own env inspection. jaque does not fetch them from a secret store.

3. Opt-in identity: -auth-config

A process started with no -auth-config behaves exactly as described above: reads open, -api-token the only optional gate on writes. Setting -auth-config to the path of a separate CUE document turns both CommandService and QueryService into identity-checked APIs, mounts a session-login surface alongside them, and mounts AdminService, the config write surface, absent when -auth-config is not set, since there is then no identity to require admin of. Leaving -auth-config out changes nothing else.

Identities live outside -config, in their own document, read once at process boot: changing them requires a restart, and a SIGHUP does not pick them up. The document's auth: block maps a name, human or service, to a role and exactly one credential:

// auth.cue, passed as -auth-config=auth.cue
auth: {
	alice: {
		role:          "operator"
		password_hash: "<jaque hash-password output>"
	}
	aggregator: {
		role:       "viewer"
		token_hash: "<hex digest of the aggregator's own token>"
	}
}

alice is a human: she logs in with a password and gets a browser session. aggregator is a service identity: the shape another process polling jaque's read API uses, a name with a token instead of a password and no login step. An identity carries one credential, never both.

jaque hash-password prints the hash a password_hash field expects. It reads the plaintext password from stdin, never from a flag or a positional argument, so it never lands in shell history or a process listing:

jaque hash-password <<< 's3cret'

Paste its output into the auth document; jaque never sees the plaintext again.

-session-secret signs the browser session issued on login. It is required the moment -auth-config is set, and jaque refuses to start without it. Sessions carry no separate store: rotating -session-secret invalidates every outstanding one at once, logging every logged-in human out immediately. Rotate it to force a sign-out, on suspicion of a leaked session, or on a schedule.

Three roles, each allowing everything the one below it does: viewer can call every QueryService read; operator additionally calls every CommandService write, ProcessCheckResult, AcknowledgeProblem, ScheduleDowntime and the rest; admin allows everything operator does, plus AdminService's ValidateConfig and ApplyConfig, the config write surface, see Admin service. Those two RPCs act on -config only: identities never ride them, in either direction. viewer and operator identities are refused AdminService calls with a permission error.

A logged-in human authenticates with a cookie; a service identity authenticates with an Authorization: Bearer <token> header carrying its own token, distinct from the hash stored in the auth document. See Command and query service for the session and bearer-token surface itself.

The command FIFO and Livestatus are unaffected by any of this: neither reaches -auth-config, and both stay open exactly as described above.

4. -read-only: the posture for an untrusted audience

-read-only unmounts CommandService and AdminService entirely: every request to either answers 404, whatever -api-token, -auth-config or the admin role would otherwise allow. It also refuses every Livestatus COMMAND, on either listener, with a 403, since no command sink is wired when it is set. QueryService, AuthService, /metrics and the dashboard stay exactly as described above, and the dashboard hides every command control regardless of role. It is refused at startup together with -api-token (the token only authorizes commands, which -read-only removes) or -command-file (the FIFO is a write surface); -auth-config is legal alongside it, since people can still sign in and browse.

This is the recommended posture for a listener facing a public or otherwise untrusted audience: a status page shared outside the team, a demo instance, anything where showing state matters but nobody reaching it should be able to change it. It removes the write surface at the process level rather than relying on a role check per request.

5. The stated posture

Put a reverse proxy in front of anything exposed beyond localhost and terminate TLS, authentication and network exposure there; jaque itself does not do TLS. Treat the network a jaque process listens on as the perimeter: -listen, -livestatus-listen, -coordination and the FIFO's containing directory all sit behind whatever boundary (firewall, private subnet, UNIX socket permissions) keeps untrusted clients out, because jaque will not turn them away itself. Coordination credentials are the most consequential of these: anyone who reaches that endpoint has full control of the monitoring system, reaching well past the engines' command surface; see the security considerations in Cluster and coordination. The default, -coordination memory, runs in-process and exposes nothing.

None of the above is a gap to be filed as a bug against a specific endpoint. It is the current shape of the trust model.

6. Security considerations

This page is the security considerations section for the deployment chapter. The pages that open a listener or handle a secret (Topologies, Cluster and coordination, Kubernetes, Docker) each end by pointing back here.