The stack

  • wazuh-manager — the rules engine. Receives events from agents, runs them through decoders + rules, emits alerts.
  • wazuh-indexer — an OpenSearch fork that stores events and alerts.
  • wazuh-dashboard — an OpenSearch Dashboards fork with Wazuh-specific UI panels.
  • wazuh-agent — the per-host binary that watches files, logs, processes, and audits, and ships data to the manager over TLS.

All-in-one install on Debian / Ubuntu

For a homelab or small deployment, Wazuh ships a single installer that puts all three server components on one box:

curl -sO https://packages.wazuh.com/4.9/wazuh-install.sh
sudo bash ./wazuh-install.sh -a

-a stands for "all-in-one." The script:

  1. Generates a self-signed root CA and node certs.
  2. Installs wazuh-indexer, wazuh-manager, wazuh-dashboard.
  3. Prints initial admin credentials (save these immediately).

Disk and RAM budget: 4 GB RAM minimum, 8 GB recommended; 50–100 GB disk for a small deployment. OpenSearch is the heavy part.

The dashboard is at https://<host>:443/ — log in with the printed admin password. Change it under Server Management → Users → admin → Edit.

Deploy an agent

From the dashboard: Agents → Deploy new agent → pick OS → copy the install command. For Linux:

# Generated by the dashboard with the server's address baked in
WAZUH_MANAGER='wazuh.lab.example.com' \
    apt install -y https://packages.wazuh.com/4.x/apt/pool/main/w/wazuh-agent/wazuh-agent_4.9.0-1_amd64.deb

systemctl daemon-reload
systemctl enable --now wazuh-agent

Within a minute the agent registers and appears in the dashboard with status Active. It starts shipping:

  • Real-time file changes from configured paths
  • Linux audit subsystem events
  • Logs from /var/log/auth.log, sshd, etc.
  • Periodic system inventory (packages, services, listening ports, users)

Decoders and rules

Wazuh's "rules" pattern-match against decoded events. The stack ships with thousands of curated rules for common services; custom ones live in /var/ossec/etc/rules/local_rules.xml:

<group name="local,syslog,sshd">
  <rule id="100001" level="10">
    <if_sid>5710</if_sid>     <!-- SSH login from unusual location -->
    <srcip>!192.168.0.0/16</srcip>
    <srcip>!10.0.0.0/8</srcip>
    <description>SSH login from outside the LAN.</description>
  </rule>

  <rule id="100002" level="12">
    <if_sid>5712</if_sid>     <!-- SSH brute force -->
    <same_source_ip />
    <description>SSH brute force, 10 failures in 60s from same IP.</description>
  </rule>
</group>

Reload the manager with systemctl restart wazuh-manager, then watch alerts in the dashboard's Security Events tab.

File integrity monitoring (FIM)

FIM is the feature most people install Wazuh for. In /var/ossec/etc/shared/<group>/agent.conf (or per-agent override), declare paths to watch:

<syscheck>
  <directories check_all="yes" realtime="yes">/etc/</directories>
  <directories check_all="yes" realtime="yes">/usr/bin,/usr/sbin</directories>
  <directories check_all="yes" realtime="yes">/var/www/html</directories>

  <ignore>/etc/mtab</ignore>
  <ignore>/etc/.pwd.lock</ignore>
  <ignore type="sregex">.log$</ignore>
</syscheck>

Within seconds of any change in those directories, an alert appears in the dashboard with the user, process, command line, and the file's before/after hashes.

Vulnerability detection

The manager periodically downloads CVE feeds (Debian, Ubuntu, RHEL, Amazon Linux, Microsoft) and cross-references them with each agent's installed packages. Findings show up under Modules → Vulnerabilities with severity + a remediation link. No agent-side scanner; everything happens server-side by comparing inventory data against feeds.

Active response

For automated reactions, define a command and a rule that triggers it:

<!-- /var/ossec/etc/ossec.conf -->
<command>
  <name>firewall-drop</name>
  <executable>firewall-drop</executable>
  <timeout_allowed>yes</timeout_allowed>
</command>

<active-response>
  <command>firewall-drop</command>
  <location>local</location>
  <rules_id>100002</rules_id>       <!-- the brute-force rule above -->
  <timeout>1800</timeout>             <!-- block for 30 min -->
</active-response>

The agent runs the bundled firewall-drop script (iptables on Linux, netsh on Windows) to drop the offending IP for the timeout. Pair with CrowdSec (see that tutorial) for "Wazuh detects, CrowdSec enforces network-wide."

Policy compliance scans

Out of the box, Wazuh ships SCA (Security Configuration Assessment) policies for CIS benchmarks of common distros and apps. Each agent periodically runs the checks and reports per-control pass/fail. In the dashboard, the Security Configuration Assessment module shows per-host posture; useful for "is this server hardened to CIS Level 1?"

Cloud / Kubernetes / container support

  • The agent runs cleanly on containers via a sidecar; for K3s (see that tutorial) there's a Helm chart that deploys agents as a DaemonSet.
  • CloudWatch / GCP / Azure log sources can be ingested via the manager's cloud integrations.
  • Docker container events (start/stop/exec) are captured via the Docker listener module.

Backups

  • Manager config/var/ossec/etc/ (rules, decoders, certs, ossec.conf).
  • Manager state/var/ossec/queue/, /var/ossec/stats/.
  • Indexer data/var/lib/wazuh-indexer/. For long-term retention, snapshot to S3 via OpenSearch's snapshot API.
  • Dashboard config — mostly stored in the indexer, plus /etc/wazuh-dashboard/.

Noise tuning

A fresh Wazuh install is loud — expect hundreds to thousands of low-severity events per day per agent. Spend the first week skimming and adding tuning rules: ignore your own routine activity, raise the threshold on noisy non-actionable events, lower it for genuinely-meaningful ones. The shipped rule set is a starting point, not the destination.

Distributed deployment

The all-in-one is fine to start. For real production:

  • Separate the indexer (1-3 nodes), manager (1-2 nodes), and dashboard (load-balanced).
  • Cluster the manager with a worker tier for >200 agents.
  • Pair with Filebeat or Logstash if you have other log sources to ingest into the same indexer.