One binary, six roles. Every deployment shape on this page is the same
jaque executable started with a different -target; there is nothing
to build separately and nothing to install differently per role. The
page is in two halves: section 1 is each role's contract, stated as what
it requires and what it refuses at startup, and sections 2 and 3 are how
those roles compose. A role that refuses a flag refuses it at startup
with an error, not silently; the lists below are the lists the binary
enforces.
Status: the remote agent (section 4) is planned and does not exist. See project status.
1. The six targets
1.1 all (default)
Text version
+----------------------------------------------+
| jaque -target all |
| |
| schedule --> execute --> fold --> append |
| ^ | |
| +-------------------------------+ |
+----------------------------------------------+
+ UI/API + /metrics
Schedules and executes checks in the same process. Requires -config.
Forbids -queue, because there is no second process to dispatch checks
to, and -notifier-id, because there is no separate notifier identity
to name.
1.2 engine
Text version
+------------------------+ .---------------------.
| jaque -target engine | ---- work ----> ( queue )
| owns the check loop | <--- result ---- ( (memory/shared) )
+------------------------+ `---------------------'
Decides what runs and when, and never runs a check itself: it publishes
each one to -queue and waits for the result. Requires -config and
-queue. Forbids -notifier-id.
1.3 worker
Text version
+------------------------+ .---------------------.
| jaque -target worker | <--- work ----- ( queue )
| runs the checks | ---- result ---> ( (memory/shared) )
+------------------------+ `---------------------'
No config, no event log, no projection. It pulls work items from
-queue and executes them. Requires -queue; forbids -config,
-coordination, -heartbeat-ttl and every notification flag. A worker
needs its own disk: any legacy plugin or WASM module a remote check uses
is installed on the worker's machine, not the engine's, because the
worker is where the check runs.
1.4 ui
Text version
+--------------------------+ .-----------------------------.
| jaque -target ui | <== follow ==== ( log server )
| projection + dashboard | -- cmd ingress -> ( eventlog + coordination )
+--------------------------+ `-----------------------------'
Read-only. It follows the event log and serves the dashboard and the
API; it never schedules or runs a check and never handles SIGHUP.
Requires -config, for labels, views and the dependency graph. Forbids
-queue, -command-file, -events-out, both -livestatus-* flags,
-heartbeat-ttl and every notification flag.
With -coordination pointed at the shared store, a command the ui
receives is forwarded to the engine fleet over jaque.work.cmd.ingress,
fire-and-forget. Without -coordination, writes are rejected with 503.
A -target ui process never joins engine membership.
1.5 sink
Text version
+----------------------+ .---------------.
| jaque -target sink | <== follow ==== ( event log )
| perfdata only | ( (shared) )
+----------------------+ `---------------'
Runs perfdata (metrics-input) sinks and nothing else, on its own
sink/membership/ bucket and a -sink-id (hostname by default).
Requires -config. Forbids -queue, -command-file, -events-out,
both -livestatus-* flags, -snapshot-out, -api-token, every
SMTP/Telegram flag and every notification flag; none of that surface
exists in this role.
-sinks selects which entries of the CUE config's sinks: block this
process runs; empty runs all of them. A sink declared with
input: "events" is rejected for this target: no events-input sink
runs under -target sink. This role does not reconcile its sink set on SIGHUP;
restart the process to pick up an added, removed or changed sink.
1.6 notifier
Text version
+--------------------------+ .---------------.
| jaque -target notifier | <== follow ==== ( event log )
| delivery only | ( (shared) )
+--------------------------+ `---------------'
Runs notification delivery and nothing else, on its own
notifier/membership/ bucket (a sibling of membership/ and
sink/membership/, nested under neither) and a -notifier-id.
Requires -config, because contacts and policies live there. Forbids
-queue, -command-file, -events-out, -snapshot-out, both
-livestatus-* flags and -api-token.
It also forbids -notify-delivery. That flag belongs to all and
engine, which decide where delivery happens; the notifier is the
delivery target and has nothing to decide. It accepts -smtp-*,
-telegram-token, -notify-workers and -notify-queue.
2. Two decisions, three shapes
Every deployment sits somewhere on two independent axes: how many
processes (one -target all, or one process per role) and how many
engines (one, or several sharing ownership of the object set). The axes
compose; production is usually both split by role and running more than
one engine. The three shapes below are the useful corners of that grid,
not three rungs of a ladder.
2.1 Standalone
Text version
+------------------------------------------------+
| jaque -target all |
| |
| schedule --> execute --> fold --> append |
| ^ | |
| +-------------------------------+ |
| |
| eventlog: embedded, in-process |
+------------------------------------------------+
One process. Nothing crosses a network boundary.
Everything in one process. Overview,
section 2, says when this is enough. The chart renders this shape with
deploymentMode: standalone.
2.2 Split by role
Text version
+------------------------+ -queue +------------------+
| jaque -target engine | --------------> | -target worker |
| owns the check loop | | runs the checks |
+------------------------+ +------------------+
| |
+--------------- -eventlog ------------+
|
v
.-----------------.
( log server )
( external )
`-----------------'
|
+----------- folds -+------------+
| | |
v v v
+----------------+ +------------------+ +----------------------+
| -target ui | | -target sink | | -target notifier |
+----------------+ +------------------+ +----------------------+
each follows the log on its own membership bucket
Every role points -eventlog and -coordination at the same external
log server. engine dispatches work over -queue nats://...; one or
more worker processes pull it, scoped by -zones (section 3). ui,
sink and notifier each follow the log independently and each scale
on their own membership bucket.
Splitting by role buys scale for worker, ui, sink and notifier,
and network isolation between them. It does not buy availability of the
check loop: there is still exactly one engine process, and if it dies
checks stop until it comes back. Section 2.3 is the second axis that
fixes that, and the two combine.
2.3 Multiple engines
Text version
rendezvous hash (HRW) over the live engines
|
+-------------------+-------------------+
| | |
+----------------+ +----------------+ +----------------+
| -target engine | | -target engine | | -target engine |
+----------------+ +----------------+ +----------------+
| | |
+-------------------+-------------------+
|
v
.---------------------------.
( log server )
( eventlog + coordination )
`---------------------------'
replicas: 3+ -- active/active, every engine owns a share, none idle
replicas: 2 -- active/passive failover: the survivor takes over
This is 2.2's second axis, not a replacement for it: the same role
split, with more than one engine process instead of one. Cluster and
coordination is how
membership, rendezvous-hashed ownership, heartbeats and epoch fencing
combine to make that safe. deploymentMode: split renders this shape;
engine.replicas is the second axis.
3. Worker zones
-zones (default default, comma-separated) names the zones a worker
serves. Each host in CUE carries a zone (default "default"); each
service inherits its host's zone unless it sets its own. The engine
publishes each check to the queue of its object's zone, and only a
worker subscribed to that zone picks it up. This is the whole mechanism
for routing a check to a worker that can reach a given network segment:
there is no per-check worker address, only a zone name both sides agree
on.
4. The remote agent: not built
A remote agent, outbound gRPC streaming over mTLS, is planned for sites
where even the pull-based worker model does not fit.
It does not exist. Today, cross-network execution is the
engine/worker split of section 2.2, over a queue both sides can
reach.
5. Security considerations
Splitting changes which process holds which secret and which process
opens which listener. worker holds no config and no notification
secret; sink and notifier open no dashboard, API or Livestatus
listener, which is why they forbid -api-token and the -livestatus-*
flags. A ui process with -coordination can submit writes to the
engine fleet, so it is not read-only toward the cluster, only toward
the log. Security lists what each
listener authenticates.