The decentralized SOC
A SOC is usually built around one assumption: every log line reaches a central place, and that place decides what is an attack. Everything downstream inherits that assumption, including the bandwidth bill, the detection latency, and the blast radius when the correlator is unreachable.
MarlinOS starts from the opposite end. The host that produced the log parses it, enriches it, matches it, and scores the entity behind it, before the line is written to disk. Edges then compare notes with their peers. What travels is a verdict, and what makes a detection is quorum across the mesh rather than one machine's view of everything.
Decide where the evidence is
Parse, CTI, Sigma, and entity scoring run in the rsyslog hot path on the collector. The parsed event is already in memory, so the verdict costs a match, not a round trip.
Agree without a correlator
Edges gossip evidence about scored entities into a shared counter. An alert needs at least two independent sources, so it cannot fire from one node's view however strong that view is.
Survive the link
An offshore vessel, a DMZ collector, an air-gapped floor. The uplink is how verdicts are delivered, not how they are produced.
Two shapes for the same job
The difference is not the detection content. Both shapes can run the same Sigma corpus. The difference is where the decision happens, and therefore what has to be true for detection to work at all.
Quorum: weak signals, one detection
The interesting adversary does not trip a rule on one host. They leave a small trace on several: a handful of failed logins here, one port touch there, an odd DNS pattern somewhere else. Each is under any sane threshold on its own. Raise the sensitivity and you drown in false positives; leave it alone and nothing fires.
Each edge deposits what it scored, and peers accumulate those deposits into a shared per-entity counter. The composite score is a property of the mesh: it can cross the detection threshold even though no participant ever saw enough to fire on its own. The requirement is structural, not a heuristic. An alert needs the accumulated confidence, a minimum number of hits, and at least two distinct sources, and an entity's source count is only raised by a remote peer's reinforcement, never by the local deposit.
When the link dies
Every deployment we care about has a link that is not always there. Offshore racing means days without satellite. A DMZ collector may be firewalled to a one-way path. An industrial floor may be air-gapped by policy. In the centralized shape those are outages of detection. Here they are outages of delivery.
What actually leaves the edge
Forwarding raw logs becomes a policy choice rather than a requirement. That is the practical consequence of the whole design, and it is where the bandwidth and storage numbers come from.
| Plane | Payload | Scope |
|---|---|---|
| Verdicts | Scored entity, detector output, and OCSF 1.8.0 projection. Sigma rule identity rides along for promoted signals: correlations, and single-event rules at high or critical severity. | Edge to console, or edge to an existing SIEM. |
| Sigma partials | $!sigma_contribution: a JSON array, one entry per matching correlation rule. Each carries corr_id, event time, group values and its partial (count, numeric, seen_mask or value). |
Hashed onto one owner in a configured peer ring. See mmsigma. |
| Pheromone | Evidence about a scored entity, added into a shared per-entity counter, plus liveness. | Gossip across tenant peers over SWIM and PlumTree, run by the immesh rsyslog module. |
| Raw lines | The original log, unchanged. | Optional. Kept local, or forwarded when policy or retention says so. |
What this is not
The design buys locality and availability. It does not buy a global view for free, and pretending otherwise is how these architectures get a bad name.
- Not a short window across a WAN. Commutative
correlation merges across a peer ring the operator configures per
site, and high RTT forbids sharing the same
event_countacross sites. The ring is static and the module never consults liveness, so a dead member is undefined behaviour until the overlay is rewritten, not graceful degradation. See what actually happens. - Not a replacement for retention. Forensic search over months of raw data is a different job with different storage. WAKE decides what deserves to be kept and looked at.
- Not a second correlator in Python. A correlation fire is a fact produced once, in C. Nothing downstream re-counts it.
- Not a trained central model. Baselines are local and adaptive: an EMA per protocol and port over a weekly seasonal profile, plus per-entity rolling windows and Welford population thresholds. State is per-node; there is no shared clock and no model to ship.
Something still has to manage the nodes
A mesh of edges is only as good as your ability to configure and observe them. We built Fleet for that: enroll, apply, drift, WireGuard, one YAML platform per host role. It is a control plane, not the product, and it is deliberately small.