Skip to content

rsigma engine daemonπŸ”—

Run as a long-running daemon with hot-reload, health checks, and Prometheus metrics.

SynopsisπŸ”—

rsigma engine daemon [OPTIONS] --rules <RULES>

DescriptionπŸ”—

Loads rules and pipelines, opens an event source, evaluates events as they arrive, fans the detections out to one or more sinks, and stays alive until it receives SIGTERM/SIGINT. Reloads rules and pipelines on file change, SIGHUP, or POST /api/v1/reload. Exposes Prometheus metrics, REST control endpoints, and OTLP log ingestion on the same --api-addr.

This is the long-running counterpart of engine eval. Use it when you need state to survive restarts, hot-reload across rule changes, or a Prometheus-scrapeable detection engine.

For narrative coverage see Streaming Detection. For NATS-specific operations (auth, replay, consumer groups, DLQ) see NATS Streaming.

FlagsπŸ”—

RequiredπŸ”—

Flag Description
-r, --rules <RULES> Path to a Sigma rule file or directory of rules (recursive).

Event inputπŸ”—

Flag Default Description
--input <URL> stdin Event source. Schemes: stdin, http (accepts POST /api/v1/events), nats://<host>:<port>/<subject>.
--input-format <FORMAT> auto Input log format: auto, json, syslog, plain. With features: logfmt, cef.
--syslog-tz <OFFSET> +00:00 Timezone offset for RFC 3164 syslog (+HH:MM or -HH:MM).
--jq <JQ> unset jq filter to extract the event payload from each JSON object. Mutually exclusive with --jsonpath.
--jsonpath <JSONPATH> unset JSONPath (RFC 9535) query to extract the event payload.

Output sinks and DLQπŸ”—

Flag Default Description
--output <URL> stdout Detection sink. Schemes: stdout, file://<path>, nats://<host>:<port>/<subject>. Repeatable for fan-out.
--dlq <URL> unset Dead-letter queue for events that fail parsing or sink delivery. Same schemes as --output. When unset, failed events are logged and discarded.
--include-event off Embed the full event JSON in every detection match.
--pretty off Pretty-print JSON output.

Pipelines and dynamic sourcesπŸ”—

