> Section: [7. Running it](https://jaque.sh/docs/deployment/overview.md)
> Next: deployment/cluster-and-coordination
> Index: https://jaque.sh/llms.txt


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](https://jaque.sh/docs/project/status.md).

## 1. The six targets

### 1.1 `all` (default)


```text
+----------------------------------------------+
|              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
+------------------------+                  .---------------------.
|  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
+------------------------+                  .---------------------.
|  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
+--------------------------+                   .-----------------------------.
|  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
+----------------------+                 .---------------.
|  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
+--------------------------+                 .---------------.
|  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
+------------------------------------------------+
|                 jaque -target all              |
|                                                |
|     schedule --> execute --> fold --> append   |
|        ^                               |       |
|        +-------------------------------+       |
|                                                |
|          eventlog: embedded, in-process        |
+------------------------------------------------+

One process. Nothing crosses a network boundary.
```

Everything in one process. [Overview](https://jaque.sh/docs/deployment/overview.md),
section 2, says when this is enough. The chart renders this shape with
`deploymentMode: standalone`.

### 2.2 Split by role


```text
   +------------------------+     -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
      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](../deployment/cluster-and-coordination.md) 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](https://jaque.sh/docs/deployment/security.md) lists what each
listener authenticates.
