Get started — add Cernity to your Suricata sensor
Goal of this guide: you already run a Suricata sensor. By the end of this page you’ll have Cernity turning its telemetry into security findings and delivering them to your SIEM. Every step is copy-paste, and each one ends with a quick “did it work?” check.
You don’t need to understand the internals to follow this — if you want them, read how-it-works.md. If you just want it running, start here.
YOUR SENSOR ONE NEW HOST (Cernity) YOUR SIEM
---------- -------------------- ---------
Suricata ─ eve logs ─► shipper ─► bus ─► detectors ─► findings ─► (Splunk,
(you have this) (you add both of these, one command each) Elastic,
Devo, …)
You add two things: the Cernity central stack (on any spare Docker host) and a tiny shipper on the sensor. Then you point Cernity at your SIEM. That’s the whole job.
Before you start
You need:
- A Suricata sensor you can edit the config on and restart (you have this).
- One Docker host for Cernity — a VM/LXC/box with Docker + Docker Compose v2, ~4 CPU / 8 GB RAM to start, reachable from the sensor on TCP 19092 (the bus’s external listener). This is not the sensor — keep the heavy analytics off the sensor.
- Your SIEM’s connection details (endpoint + credentials). Cernity ships to Elasticsearch/OpenSearch, Splunk, Devo, syslog/CEF, or a webhook.
- Git + this repo checked out on the Cernity host:
git clone https://github.com/cernity/cernityndr.git && cd cernityndr cp cernity.env.example .env # every setting has a working default
Throughout, CENTRAL_HOST = the IP/hostname of your Cernity host.
Step 1 — Stand up the Cernity central stack
On the Cernity host, first tell the bus this host’s reachable address so the remote
sensor can connect — edit .env and set:
CERNITY_ADVERTISE_HOST=CENTRAL_HOST # this host's LAN IP or DNS name
The bus uses SASL/SCRAM-SHA-512 with authorization enforced by default — an
unauthenticated or unauthorized client is refused. There are three separate credentials so
a compromised sensor can’t forge findings: a produce-only sensor credential (distributed to
sensors, scoped to suricata.*), and central-only pipeline + admin credentials. Generate
the CA, broker cert, and all three:
CERNITY_ADVERTISE_HOST=CENTRAL_HOST ./deploy/security/gen-bus-certs.sh
It prints the CERNITY_BUS_* values to add to .env (all three on the central host; only the
produce-only CERNITY_BUS_USER/CERNITY_BUS_PASSWORD + the ca.crt go to each sensor in
Step 3). For a throwaway single-host demo, set CERNITY_INSECURE_BUS=1 and
CERNITY_BUS_CENTRAL_MECHANISM= (empty) — no auth on either listener, warns loudly, never on
an untrusted network.
Then bring it up. Pass --env-file .env so your bus credentials load — when you invoke
Compose with -f deploy/central/..., it does not auto-load a repo-root .env, and secure
mode needs the three CERNITY_BUS_* credentials (you’ll see a clear ... required in secure mode error if one is missing):
docker compose --env-file .env -f deploy/central/docker-compose.yml up -d
That starts the bus (Redpanda), the detectors, finding-service, and
findings-forwarder. Give it ~30 seconds.
Check it worked:
docker compose -f deploy/central/docker-compose.yml ps
All services should show Up (Redpanda shows Up (healthy)). If anything is restarting,
see Troubleshooting.
By default findings are written to a local file (the
filesink) so you can verify the pipeline before wiring your SIEM. You’ll switch that to your SIEM in Step 4.
Step 2 — Configure your Suricata to feed Cernity
Cernity reads Suricata’s EVE telemetry. Suricata needs two things: split its EVE
output into an alerts file and a network-telemetry file, and turn on
community-id. Add this to your suricata.yaml under outputs::
outputs:
- eve-log:
enabled: yes
filename: eve-alerts.json # signature alerts
community-id: true
types:
- alert
- eve-log:
enabled: yes
filename: eve-nsm.json # network telemetry (the detectors' fuel)
community-id: true
types:
- flow
- dns: { version: 3 }
- tls: { extended: yes }
- http: { extended: yes }
- ssh
- files
- anomaly
Then restart Suricata and confirm both files are being written:
sudo systemctl restart suricata # or however you run it
ls -la /var/log/suricata/eve-alerts.json /var/log/suricata/eve-nsm.json
Both should exist and be growing.
This is the minimum. To get the most out of Cernity — nDPI application/risk detection, JA3/JA4 fingerprints, file hashing — follow the full, copy-paste best-results config in suricata-config.md. You can do that later; the minimum above is enough to start seeing findings.
Step 3 — Run the shipper on the sensor
The shipper is a tiny Fluent Bit container that tails those two EVE files and forwards them to Cernity. It runs on the sensor (it’s the one piece that must be where the logs are) and uses almost nothing.
First copy the ca.crt generated in Step 1 from the Cernity host to this sensor. Then, on
the sensor, from a checkout of this repo (the shipper authenticates to the secure bus with
the SCRAM credential + CA):
REDPANDA_BOOTSTRAP=CENTRAL_HOST:19092 \
SURICATA_LOG_DIR=/var/log/suricata \
CERNITY_BUS_USER=cernity-sensor \
CERNITY_BUS_PASSWORD=<from Step 1> \
CERNITY_BUS_CA=/path/to/ca.crt \
docker compose -f deploy/sensor/docker-compose.yml up -d
(Only if the central host runs with CERNITY_INSECURE_BUS=1: skip the CA/creds and remove the
rdkafka.sasl.*/ssl.* lines from deploy/fluent-bit/fluent-bit.conf so the shipper connects
plaintext.)
(Replace CENTRAL_HOST with your Cernity host. If your EVE files live elsewhere, set
SURICATA_EVE_ALERTS / SURICATA_EVE_NSM — see deploy-sensor.md.)
Check it worked — on the sensor:
docker logs cernity-fluent-bit 2>&1 | tail -5
You want to see it tailing the files and forwarding, with no connection errors to
CENTRAL_HOST:19092. If it can’t connect, the Cernity host’s firewall is blocking 19092,
or CERNITY_ADVERTISE_HOST isn’t set to an address the sensor can reach.
Step 4 — Connect Cernity to your SIEM
By default Cernity writes findings to a file. Now point it at your SIEM. On the Cernity
host, edit .env and set the sink. Pick your SIEM:
Elasticsearch / OpenSearch
CERNITY_SINK=elasticsearch
ES_ENDPOINT=https://your-es:9200
ES_USER=elastic
ES_PASSWORD=your-password
ES_INDEX_PREFIX=ndr-findings
Splunk (HTTP Event Collector)
CERNITY_SINK=splunk
SPLUNK_HEC_URL=https://your-splunk:8088/services/collector
SPLUNK_HEC_TOKEN=your-hec-token
Syslog / CEF (QRadar, ArcSight, most on-prem SIEMs)
CERNITY_SINK=syslog
SYSLOG_HOST=your-siem
SYSLOG_PORT=514
Webhook (Slack, ticketing, custom)
CERNITY_SINK=webhook
WEBHOOK_URL=https://your-endpoint/hook
(Devo and multi-SIEM fan-out — set CERNITY_SINK to a comma list — are in
siem-integrations.md.)
Then re-create just the forwarder so it picks up the new sink:
docker compose -f deploy/central/docker-compose.yml up -d findings-forwarder
Check it worked:
docker logs cernity-findings-forwarder 2>&1 | tail -5
You want a line like indexed N finding(s) -> ... (or your sink’s equivalent), and no
auth/connection errors.
Step 5 — Verify the whole pipeline end to end
Findings appear when Suricata sees something worth flagging. To confirm the pipeline without waiting for real traffic, replay the built-in beacon fixture on the Cernity host:
docker compose -f deploy/quickstart/docker-compose.yml up -d eve-feeder
Within ~a minute a beacon / C2 finding should reach your SIEM (or, if you’re still on the
file sink, read it directly):
docker compose -f deploy/central/docker-compose.yml exec findings-forwarder \
cat /out/findings.jsonl
If you see a finding with "category": "c2" and "state": "FINAL", you’re done —
Cernity is live: your sensor’s telemetry is becoming findings and landing in your SIEM.
Troubleshooting
| Symptom | Likely cause / fix |
|---|---|
| A central service keeps restarting | docker compose -f deploy/central/docker-compose.yml logs <svc> — usually a missing .env value (e.g. an unset CLICKHOUSE_PASSWORD while ClickHouse is enabled; leave it empty to run without ClickHouse). |
Shipper can’t reach CENTRAL_HOST:19092 | Open TCP 19092 on the Cernity host’s firewall, and set CERNITY_ADVERTISE_HOST to a name/IP the sensor can reach; confirm REDPANDA_BOOTSTRAP points at the right host. The port is auth+TLS by default — it should refuse unauthenticated clients. |
| Shipper connects but the bus rejects it (auth/TLS errors) | The secure bus needs the SCRAM creds + CA on the sensor: CERNITY_BUS_USER/CERNITY_BUS_PASSWORD (from gen-bus-certs.sh) and CERNITY_BUS_CA pointing at the ca.crt copied from the central host. The cert’s SAN must include CERNITY_ADVERTISE_HOST. |
| No findings arrive | Confirm both EVE files are growing (Step 2), the shipper shows no errors (Step 3), and finding-service logs show FINAL lines: docker compose -f deploy/central/docker-compose.yml logs finding-service. |
| SIEM shows nothing | Check findings-forwarder logs for auth/endpoint errors (Step 4); verify the credentials and that the index/HEC token exists. |
Next steps
- Get more detections: apply the full Suricata best-results config (nDPI, JA3/JA4, file hashing) — each unlocks more detectors.
- Richer findings: turn on enrichment — GeoIP/ASN, reverse DNS, domain age, IP reputation.
- Grow past one sensor: the scale guide covers many sensors and splitting Cernity across hosts.
- Understand what you built: how-it-works.md and how Cernity completes Suricata into an NDR.