Flag Description
-p, --pipeline <PIPELINES> Processing pipeline(s) to apply. Builtin names (ecs_windows, sysmon) or YAML file paths. Repeatable.
--source <FILE_OR_DIR> External source file(s) or directory of source files. Repeatable. Loads dynamic source declarations independently of any pipeline file. A file path loads one YAML file with a top-level sources: block; a directory path loads all *.yml/*.yaml files in it, alphabetically. Source IDs must be unique across all --source files and all pipeline-embedded sources: blocks. See Dynamic Pipeline Sources.
--allow-remote-include Allow include: directives in pipelines to reference remote (HTTP/NATS) sources. Off by default for security.

Post-evaluation enrichmentπŸ”—

Flag Description
--enrichers <PATH> YAML file declaring post-evaluation enrichers. Hot-reloaded on SIGHUP, file-watcher changes, and POST /api/v1/reload; failed reloads keep the previous pipeline active. See Enrichers for the schema, the four primitives, and the recipes catalog.

The enrichers file accepts max_concurrent_enrichments: <N> at the top level (default 16) plus a list of enricher entries, each declaring kind: detection | correlation, a primitive type: (template / lookup / http / command), an inject_field, and primitive-specific keys (template, url / headers / cache_ttl, command, source / extract / default, ...). Cross-namespace template references are rejected at startup with a clear error pointing at the offending field.

API serverπŸ”—

Flag Default Description
--api-addr <ADDR> 0.0.0.0:9090 Bind address for /healthz, /readyz, /metrics, /api/v1/*, and (with the daemon-otlp feature) /v1/logs.

TLS (requires the daemon-tls build feature)πŸ”—

When TLS is configured, the daemon terminates TLS in-process for every protocol on --api-addr (HTTP REST API, /metrics, OTLP/HTTP, OTLP/gRPC). The negotiation advertises both h2 and http/1.1 via ALPN so legacy REST clients and modern gRPC clients share one socket.

Flag Env Default Description
--tls-cert <PATH> unset unset PEM-encoded leaf certificate (with any intermediates) for the API listener. Requires --tls-key.
--tls-key <PATH> unset unset PEM-encoded private key. PKCS#8, PKCS#1 (RSA), and SEC1 (EC) formats are accepted. Requires --tls-cert.
--tls-key-password <PASS> RSIGMA_TLS_KEY_PASSWORD unset Password for an encrypted --tls-key. Currently rejected at startup with a clear error; decrypt with openssl rsa -in key.pem -out key-decrypted.pem first.
--tls-client-ca <PATH> unset unset PEM bundle of trusted CA certificates used to verify inbound client certificates. Enables mutual TLS: clients without a cert signed by one of the listed CAs are rejected during the handshake.
--tls-min-version <1.2\|1.3> unset 1.3 Minimum TLS protocol version. Drop to 1.2 only for legacy agents that cannot negotiate TLS 1.3.
--allow-plaintext unset off Permit plaintext on a non-loopback --api-addr. Without this flag (and without --tls-cert/--tls-key) the daemon refuses to start on any public address. Loopback (127.0.0.0/8, ::1) always allows plaintext for local development.

Hot-reload: every reload trigger funnels through the daemon's central debounced reload task, so a single POST /api/v1/reload (cross-platform, including Windows), kill -HUP <pid> (Unix), or a YAML file change picked up by the file watcher rotates rules, pipelines, enrichers, and the TLS certificate in one pass. The active rustls::ServerConfig is swapped atomically via Arc<ArcSwap<…>>, so new handshakes pick up the rotated material without dropping inflight TLS connections. Failed reloads keep the previous certificate active, bump rsigma_reloads_failed_total, and log an error so a typo in the cert path cannot black-hole the listener.

Observability: the /metrics endpoint exposes rsigma_tls_certificate_expiry_seconds (signed; negative once the cert has expired) and rsigma_tls_active_connections. A single WARN is logged at startup (and after every reload) if the active certificate expires within 30 days.

See TLS deployment for a deeper dive, including ACME / sidecar reverse proxy alternatives that this feature replaces.

Correlation behaviorπŸ”—

Flag Default Description
--suppress <DURATION> unset Suppress duplicate correlation alerts within the window (5m, 1h, 30s).
--action <ACTION> alert Post-fire action: alert (keep state, re-alert on next match) or reset (clear window state).
--no-detections off Suppress detection output for correlation-only base rules.
--correlation-event-mode <MODE> none none, full (deflate-compressed full bodies), refs (timestamp + ID only).
--max-correlation-events <N> 10 Cap on stored events per correlation window.
--timestamp-field <FIELD> unset Field name to prepend to the timestamp extraction list. Repeatable.
--timestamp-fallback <MODE> wallclock Behavior when no timestamp is found: wallclock (use wall clock time) or skip (skip correlation state for that event). Use skip for forensic replay.

State persistenceπŸ”—

Flag Default Description
--state-db <PATH> unset SQLite database for persisting correlation state across restarts. When set, state is loaded on startup and saved periodically and on shutdown.
--state-save-interval <SECONDS> 30 Periodic snapshot interval. No effect without --state-db.
--clear-state off Clear stored state on startup. With --replay-from-*, forces a clean slate even if the replay starts after the stored position.
--keep-state off Force restore stored state even during replay. Use for forward catch-up where you want to preserve cross-boundary correlation windows. Mutually exclusive with --clear-state.

ThroughputπŸ”—

Flag Default Description
--buffer-size <N> 10000 Bounded mpsc capacity for source→engine and engine→sink queues.
--batch-size <N> 1 Maximum events per engine lock acquisition. Raise to 64 or 128 under load to amortize mutex overhead.
--drain-timeout <SECONDS> 5 Seconds to wait for in-flight events to drain on shutdown.

NATS (requires the daemon-nats build feature)πŸ”—

Flag Env Description
--nats-creds <FILE> NATS_CREDS NATS credentials file (.creds) for JWT + NKey authentication.
--nats-token <TOKEN> NATS_TOKEN NATS authentication token.
--nats-user <USER> NATS_USER NATS username (requires --nats-password).
--nats-password <PASS> NATS_PASSWORD NATS password (requires --nats-user).
--nats-nkey <SEED> NATS_NKEY NATS NKey seed.
--nats-tls-cert <FILE> unset TLS client certificate for mutual TLS with NATS.
--nats-tls-key <FILE> unset TLS client private key for mutual TLS with NATS.
--nats-require-tls off Refuse to connect to a NATS server that does not negotiate TLS.
--replay-from-sequence <SEQ> unset Replay from a specific JetStream sequence number.
--replay-from-time <TIMESTAMP> unset Replay from a wall-clock time (ISO 8601: 2026-05-15T10:00:00Z).
--replay-from-latest off Start from the last existing message in the stream, then deliver new ones.
--consumer-group <NAME> RSIGMA_CONSUMER_GROUP Consumer group name for JetStream load balancing across daemon instances.

The auth methods are mutually exclusive. See NATS Streaming for the full operational guide.

Performance (advanced)πŸ”—

Flag Default Description
--bloom-prefilter off Enable per-field bloom over positive substring needles. See Performance Tuning.
--bloom-max-bytes <BYTES> 1048576 Memory budget for the bloom index (1 MiB default). No effect without --bloom-prefilter.
--cross-rule-ac off Enable cross-rule Aho-Corasick. Available with the daachorse-index build feature. See Performance Tuning.

ExamplesπŸ”—

Minimal daemon: stdin β†’ stdoutπŸ”—

rsigma engine daemon -r rules/

Reads NDJSON from stdin, writes detections to stdout. Default API on 0.0.0.0:9090.

HTTP ingest with persistent stateπŸ”—

rsigma engine daemon -r rules/ \
    --input http \
    --state-db /var/lib/rsigma/state.db \
    --pipeline ecs_windows

Accepts POST /api/v1/events for ingest; correlation state survives restarts.

NATS source + sink + DLQπŸ”—

NATS_CREDS=/etc/rsigma/nats.creds \
rsigma engine daemon -r /etc/rsigma/rules/ \
    --input "nats://nats.internal:4222/events.>" \
    --output "nats://nats.internal:4222/detections" \
    --dlq "file:///var/log/rsigma/dlq.ndjson" \
    --state-db /var/lib/rsigma/state.db \
    --buffer-size 50000 \
    --batch-size 128 \
    --drain-timeout 30 \
    --nats-require-tls \
    --api-addr 0.0.0.0:9090

Multi-output fan-outπŸ”—

rsigma engine daemon -r rules/ \
    --output stdout \
    --output "file:///var/log/rsigma/detections.ndjson" \
    --output "nats://nats.internal:4222/detections.urgent"

HTTPS with mutual TLSπŸ”—

rsigma engine daemon -r rules/ \
    --input http \
    --api-addr 0.0.0.0:9090 \
    --tls-cert /etc/rsigma/tls/server.crt \
    --tls-key  /etc/rsigma/tls/server.key \
    --tls-client-ca /etc/rsigma/tls/clients-ca.crt

Clients connecting to https://daemon:9090/v1/logs (OTLP/HTTP) or https://daemon:9090/api/v1/events (REST) must present a certificate signed by clients-ca.crt or the handshake is rejected. Rotate the server cert with cp new.crt /etc/rsigma/tls/server.crt && kill -HUP $(pidof rsigma) on Unix, or cp new.crt … && curl -X POST https://daemon:9090/api/v1/reload on any platform (including Windows, where SIGHUP does not exist).

Forensic replay from a NATS sequenceπŸ”—

rsigma engine daemon -r rules/ \
    --input "nats://localhost:4222/events.>" \
    --replay-from-sequence 1001 \
    --state-db /var/lib/rsigma/replay-state.db \
    --timestamp-fallback skip

--timestamp-fallback skip prevents wall-clock contamination of correlation windows when replaying old events.

Health and readinessπŸ”—

Endpoint Returns Probe wiring
/healthz 200 once the listener is up. Liveness probe.
/readyz 200 once rules + pipelines are loaded; 503 during startup or after a failed reload. Readiness probe. Drain traffic when 503.
/metrics Prometheus text format. ~20 metrics at startup; up to 27 once dynamic sources and OTLP fire. Scrape every 15-30 s.

Full HTTP API reference: HTTP API. All metric definitions: Prometheus metrics.

ShutdownπŸ”—

SIGTERM and SIGINT trigger a graceful drain bounded by --drain-timeout. In-flight events are processed and acknowledged before the daemon exits. With --state-db, the final correlation state snapshot is written during shutdown.

Exit codesπŸ”—

Code Meaning
0 Normal shutdown.
2 Rules path could not be read at startup.
3 Configuration error: bad -p, malformed --suppress, invalid --input URL, etc.

See alsoπŸ”—