
Open-source, self-hosted security pipeline for IT, AI and OT. Logs in. Evidence out.: OCSF normalization, 46 detection rules (MITRE/ATLAS/ICS-tagged), correlation, evidence packages, NIS2 drafts, rebuilt React console + GitHub Pages demo. Apache-2.0.
Logs in. Evidence out.
Open-source security pipeline for IT, AI and OT: raw logs to a verified incident and a draft NIS2 notification.
Project page and live demo · Quickstart · Console · Architecture · Status (SSOT)
Badges reflect the latest real run on
main, not a promise. Scorecard's remaining findings are accepted, documented trade-offs, not gaps; see SSOT.md §1.
FENGARDE connects security telemetry across IT, AI and OT to show what happened, who or what acted, what was affected, how the events relate, and what evidence supports the conclusion.
Built for the European industrial Mittelstand: open source, self-hosted, Apache-2.0, with a draft NIS2 incident-notification path, a deterministic German/English report generator, opt-in RBAC/MFA/audit-log/multi-tenancy for MSP-style deployments, an opt-in HA profile (live-kill-tested, not just wired), and AI triage that never leaves your network.
Logs are collected, normalized to one schema (OCSF), run through correlation rules over a sliding window, grouped into incidents with a causal graph and a hash-chained evidence package, and indexed in OpenSearch. Every service is independent and talks to the rest only through a message bus, so any piece can be scaled or replaced without rewriting the others.
OLLAMA_URL is set; otherwise a
labelled deterministic stub. Alert data is never piped through a third-party LLM
API, and the console names which engine actually ran. Verdict quality is poor in the two models measured (qwen2.5:3b 1 of 54 labelled alerts correct, qwen2.5:7b 7 of 54, mostly suspicious answers); see
eval/llm_triage/RESULTS.md.OpenSearch, not Elastic: no license asterisk on the storage engine (ADR 003). Worth knowing, but not a differentiator against Wazuh (its indexer is an OpenSearch fork too).
| Way | Needs | What you get |
|---|---|---|
| The project page | A browser | The real console on a recording of a lab run, with a replayable attack, the architecture, all 46 rules and four recorded walkthroughs. Static; writes stay in your browser (docs/console-demo.md says exactly what is real). |
make e2e | Python 3 | SSH brute-force to a real alert, idempotent under replay. No Docker, Redis or OpenSearch. |
make demo | Docker | The full live stack; a real brute-force alert appears in the console within about a minute. |
git clone https://github.com/supermhel/fengarde.git && cd fengarde
make preflight # doctor: checks vm.max_map_count, Docker RAM, free ports
make demo # docker compose up -- a real SSH brute-force alert appears
# in the dashboard within ~30-60s, no manual step
# open http://localhost:8080
No Docker on hand? The whole detection pipeline runs zero-infra:
make e2e # SSH brute-force -> real alert -> idempotent replay, no Docker/Redis/OpenSearch
bash tools/demo.sh # same test, narrated (Windows: powershell -File tools\demo.ps1)
What you're seeing: 10 failed logins from one IP within 60 seconds (SSH
Failed password or Windows EventID 4625 — both normalize to the same OCSF
Authentication event) trip
common_bruteforce.yml
(threshold: 10, window_seconds: 60, grouped by source IP), and the alert
lands in the dashboard's alert list, idempotent under redelivery.
Prerequisites: Docker Desktop or Docker Engine + Compose v2, ≥4 GB RAM
allocated to Docker; Linux, macOS, or Windows via WSL2 (Linux containers,
POSIX sh scripts). Python 3 only if you're contributing a parser — no
Docker needed for that (see Contributing).
vm.max_map_count raised firstsudo sysctl -w vm.max_map_count=262144
# persist across reboots:
echo 'vm.max_map_count=262144' | sudo tee /etc/sysctl.d/99-fengarde.conf
Without it, OpenSearch fails with a JVM crash, not a helpful error. Not
needed on macOS Docker Desktop (handled inside its VM). make preflight
checks this for you and prints the exact fix if anything's missing.
Other targets:
make test # full zero-infra contract test suite, no Docker needed
make up # start the stack detached
make down # stop the stack, remove volumes
make ha-up # opt-in: Redis Sentinel + 3-node OpenSearch HA (needs REDIS_PASSWORD)
make ha-down # stop the HA profile, remove its volumes