Skip to content

Wazuh: SIEM Architecture, Agents & Detection Rules

Deploy Wazuh as a real detection layer — manager and indexer architecture, fleet-wide agents, and rules tuned to your own environment.

Wazuh ManagerWazuh IndexerWazuh AgentFilebeat
RR

Ranjith R

Linux SysAdmin & Cloud Engineer

Published April 18, 2026Updated June 20, 2026
8 min readAdvanced#Wazuh#SIEM#Security Monitoring#Detection
Share
Section 01

Introduction

Wazuh is an open-source security platform that unifies host-based intrusion detection (HIDS), log analysis, file integrity monitoring (FIM), vulnerability detection, and SIEM-style correlation and alerting into a single agent/manager architecture. It began as a fork of OSSEC and has since grown into a full stack: lightweight agents on every monitored host, a manager that decodes and correlates events against rules, an OpenSearch-based indexer for storage and search, and a dashboard for visualizing alerts.

This guide treats Wazuh the way a production security team actually runs it: not just “install the agent and look at a dashboard,” but understanding the decoder → rule → alert pipeline well enough to write your own detections, tune out noise, and trace a real attack (SSH brute forcing) end-to-end from raw log line to a dashboard alert.

Who this is for

  • DevOps/SysAdmin engineers adding detection capability to a fleet of servers.
  • Anyone who has run a SIEM concept in theory but never built the manager, indexer, and agent pipeline by hand.
  • Security-conscious teams who want alerting that maps to MITRE ATT&CK, not just raw logs.
Section 02

Prerequisites

You should have the following before deploying the stack in this guide:

  • A Linux host (Ubuntu 22.04/RHEL 9 recommended) with at least 4 vCPU / 8 GB RAM for the manager + indexer + dashboard (all-in-one), or separate hosts for a distributed install.
  • Root or sudo access on the manager host and every host you intend to monitor.
  • Basic familiarity with systemd, YAML, and reading XML configuration files.
  • Outbound access from monitored hosts to the manager on TCP 1514 (event data) and 1515 (agent enrollment).
  • Docker and Docker Compose installed if you plan to follow the containerized install path.

Sizing matters

The Wazuh indexer is an OpenSearch cluster under the hood — it is the most resource-hungry component. Undersized indexer nodes are the number one cause of a “working” Wazuh install that silently stops ingesting alerts under load.
Section 03

Theory

What a SIEM/HIDS actually does

At its core, a SIEM (Security Information and Event Management) platform does three things: collect logs and telemetry from many sources, normalize and correlate that data against known-bad patterns, and alert a human when something matches. A HIDS (Host-based Intrusion Detection System) narrows that scope to a single host: it watches log files, the filesystem, running processes, and configuration state for signs of compromise. Wazuh is both — agents provide the HIDS layer per host, and the manager/indexer/dashboard provide the SIEM layer across the whole fleet.

The decode → rule → alert pipeline

Every raw log line the manager receives goes through the same pipeline inside wazuh-analysisd:

  1. Decoding — a decoder (defined in XML) recognizes the log format (e.g. sshd, sudo, iptables) and extracts structured fields like srcip, user, and action from the free-text line.
  2. Rule matching— decoded fields are tested against a tree of rules. Rules can match on a single event (e.g. “failed password”) or on frequency/correlationacross multiple events (e.g. “8 failed passwords from the same IP within 120 seconds”).
  3. Alerting — a matched rule has a level (0-16, severity) attached. If the level clears the configured threshold, an alert is written to alerts.json/alerts.log on the manager and shipped to the indexer for the dashboard to display.

Rule levels, at a glance

LevelMeaning
0Ignored — informational, no alert generated
1-6Low severity — noise-prone, often just logged
7-11Medium/high severity — actionable alerts (auth failures, policy violations)
12-15High severity — likely active compromise indicators
16Critical — reserved for the most severe, high-confidence detections

MITRE ATT&CK mapping

