Wazuh is an open-source SIEM and XDR. It monitors endpoints, detects threats, fires alerts, and maps everything to MITRE ATT&CK. This guide gets you from zero to a working deployment. No theory dumps. No enterprise fluff. Just the commands that work.
Tested on Ubuntu 22.04 with Wazuh 4.7+. The installer handles OpenSearch, the manager, and the dashboard. One script, three components, production-ready in under an hour.
Step 1: Server Preparation
Run this on a fresh Ubuntu 22.04 machine. 8 GB RAM minimum, 4 vCPU. Don't co-locate this with anything else. The indexer's JVM will fight for memory.
Two things I learned the hard way: swap and timezone. OpenSearch runs on a JVM, and the JVM wants locked heap memory. If swap is enabled, the kernel can page out the heap, and the JVM crashes with an error message that tells you absolutely nothing about swap. Disable it first. Timezone matters because every alert timestamp will be wrong otherwise, and debugging timestamp mismatches between the agent, manager, and dashboard at 2 AM is not how you want to spend your night.
sudo apt update && sudo apt upgrade -y
sudo hostnamectl set-hostname wazuh-server
# Wazuh components need these
sudo apt install -y curl wget gnupg apt-transport-https lsb-release
# Set timezone
sudo timedatectl set-timezone Asia/Jakarta
# Disable swap (indexer JVM requirement)
sudo swapoff -a
sudo sed -i '/ swap / s/^/#/' /etc/fstab
Step 2: Download the Installer
Wazuh ships an all-in-one installation assistant. It generates certificates, configures the indexer cluster, installs the manager, and deploys the dashboard. All from one script and one config file.
sudo su
cd ~
# Download the latest installer and config template
curl -sO https://packages.wazuh.com/4.7/wazuh-install.sh
curl -sO https://packages.wazuh.com/4.7/config.yml
Step 3: Edit config.yml
The config file tells the installer which components go where. For a single-server deployment, use the same IP for all three. The installer reads this, generates certificates with correct SANs, and provisions each component.
nodes:
indexer:
- name: node-1
ip: 192.168.1.10
server:
- name: wazuh-1
ip: 192.168.1.10
dashboard:
- name: dashboard
ip: 192.168.1.10
Replace 192.168.1.10 with your server's IP. For multi-node deployments, add more entries under each section.
Step 4: Generate Certificates & Passwords
This step creates all the PKI material the cluster needs. The output is a single tar file containing certificates, keys, and randomly generated passwords. Run this once, then copy the tar to other nodes if you're doing multi-server.
The password that comes out of this step is the only way into your dashboard. I've seen people run the script, ignore the password output, then spend 30 minutes grepping through files wondering why admin:admin doesn't work. Save it somewhere safe. You won't see it again unless you re-run the whole generation.
bash wazuh-install.sh --generate-config-files
# View the admin password
tar -axf wazuh-install-files.tar wazuh-install-files/wazuh-passwords.txt -O | grep -P "'admin'" -A 1
# Save this password. You'll need it for the dashboard login.
Step 5: Install the Indexer
The indexer is Wazuh's packaged OpenSearch. It stores alerts, events, and agent state. This step installs it on the node named node-1 in your config.yml.
Why start with the indexer? Because everything else depends on it. The manager writes to the indexer. The dashboard reads from the indexer. If the indexer isn't running when you install the other components, they'll install fine, then fail silently on first startup because they can't reach the backend. Install it first, start it, verify it, then move on.
bash wazuh-install.sh --wazuh-indexer node-1
Step 6: Initialize the Cluster
This starts the indexer cluster. Run it once, even on multi-node setups. The cluster handles node discovery internally after initialization.
bash wazuh-install.sh --start-cluster
# Verify the indexer is running
curl -k -u admin:YOUR_PASSWORD https://localhost:9200
# Expected: JSON response with cluster_name, version, tagline
Step 7: Install the Wazuh Server
The server is the brain: analysis engine, agent enrollment, rule processing. It receives data from agents on port 1514, runs decoders and rules, and ships alerts to the indexer.
At this point you have a working indexer but nothing feeding it. The server bridges that gap. Once installed, agents can start enrolling, and you'll see actual data flowing. But hold off on deploying agents until the dashboard is up. You want to see the full pipeline: agent → server → indexer → dashboard. Installing them in order makes debugging easier when something breaks.
bash wazuh-install.sh --wazuh-server wazuh-1
Step 8: Install the Dashboard
The web interface. Agent management, rule editing, threat hunting, MITRE ATT&CK mapping, all from a browser. Default port 443.
bash wazuh-install.sh --wazuh-dashboard dashboard
# After install, access https://YOUR_IP
# Login: admin / password from step 4
Step 9: Deploy an Agent (Linux)
The agent is what watches your endpoints. It collects logs, checks file integrity, scans for vulnerabilities, and sends everything to the manager. Install it on every machine you want to monitor.
The Wazuh agent is surprisingly lightweight. I've run it on Raspberry Pis, old office desktops, and cloud VMs with 1 GB RAM. The most common issue people hit: agent installs fine, service starts, but never appears in the dashboard. Nine times out of ten, it's a firewall. Port 1514 needs to be open from the agent to the manager. Don't waste time checking logs before verifying connectivity.
# On the target machine (not the Wazuh server)
curl -s https://packages.wazuh.com/key/GPG-KEY-WAZUH | gpg --no-default-keyring --keyring gnupg-ring:/usr/share/keyrings/wazuh.gpg --import
chmod 644 /usr/share/keyrings/wazuh.gpg
echo "deb [signed-by=/usr/share/keyrings/wazuh.gpg] https://packages.wazuh.com/4.x/apt/ stable main" | sudo tee /etc/apt/sources.list.d/wazuh.list
sudo apt update
# Replace 192.168.1.10 with your Wazuh manager IP
WAZUH_MANAGER="192.168.1.10" sudo apt install -y wazuh-agent
sudo systemctl daemon-reload
sudo systemctl enable wazuh-agent
sudo systemctl start wazuh-agent
Step 10: Deploy an Agent (Windows)
# Download the MSI (check https://packages.wazuh.com/4.x/windows/ for latest)
Invoke-WebRequest -Uri https://packages.wazuh.com/4.x/windows/wazuh-agent-4.7.5-1.msi -OutFile wazuh-agent.msi
# Replace 192.168.1.10 with your manager IP
Start-Process msiexec -ArgumentList "/i wazuh-agent.msi /qn WAZUH_MANAGER=192.168.1.10 WAZUH_REGISTRATION_SERVER=192.168.1.10" -Wait
Start-Service WazuhSvc
Step 11: Verify Everything
Log into the dashboard. Go to Agents. Your newly installed agent should appear within 30 seconds. If it doesn't:
# 1. Agent can reach the manager?
nc -zv 192.168.1.10 1514
# 2. Manager has the agent registered?
sudo cat /var/ossec/etc/client.keys | wc -l
# 3. Manager logs showing errors?
sudo tail -50 /var/ossec/logs/ossec.log
# 4. Firewall allowing agent traffic?
sudo ufw status | grep 1514
# 5. Agent service actually running?
sudo systemctl status wazuh-agent
What You Have Now
A functioning SIEM. 3,000+ built-in detection rules. File integrity monitoring. Vulnerability scanning. MITRE ATT&CK mapping. All from one server, one script, no licensing costs.
The out-of-the-box ruleset is broad but generic. You'll get SSH brute force alerts, Windows Event Log anomalies, basic FIM. What you won't get: custom web shell detection, WordPress scan correlation, or HAProxy JSON log parsing. That's where custom rules and decoders come in. But the foundation is there, and it took you under an hour.
Next: tune the rules, set up Slack or Telegram alerts, deploy agents to production endpoints. If you're building a full SOC, the open-source SOC platform guide covers Graylog, Grafana, Shuffle, IRIS, and MISP. For custom detection logic, the custom rules and decoders tutorial builds on what you just deployed. But that's for another session.
References
Wazuh Documentation. documentation.wazuh.com
Wazuh Quickstart. documentation.wazuh.com/quickstart