jaque project

Check-based monitoring engine

Status: production-ready

jaque.sh

September 2026

A monitoring engine with a record of every move.

Checks for hosts, services and network gear. Your Nagios plugins, configs and Livestatus tools keep working. One binary.

jaque checks hosts, services and network gear and keeps the states you are used to: soft and hard, acknowledged, in downtime, depending on something else. Every change of state is written to a log before anything else happens, so you can always go back and see what the engine saw. It comes as one binary.

$ curl -fsSL https://pkgs.jaque.sh/install.sh | sh

[ install ] [ coming from nagios ]

An incident, replayed

Here is an ordinary night. A database stops answering, the engine retries sooner than usual, one page goes out, the service that depends on the database stays quiet instead of paging too, someone acknowledges, and the recovery closes it.

14:02:11  db-1/postgres    CRITICAL  soft 1/3  connection refused
          retrying in 30s: a soft state shortens the interval
14:02:41  db-1/postgres    CRITICAL  soft 2/3  connection refused
14:03:11  db-1/postgres    CRITICAL  hard 3/3  connection refused
14:03:11  -> oncall (webhook)  first notification: hard transitions only
14:03:11  shop-api/health  UNREACHABLE  depends on db-1/postgres
          suppressed: it depends on db-1/postgres
14:06:02  db-1/postgres    ACKNOWLEDGED by ana  sticky ack
14:11:11  db-1/postgres    OK  hard  recovery notified; ack cleared
14:11:11  shop-api/health  OK  reachability recomputed from the graph
Figure 1: a scripted incident

That transcript is scripted. demo.jaque.sh is a real jaque you can look at, read-only, watching nine hosts, with its config published so you can see what each state rests on.

Nothing to abandon

Most of us have a shelf of check scripts that took years to get right. They run unchanged: the plugin protocol, exit code plus output plus perfdata, is fixed in jaque and stays fixed. Routers and switches are checked over SNMP, since network gear does not run agents, and there are native checks for the common cases, so you do not need a script for a ping.

jaque import reads your Nagios object files and writes a native config, with a report of what mapped, what it approximated and what it could not carry over. From then on the config is yours. It is typed, so a mistake is caught when you load the config rather than during an incident.

hosts: gw: {
    address: "192.168.1.1"
    check: {type: "icmp", host: address}
}
Figure 2: a complete, loadable configuration

jaque speaks Livestatus, so the dashboards and consoles you already use keep working. Livestatus, the plugin protocol and the config language are open, so nothing you write for jaque is tied to it.

One binary, any shape

One file holds the event log, the state machine, the scheduler, the API and the dashboard. There is no database or broker to look after. When one machine is no longer enough, the same binary runs one role per process, engines, workers, notifiers, event handlers and sinks, and the config stays as it was. The deployment guides cover one node and split roles on systemd, compose and Kubernetes.

One nodeSeveral nodes
systemd host (deb/rpm) Single node, systemd: one host, the packaged unit, nothing external. Split by role, systemd: one unit per role across hosts you manage yourself.
Docker Compose Single node, compose: one container, a named volume for the event log. Split by role, compose: one container per role plus a log server, all in one stack.
Kubernetes Single node, Kubernetes: the Helm chart in standalone mode, one pod. Split by role, Kubernetes: the chart in split mode, one workload per role.

When it pages you, you can see why

Every state change is computed from the log, so replaying the log gives the same states. If the process dies mid-check it comes back with the same history. Paging follows the thresholds and policies you wrote; nothing scores or guesses in between.

The check pipeline: the engine schedules what is due and owns object state in memory, workers take the work off a queue and publish results back, the pure state machine folds each result and appends it to the event log, and every consumer reads the logthe engine owns object state in memory; several engines partition the objectsschedulerdecides what is duestate machinepure folddispatchwork queuedue checksworkersexecutorsresultscheck resultsappendThe two queues exist only when the engine and the workers are separateprocesses; run everything in one and the check runs in-process instead.event logmemory | file | remoteprojectionsUI, API,livestatusnotifieradaptershandlersrun a commandon state changesinksclickhouse,http, exec,file, otlparchivesegmentsreplayrebuild anyprojectionNothing reaches in and mutates state; each consumer reads the log at its own pace.
Figure 3: every transition appends; everything downstream reads the log

The engine handover is a TLA+ model and the state machine is property-tested. How it is verified has the models and the invariants, for anyone who wants to check our work.

Status

jaque is in production use. The status page lists each capability with the evidence behind it, and it says plainly what is missing: the Nagios importer has not yet seen a config from outside this project, and the remote agent is not built.

capabilitystate
soft/hard states, flap detection, acks, downtimes, dependencies, escalationsshipped
event-log replay survives kill -9shipped
Livestatus: LQL parser and nine tablesshipped
signed packages, apt and yum repositories, image and chartshipped
Nagios importerimplemented, unverified
remote agentunbuilt

It is not a time-series database; perfdata goes out to ClickHouse, remote_write or OTLP. There is no anomaly detection and no model in the loop.

A soak of 10000 objects holds a p99 check drift under 5ms in half a gigabyte of memory; the benchmarks page has the machine, the method and every other cell.

Start

Install it and point it at one host; the quickstart takes it from there. If you run Nagios, run jaque import on your object files and tell us what did not come across; that is what the importer needs most. Write to [email protected], or check the status page first.