Wazuh's default ruleset tags many rules with MITRE ATT&CK technique IDs (e.g. T1110 for brute force, T1098for account manipulation). This lets an analyst pivot from “I got an alert” straight to “this maps to the Credential Access tactic” without manually cross-referencing the framework, and lets you build dashboard visualizations grouped by tactic instead of by raw rule ID.

Section 04

Architecture

A production Wazuh deployment has four moving parts. Agents run on every monitored endpoint and forward events over an encrypted channel to the manager. The manager decodes, correlates, and writes alerts, then hands them to Filebeat, which ships them to the indexer. The dashboard queries the indexer to render everything an analyst sees.

Agents → Wazuh Manager (analysisd) → Filebeat → Wazuh Indexer (OpenSearch) → Wazuh Dashboard

Component responsibilities

ComponentRole
Wazuh AgentRuns on the monitored host; collects logs, monitors file integrity, and runs rootcheck/SCA checks
Wazuh ManagerReceives agent events, decodes and matches them against rules, generates alerts, manages agent enrollment and keys
FilebeatShips the manager's alert and archive JSON output into the indexer using the Wazuh Filebeat module
Wazuh IndexerAn OpenSearch cluster that stores and indexes alerts for fast search and aggregation
Wazuh DashboardAn OpenSearch Dashboards build with Wazuh-specific plugins for browsing alerts, agents, and compliance views

Single-node vs. distributed

For labs and small fleets, all four components can live on one host (the “all in one” install). Past a few hundred agents, split the indexer onto its own cluster of nodes — it is the component most sensitive to disk I/O and heap pressure.
Section 05

Installation

Wazuh ships an official quickstart script for small/all-in-one deployments, and a Docker Compose stack for distributed or disposable lab environments.

terminal
# Download and run the official install assistant
curl -sO https://packages.wazuh.com/4.9/wazuh-install.sh
sudo bash wazuh-install.sh -a

# The script installs and configures, in order:
#   1. Wazuh indexer   (OpenSearch-based)
#   2. Wazuh manager   (+ Filebeat for shipping alerts)
#   3. Wazuh dashboard (OpenSearch Dashboards)
#
# On completion it prints the generated admin password — save it immediately:
sudo tar -xvf wazuh-install-files.tar

# Verify all three services are active
sudo systemctl status wazuh-manager wazuh-indexer wazuh-dashboard

vm.max_map_count before you start the indexer

OpenSearch refuses to boot unless the host kernel allows enough memory-mapped areas. Set this before bringing up the indexer container/service — see the Troubleshooting section for the exact fix.
Section 06

Configuration

Manager: ossec.conf essentials

The manager's behavior — which log sources to trust, active response, and global alert thresholds — lives in /var/ossec/etc/ossec.conf.

/var/ossec/etc/ossec.conf (manager, excerpt)
<ossec_config>
  <global>
    <jsonout_output>yes</jsonout_output>
    <alerts_log>yes</alerts_log>
    <logall>no</logall>
    <email_notification>no</email_notification>
  </global>

  <alerts>
    <log_alert_level>3</log_alert_level>
    <email_alert_level>12</email_alert_level>
  </alerts>

  <remote>
    <connection>secure</connection>
    <port>1514</port>
    <protocol>tcp</protocol>
  </remote>

  <!-- Vulnerability detection module -->
  <vulnerability-detector>
    <enabled>yes</enabled>
    <interval>5m</interval>
    <run_on_start>yes</run_on_start>
  </vulnerability-detector>

  <ruleset>
    <decoder_dir>ruleset/decoders</decoder_dir>
    <rule_dir>ruleset/rules</rule_dir>
    <rule_dir>etc/rules</rule_dir>
    <list>etc/lists/audit-keys</list>
  </ruleset>
</ossec_config>

Agent: ossec.conf essentials

Each agent's /var/ossec/etc/ossec.conf defines the manager address and which local log files and integrity paths to watch.

