Skip to content

Architecture

This page gives the high-level design: the programs that make up Signalith, what each part of the server does, and how an event travels from a computer to a finding. For the security view of the same parts (trust boundaries, threats and defenses), see the threat model.

The programs

Program Where it runs What it does
Signalith server (signalith) One or more servers Web pages and API, data intake, search, detections, findings, cases, playbooks, settings. One Go binary with the web interface built in
OpenSearch Next to the server, or a separate cluster Stores events, findings and Signalith's own state. Signalith talks to it over HTTPS with a client certificate
Signalith Agent (signalith-agent) Each monitored computer Installs, configures and supervises Fluent Bit and osquery, and reports their health. See Signalith Agent
Fluent Bit and osquery Each monitored computer Fluent Bit reads and sends logs; osquery reports inventory and file changes and answers live queries. Both come from their own publishers

Other senders need no agent: syslog devices, OpenTelemetry collectors, HEC-compatible senders and cloud services that Signalith pulls from (see Sending data).

 Computers                    Signalith server                       OpenSearch
 ─────────                    ────────────────                       ──────────
 Agent ─ Fluent Bit ─HTTPS:7779─►┐
 Agent ─ osquery ────HTTPS:7779─►│  intake ─► parse ─► normalize ─────► daily event
 Syslog devices ───UDP/TCP 514──►│  (limits,   (per     (data model     indices
 OTLP / HEC senders ──HTTPS─────►┘  tokens)    source)   fields)
                                                                 ┌──── findings, cases,
 Browsers, API, MCP ─HTTPS:9000─► web pages + API ─► search ─────┤     settings, users,
                                     │                           │     audit log
                                     └─ detections (scheduled) ──┘
                                        ─► findings ─► risk, notifications, playbooks

Inside the server

The server is one process made of packages under internal/. The main groups:

Area Packages Role
Web and API api, httpserver, auth, users, oidc, saml, scim, mcp Serves the web interface (web/) and the JSON API, signs people in, checks each request against the user's role and tenant
Intake ingest, syslog, agents, agenttokens, agentproto, m365, okta, cloud pulls Accepts events, enforces size and rate limits, checks agent tokens
Parsing and data models datamodel, clusterparsers, redact Turns raw events into common fields grouped by data model (Authentication, Endpoint, Network Traffic and others) so one search covers many sources
Storage store, retention, clusterarchive, archivecrypt, summary Writes to OpenSearch in daily indices (<prefix>-<datamodel>-YYYY.MM.DD, split into parts on busy days), applies retention, moves old days to encrypted cold storage, keeps summary indexes
Search query, search, nlq, lookuptables Parses the pipe-style query language, runs what it can inside OpenSearch and the rest in the server, with time and size limits. nlq turns plain-English questions into queries
Detections detect, sigmacheck, splcheck, content, ruledraft Runs detections on a schedule, converts Sigma and other rule formats into Signalith queries, loads signed content updates
Findings and response findings, risk, cases, storyline, investigate, respond, playbooks, notify, ticketing, chatops Groups detection hits into findings with risk scores, tracks cases, runs response playbooks (with approval), and sends notifications and tickets
AI assistant, investigate, mcp Optional AI features using a model you choose; the MCP server is read-only
Settings and secrets config, secrets, securefile, audit Settings with validation, secrets encrypted at rest with the master key, and a signed, chained audit log
Cluster cluster, clusterauth, clusterjoin, clusterpki, clustertls, clustercfg, ospki, tlsauto Lets several servers share one OpenSearch: membership, the cluster key, the certificate authority, shared settings and the choice of which server runs background jobs
Tenants tenants Keeps each tenant's data, users and settings apart in multi-tenant mode

How an event becomes a finding

  1. A sender delivers events to the agent port (7779), a syslog port or an intake API. The server checks the sender's token and the size limits, and refuses what does not fit.
  2. A parser for that source pulls out fields, and the event gets its data model and common field names. Unknown fields are kept.
  3. The event is written to that day's index for its data model.
  4. Each detection is a saved query with a schedule and a look-back window. When it is due, the server runs the query over that window. Each row it returns is a hit.
  5. Hits become findings, grouped by entity and scored for risk. A finding can raise a notification, open a ticket, start a playbook or be added to a case.

Several servers

Any number of Signalith servers can share one OpenSearch. Every server serves the web pages, takes in data and searches. They find each other through OpenSearch and share settings signed with the cluster key. One server at a time runs the background jobs, detections can be spread across all of them, and if a server stops, another takes over its work. See Servers and Multi-server setup.

Where state lives

  • OpenSearch: events, findings, cases, users, shared settings, detection state and the audit log. Records Signalith depends on are signed with keys OpenSearch never holds.
  • The state folder on each server: the master key, the cluster key, certificates and the server's own settings file. Anyone who can write it controls that server; back up the master key (see Backing up the key).

Built with

Go (standard library crypto, no cgo of its own), OpenSearch 2.17 or 3.x, Fluent Bit, osquery, and plain HTML, CSS and JavaScript for the web interface with no build step.