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.