Security Stack

The lab's reason for existing: run real detection on real telemetry, end to end - and not drown in the noise that produces.

Why this stack

Detection is a career path I'm aiming at and it was core to my studies - so building the stack was the obvious thing to actually learn the software on, rather than read about it. The lab is the place I get my hands on the tools a real shop runs.

It is Wazuh, not ELK, for a blunt reason: hardware. I ran an ELK stack first and liked it - but this is one second-hand workstation that also does development and everyday work, and ELK was simply too heavy to sit on top of all that. In the early days, fighting ELK's resource appetite on top of everything else the box was doing was pure frustration. Wazuh gives me a SIEM, agent management, and a rule engine in a footprint the box can actually carry while still being useful for everything else. Suricata adds the network-IDS half cheaply. The whole design bends to one constraint - it has to earn its keep on hardware that is also doing three other jobs.

The pieces

Component Role
Wazuh SIEM - log/alert correlation, custom rules, agent management
Suricata Network IDS on the core server, feeds Wazuh
Endpoint agents On the server and client machines (workstation, laptop, Windows lab VM), reporting to Wazuh
Edge syslog The router ships logs to Wazuh with custom decoders/rules
Threat-intel feeds Public IOC feeds (e.g. abuse.ch) pulled into Wazuh CDB lists on a timer
Telegram bot (Hermes) Real-time push of high-severity (level 7+) alerts
Local LLM (Gemma gemma4:e4b) Tiered alert triage - an L1 classifier/escalator that runs overnight and escalates only what it cannot resolve to an L2 (Claude) review

At a glance

detection engineering · custom Wazuh rules
grep -c '<rule id' local_rules.xml
179
sed -n '/id="100533"/,+4p' local_rules.xml
<rule id="100533" level="0"> <if_sid>533</if_sid> <match>cloudflared|chrome|firefox|spotify|rsyslogd</match> <description>Ignored - known services, ephemeral UDP ports</description> </rule>
# 179 custom rules; the level-0 ones tune out benign noise so a level-7 ping means "look now"
host audit · STIG-based auditd, as code
ls roles/auditd/files/audit-rules/
30-stig.rules 31-privileged.rules 32-power-abuse.rules 41-containers.rules 42-injection.rules 43-module-load.rules 44-installers.rules 71-networking.rules 40-local.rules
cat roles/auditd/files/audit-rules/*.rules | grep -c '^-'
87 # rules, version-controlled, re-applied on every rebuild

Full mechanics - the telemetry pipeline, the local-LLM triage in depth, and three real gotchas (the Windows ACL trap, a suppression blind spot, and the router that scanned itself) →