qasim@wiki:~$
Security

Wazuh SIEM

Architecture, agent deployment, rule tuning, OpenSearch cluster management, and the custom Python alert-routing framework I built on top of it.

● Ready

Overview

Wazuh is the SIEM I run in production — not just administered, but engineered. A SIEM is a pipeline, not a single product: agents collect, the manager decodes and correlates, the indexer stores, the dashboard is where humans hunt, and alert routing is where detection becomes action. The stage most teams under-invest in is the last one — an alert nobody sees doesn't exist.

SIEM pipeline: agents, manager, indexer, dashboard, alert routing
The full pipeline, as deployed in production.

Architecture

ComponentRoleWhat I tune
AgentsCollect events from every endpointAgent grouping, policy management, FIM scope
ManagerDecode, match rules, correlateCustom local rules, MITRE ATT&CK mapping, false-positive suppression
IndexerStore and make searchable (OpenSearch)Shard allocation, index templates, lifecycle policies
DashboardVisualize, hunt, investigateSaved searches, alert views
Alert routingNotify the right team, fastCustom Python framework — dedup, team routing, deep links

Configuration Reference

Manager health & diagnostics — first commands in any incident

sudo systemctl status wazuh-manager
sudo tail -f /var/ossec/logs/ossec.log
sudo /var/ossec/bin/agent_control -l          # list agents and connection state

Test a detection rule without waiting for a real event

sudo /var/ossec/bin/wazuh-logtest
# paste a sample log line, e.g.:
#   Failed password for root from 203.0.113.50 port 22 ssh2
# output shows: which decoder parsed it, which rule fired, and the alert level

OpenSearch cluster — the layer underneath the SIEM

# cluster health at a glance
curl -sk -u admin:PASS https://localhost:9200/_cluster/health?pretty

# per-index size and doc counts
curl -sk -u admin:PASS https://localhost:9200/_cat/indices/wazuh-alerts-*?v

# shard distribution — the exact thing that broke and taught me this
curl -sk -u admin:PASS https://localhost:9200/_cat/shards?v | head
Real incident: shard exhaustion Our Wazuh deployment stopped indexing alerts — the SIEM effectively went blind. Root cause: OpenSearch hit its cluster.max_shards_per_node ceiling, from months of daily indices each carrying more primary shards than the workload needed. Immediate fix raised the limit to restore visibility; the permanent fix reduced primary shards per index and added lifecycle-based deletion of old indices so it can't happen again.
curl -sk -u admin:PASS -X PUT https://localhost:9200/_cluster/settings \
  -H 'Content-Type: application/json' \
  -d '{"persistent":{"cluster.max_shards_per_node":1500}}'

The alert-routing layer (custom Python framework)

Wazuh's built-in integrations are a starting point; production needs more: team-based routing by agent group, deduplication so one noisy rule doesn't page fifty times, severity-gated escalation to PagerDuty, and HTML email notifications that deep-link straight to the exact alert in the dashboard. Core shape of the router:

# simplified shape of the routing logic
def route_alert(alert):
    if is_duplicate(alert, window_minutes=15):
        return  # suppressed — already notified for this root cause

    team = TEAM_MAP.get(alert["agent"]["group"], "default")
    severity = alert["rule"]["level"]

    if severity >= 12:
        pagerduty.trigger(alert, team=team)
    email.send(
        to=TEAM_EMAILS[team],
        subject=f"[{severity}] {alert['rule']['description']}",
        body=render_html_template(alert, dashboard_deeplink(alert["id"]))
    )

Real Project: SIEM Engineering at Constellation

Beyond keeping the SIEM online, the meaningful work was making it usable: custom detection rules tuned against false positives, File Integrity Monitoring, vulnerability detection and Security Configuration Assessment, MITRE ATT&CK-aligned reporting — and the Python alert framework above, which turned "go look through a dashboard" into "click the link in the email and land on the exact alert." Investigation time dropped accordingly.

Related Topics

🎥
Video walkthrough — coming soon
Live rule tuning, wazuh-logtest demo, and the Python router in action