/var/ossec/etc/ossec.conf (agent, excerpt)
<ossec_config>
  <client>
    <server>
      <address>10.0.0.10</address>
      <port>1514</port>
      <protocol>tcp</protocol>
    </server>
    <enrollment>
      <enabled>yes</enabled>
      <manager_address>10.0.0.10</manager_address>
      <port>1515</port>
    </enrollment>
  </client>

  <localfile>
    <log_format>syslog</log_format>
    <location>/var/log/auth.log</location>
  </localfile>

  <localfile>
    <log_format>syslog</log_format>
    <location>/var/log/nginx/access.log</location>
  </localfile>

  <syscheck>
    <frequency>43200</frequency>
    <directories check_all="yes" realtime="yes">/etc,/usr/bin,/usr/sbin</directories>
    <ignore>/etc/mtab</ignore>
  </syscheck>

  <rootcheck>
    <disabled>no</disabled>
  </rootcheck>
</ossec_config>

Registering an agent

Agent registration issues a unique key that both sides use to authenticate the encrypted channel. This can be done manually on the manager or automatically via wazuh-authd enrollment (used by the agent's <enrollment> block above).

terminal (on manager)
# Manual registration
sudo /var/ossec/bin/manage_agents -a
# -> prompts for agent name and IP, then issues an ID

# Extract the key for a given agent ID to import on the agent
sudo /var/ossec/bin/manage_agents -e 003

# List all registered agents and their connection status
sudo /var/ossec/bin/agent_control -l

Agent groups

Assign agents to groups (e.g. webservers, db-tier) via agent_groups -a -i <id> -g webservers so shared configuration (specific localfileblocks, syscheck paths) can be pushed centrally instead of hand-editing every agent's ossec.conf.
Section 07

Commands

wazuh-control — service lifecycle

terminal
sudo /var/ossec/bin/wazuh-control start
sudo /var/ossec/bin/wazuh-control stop
sudo /var/ossec/bin/wazuh-control restart
sudo /var/ossec/bin/wazuh-control status

# Or via systemd (preferred on both manager and agent)
sudo systemctl restart wazuh-manager
sudo systemctl restart wazuh-agent

manage_agents — key lifecycle on the manager

terminal
sudo /var/ossec/bin/manage_agents -a          # add a new agent
sudo /var/ossec/bin/manage_agents -l          # list agents
sudo /var/ossec/bin/manage_agents -e <id>     # export/print the agent key
sudo /var/ossec/bin/manage_agents -r <id>     # remove an agent

Agent enrollment from the agent side

terminal (on agent)
# Enroll using authd against the manager (fetches a key automatically)
sudo /var/ossec/bin/agent-auth -m 10.0.0.10

# Import a key generated manually on the manager instead
sudo /var/ossec/bin/manage_agents -i <base64-key-string>

# Restart the agent to pick up the new key
sudo systemctl restart wazuh-agent

agent_control — status and force actions from the manager

terminal (on manager)
sudo /var/ossec/bin/agent_control -l               # list agents + status
sudo /var/ossec/bin/agent_control -i <id>           # detailed info for one agent
sudo /var/ossec/bin/agent_control -R -u <id>        # force-restart an agent remotely
Section 08

Examples

The default ruleset (rule IDs roughly 1-99999) covers common software out of the box. Custom, environment-specific detections belong in /var/ossec/etc/rules/local_rules.xml using an ID range above 100000 so they never collide with vendor rule updates.

  1. Identify the log source and confirm it's decoded

    Tail /var/ossec/logs/archives/archives.json (requires logall_json yes) to confirm the raw event arrives and which decoder matched it — you need the decoded field names before you can write a rule against them.
  2. Draft the rule against a known decoder

    Choose a parent rule to inherit from (e.g. group "sudo"), then match on a specific field like full_log using a regex, keeping the rule as narrow as possible.
  3. Write it into local_rules.xml

    Custom rules always live in local_rules.xml, never in the vendor ruleset files — those get overwritten on upgrade.
  4. Validate and reload

    Run /var/ossec/bin/wazuh-logtest against a sample log line to confirm the rule fires at the intended level, then systemctl restart wazuh-manager.

Example: alert when a user is added to the sudoers group

/var/ossec/etc/rules/local_rules.xml
<group name="local,sudoers_change,">
  <rule id="100010" level="10">
    <if_sid>5902</if_sid>
    <match>usermod.*-aG sudo|usermod.*-aG wheel</match>
    <description>User added to sudo/wheel group</description>
    <mitre>
      <id>T1098</id>
    </mitre>
    <group>privilege_escalation,gdpr_IV_32.2,</group>
  </rule>
</group>

Rule 100010 extends base rule 5902 (the generic usermoddecoder match), narrows it with a regex on the command line, sets severity to level 10 (high), and tags it with the MITRE ATT&CK privilege escalation technique so it surfaces correctly in dashboard MITRE visualizations.

Section 09

Screenshots

Wazuh Dashboard — Security Events view, showing alert volume by severity and top triggered rules

Screenshot placeholder

Wazuh Dashboard — Agents view, showing per-agent connection status, OS, and last keep-alive

Screenshot placeholder

Section 10

Real World Example

Scenario: an internet-facing jump host is being brute-forced over SSH. Walk the full path from the raw auth log line to a dashboard alert.

SSH auth.log → agent logcollector → manager analysisd → correlated rule → indexer → dashboard

  1. Attacker generates failed logins

    Each failed attempt writes a line like Failed password for root from 203.0.113.7 port 51422 ssh2 to /var/log/auth.log (Debian/Ubuntu) or /var/log/secure (RHEL).
  2. Agent collects and forwards

    The agent's <localfile> block for that path is tailed by wazuh-logcollector and shipped to the manager over the encrypted 1514/tcp channel in near real time.
  3. Decoding and per-event matching

    The built-in sshd decoder extracts srcip and user. A single failed attempt matches rule 5710 (“sshd authentication failed”, level 5) — on its own, too low to page anyone.
  4. Frequency correlation escalates it

    Rule 5720(“multiple authentication failures”) extends 5710 with a <frequency> / <timeframe> clause: 8 matches of the same rule group from the same srcip within 120 seconds. When that threshold trips, the manager fires a level-10 correlated alert instead of eight separate low-level ones.
  5. Alert written and shipped

    analysisd writes the alert to alerts.json with the full decoded context (source IP, rule ID, MITRE tag T1110, agent name). Filebeat's Wazuh module picks up new lines and bulk-indexes them into the indexer within seconds.
  6. Analyst sees it on the dashboard

    The Security Events view surfaces the level-10 alert immediately; an analyst pivots on srcip to see every other rule that IP has triggered fleet-wide, and can trigger an active response (e.g. firewall-drop) to block it automatically.
Troubleshooting

Common Issues

Agent shows 'Disconnected' in the dashboard

Check the agent's connection to the manager first with /var/ossec/bin/agent_control -i <id> on the manager, then confirm the agent process is actually running (systemctl status wazuh-agent) and that TCP 1514 is reachable — a stale or mismatched agent key after a manager reinstall is the most common cause.

Wazuh indexer fails to start: vm.max_map_count too low

OpenSearch requires a higher virtual memory map count than the Linux default. Fix it with sudo sysctl -w vm.max_map_count=262144 and persist it by adding vm.max_map_count=262144 to /etc/sysctl.conf, then restart the indexer service.

Self-signed certificate errors between manager/indexer/dashboard

The installer generates its own CA and node certificates under /etc/wazuh-indexer/certs and /etc/filebeat/certs. If any component was reinstalled independently, its certs no longer chain to the shared CA — regenerate all certificates from the same CA using the Wazuh certs tool rather than patching one node in isolation.

Custom rule never triggers

Almost always a decoder mismatch: the rule's <if_sid> points at a parent rule that never actually matched the log line. Run /var/ossec/bin/wazuh-logtest with the exact raw log line to see which decoder and rule chain really fires before assuming your regex is wrong.

Dashboard login or API authentication failures

The dashboard authenticates against the indexer, and the manager's REST API (port 55000) uses separate credentials from the indexer's admin account. Confirm you're resetting the right password with the correct tool — wazuh-passwords-tool for indexer/dashboard users vs. /var/ossec/bin/wazuh-apid user management for the manager API.
Best Practices

Best Practices

  • Keep every custom rule and decoder in local_rules.xml/local_decoder.xml — never edit the shipped ruleset, which is overwritten on upgrade.
  • Use agent groups to centrally manage configuration for classes of hosts instead of hand-editing each agent's ossec.conf.
  • Start new custom rules at a low level, confirm they fire correctly with real traffic, then raise the level once you trust the signal.
  • Size the indexer for your alert volume up front — heap pressure and disk I/O on the indexer are the most common cause of dropped or delayed alerts at scale.
  • Build MITRE ATT&CK-based dashboard visualizations, not just per-rule counts, so triage maps directly to attacker tactics.
Security

Security Hardening

  • File Integrity Monitoring — enable syscheck with realtime on sensitive paths (/etc, binaries directories) so unauthorized changes generate an immediate alert.
  • Tune, don't disable — a noisy rule usually needs a frequency/timeframe adjustment or a narrower match, not <rule ... level="0">; disabling it blind to your environment can mask a real detection.
  • Manager-agent TLS — enrollment keys are unique per agent; rotate and revoke keys for decommissioned hosts immediately with manage_agents -r rather than leaving stale registrations active.
  • Restrict dashboard/API access — put the dashboard behind a VPN or reverse proxy with its own auth layer, and scope manager API (55000/tcp) accounts to read-only where the caller doesn't need write access.
  • Active response, cautiously — automated actions like firewall-drop are powerful but can self-inflict outages on a false positive; pilot new active response rules in alert-only mode before letting them execute.
Interview Questions

Interview Questions

The Wazuh agent runs on monitored endpoints and forwards logs/FIM/rootcheck data. The Wazuh manager decodes events, runs them through the rule engine, and generates alerts. Filebeat ships those alerts to the Wazuh indexer, an OpenSearch cluster that stores and indexes them. The Wazuh dashboard, built on OpenSearch Dashboards, queries the indexer to visualize alerts and agent status.
Cheat Sheet

Cheat Sheet

wazuh-cheatsheet.sh
# --- Service control ---
sudo systemctl start|stop|restart|status wazuh-manager
sudo systemctl start|stop|restart|status wazuh-agent
sudo /var/ossec/bin/wazuh-control status

# --- Agent management (on manager) ---
sudo /var/ossec/bin/manage_agents -a            # add agent
sudo /var/ossec/bin/manage_agents -l            # list agents
sudo /var/ossec/bin/manage_agents -e <id>       # export agent key
sudo /var/ossec/bin/manage_agents -r <id>       # remove agent
sudo /var/ossec/bin/agent_control -l            # list + status
sudo /var/ossec/bin/agent_control -i <id>       # agent detail

# --- Agent enrollment (on agent) ---
sudo /var/ossec/bin/agent-auth -m <manager_ip>
sudo /var/ossec/bin/manage_agents -i <key>

# --- Rule/decoder testing ---
sudo /var/ossec/bin/wazuh-logtest

# --- Logs ---
tail -f /var/ossec/logs/ossec.log
tail -f /var/ossec/logs/alerts/alerts.json

# --- Indexer prerequisite ---
sudo sysctl -w vm.max_map_count=262144

# --- Config reload ---
sudo systemctl restart wazuh-manager
Summary

Summary

Wazuh turns a fleet of otherwise-unrelated servers into a single detection surface: agents collect, the manager decodes and correlates against tunable rules, the OpenSearch-based indexer stores it all searchably, and the dashboard makes it visible. The real skill isn't installing the stack — it's understanding the decoder → rule → alert pipeline well enough to write narrow, MITRE-mapped custom rules in local_rules.xml, tune out noise instead of disabling coverage, and trace an alert like an SSH brute-force detection all the way back to the raw log line that triggered it.

Resources

Resources

  • Official Wazuh documentation — documentation.wazuh.com
  • Wazuh source code and rulesets on GitHub — github.com
  • OpenSearch documentation (underlying the indexer/dashboard) — opensearch.org
  • MITRE ATT&CK framework reference — attack.mitre.org
  • Wazuh community forum — wazuh.com/community