Introduction
Wazuh is an open-source SIEM and host-based intrusion detection platform that scales from a handful of servers to tens of thousands of endpoints. Its strength is breadth: the same manager handles Linux servers, Windows workstations, FreeBSD appliances, LXC containers, and Docker sidecars through a unified agent protocol. This article covers the full deployment spectrum — from package installation and ossec.conf tuning to Puppet-automated mass enrollment and agent health monitoring.
Agent Architecture and Communication
The Wazuh deployment model has three components: the manager, the indexer (OpenSearch), and the dashboard (OpenSearch Dashboards). Agents communicate with the manager over two TCP ports:
- TCP 1514 — agent event data (syslog-format messages, file integrity alerts, rootcheck results)
- TCP 1515 — agent registration (used once during enrollment to exchange keys)
After registration, agents authenticate using a shared key derived during enrollment. All traffic is encrypted with AES-256. The manager never initiates outbound connections to agents — agents are always the initiating side, making this architecture firewall-friendly in environments where outbound-only rules are the norm.
Each agent maintains a local queue (/var/ossec/queue/) and buffers events if the manager is temporarily unreachable. The default queue capacity is 16,384 events; once full, events are dropped and a warning is logged locally. Sizing your manager to handle peak agent load is critical for avoiding queue overflow at scale.
Linux Deployment
Wazuh publishes packages for all major distributions via a signed APT/YUM repository. On a RHEL/CentOS system:
rpm --import https://packages.wazuh.com/key/GPG-KEY-WAZUH
cat > /etc/yum.repos.d/wazuh.repo << EOF
[wazuh]
gpgcheck=1
gpgkey=https://packages.wazuh.com/key/GPG-KEY-WAZUH
enabled=1
name=EL-\$releasever - Wazuh
baseurl=https://packages.wazuh.com/4.x/yum/
protect=1
EOF
yum install -y wazuh-agent
On Ubuntu/Debian:
curl -s https://packages.wazuh.com/key/GPG-KEY-WAZUH | apt-key add -
echo "deb https://packages.wazuh.com/4.x/apt/ stable main" \
> /etc/apt/sources.list.d/wazuh.list
apt-get update && apt-get install -y wazuh-agent
Configure the manager address before starting the agent. Edit /var/ossec/etc/ossec.conf:
<ossec_config>
<client>
<server>
<address>siem01.example-corp.com</address>
<port>1514</port>
<protocol>tcp</protocol>
</server>
<enrollment>
<enabled>yes</enabled>
<manager_address>siem01.example-corp.com</manager_address>
<port>1515</port>
</enrollment>
<notify_time>60</notify_time>
<time-reconnect>300</time-reconnect>
</client>
</ossec_config>
Register the agent and start the service:
WAZUH_MANAGER="siem01.example-corp.com" \
WAZUH_AGENT_NAME="$(hostname -s)" \
systemctl start wazuh-agent
systemctl enable wazuh-agent
Key ossec.conf tuning recommendations for Linux agents:
- Set
<log_format>syslog</log_format>for journald integration via/var/log/syslogor/var/log/messages - Enable file integrity monitoring (FIM) on critical paths:
/etc,/bin,/usr/bin,/usr/sbin - Tune
<frequency>in<syscheck>— default 43200 seconds (12 hours) is usually appropriate for production - Add
<ignore>entries for high-churn paths like/tmpand log rotation directories to reduce FIM noise
Windows Deployment
The Wazuh Windows agent is distributed as an MSI installer. For manual installation on a single host:
msiexec.exe /i wazuh-agent-4.x.x-1.msi /q `
WAZUH_MANAGER="siem01.example-corp.com" `
WAZUH_AGENT_NAME="$env:COMPUTERNAME" `
WAZUH_REGISTRATION_SERVER="siem01.example-corp.com"
NET START WazuhSvc
For enterprise fleet deployment, distribute via Group Policy Software Installation or SCCM. Create a GPO that runs the MSI with the correct WAZUH_MANAGER property during computer startup. Alternatively, use a PowerShell startup script:
# GPO startup script — deploy_wazuh.ps1
$MSI = "\\fileserver01.example-corp.com\Software\Wazuh\wazuh-agent-4.x.x-1.msi"
$Manager = "siem01.example-corp.com"
if (-not (Get-Service -Name WazuhSvc -ErrorAction SilentlyContinue)) {
Start-Process msiexec.exe -ArgumentList `
"/i `"$MSI`" /q WAZUH_MANAGER=`"$Manager`" WAZUH_AGENT_NAME=`"$env:COMPUTERNAME`"" `
-Wait -NoNewWindow
Start-Service WazuhSvc
}
Windows agent configuration is stored at C:\Program Files (x86)\ossec-agent\ossec.conf. Key additions for Windows environments:
- Enable Windows Event Log collection for Security, System, and Application channels
- Configure Security channel with
<query>filters to reduce volume from high-frequency events (4624, 4634 logon/logoff) - Enable rootcheck and vulnerability detection for Windows patch compliance visibility
FreeBSD and pfSense Deployment
FreeBSD has a Wazuh agent package in the ports tree. On a standard FreeBSD host:
pkg install wazuh-agent
On pfSense (which uses FreeBSD under the hood), package installation goes through the pfSense package manager GUI or pkg directly from the shell:
pkg add https://packages.wazuh.com/4.x/freebsd/14/wazuh-agent-4.x.x-1.txz
A critical FreeBSD quirk: the Wazuh agent on FreeBSD defaults to UDP for event transport rather than TCP. Ensure the manager has UDP 1514 open in addition to TCP 1514, or explicitly override the protocol in ossec.conf:
<server>
<address>siem01.example-corp.com</address>
<protocol>tcp</protocol>
</server>
Enable and start the agent service:
sysrc wazuh_agent_enable=YES
service wazuh-agent start
Container Deployment: LXC and Docker
For LXC containers managed by Proxmox or another LXC runtime, install the Wazuh agent inside the container using the same package repository method as the underlying OS. The agent inside an LXC container monitors that container’s filesystem and logs independently, giving you per-container visibility without the overhead of privileged access from the host.
For Docker containers, the recommended pattern is a sidecar container that shares the monitored container’s log volumes:
version: "3.8"
services:
app:
image: example-corp.com/app:latest
volumes:
- app-logs:/var/log/app
wazuh-agent:
image: wazuh/wazuh-agent:latest
environment:
- WAZUH_MANAGER=siem01.example-corp.com
- WAZUH_AGENT_NAME=docker-host01-app
volumes:
- app-logs:/monitored/app-logs:ro
- /var/lib/docker/containers:/monitored/docker-logs:ro
network_mode: host
pid: host
volumes:
app-logs:
The network_mode: host is required for the agent to communicate with the manager from inside the container without complex networking configuration. The pid: host enables process monitoring of the host’s process table. For read-only log volume mounts, use :ro to follow least-privilege principles.
Version Management
Keeping agents in sync with the manager version is important — minor version mismatches are usually tolerated, but major version gaps can cause protocol failures or missing features. Track agent versions in the Wazuh dashboard under Agents > Summary, or query via the API:
curl -u admin:admin -k \
"https://siem01.example-corp.com:55000/agents?select=name,version,status&limit=500" \
| jq '.data.affected_items[] | select(.version != "Wazuh v4.x.x")'
When upgrading the manager, upgrade agents within two weeks to avoid compatibility drift. Use the Wazuh manager’s built-in agent upgrade capability for Linux agents:
# Upgrade all Linux agents to the current manager version
curl -u admin:admin -k -X PUT \
"https://siem01.example-corp.com:55000/agents/upgrade" \
-H "Content-Type: application/json" \
-d '{"agents_list": "all", "filters": {"os.platform": "linux"}}'
Puppet and Ansible Automation for Mass Enrollment
At scale, manual agent deployment is impractical. Puppet and Ansible both have mature Wazuh integration. Using the official wazuh/wazuh Puppet module:
class { 'wazuh::agent':
wazuh_server_address => 'siem01.example-corp.com',
wazuh_server_port => 1514,
wazuh_server_protocol => 'tcp',
agent_name => $facts['networking']['hostname'],
enrollment_enabled => true,
}
Apply to all nodes by including the class in your site manifest or via an ENC node classification rule. The module handles package installation, configuration templating, service management, and re-enrollment when the manager address changes.
For Ansible, use the official Wazuh Ansible role:
- hosts: all_servers
become: true
roles:
- role: wazuh.wazuh_agent
wazuh_managers:
- address: siem01.example-corp.com
port: 1514
protocol: tcp
wazuh_agent_enrollment:
enabled: true
manager_address: siem01.example-corp.com
Monitoring Agent Health
Agent health falls into two categories: connectivity status and queue/performance health. Monitor both proactively.
Disconnected agents surface in the Wazuh dashboard and via the API. Set up a Wazuh alert rule to fire when an agent goes disconnected for more than 10 minutes:
<rule id="100100" level="7">
<if_sid>502</if_sid>
<match>Agent disconnected</match>
<description>Wazuh agent disconnected from manager.</description>
<group>wazuh_agent,</group>
</rule>
Queue flooding — where an agent generates more events than the manager can process — causes event drops and creates blind spots. Identify flooded agents by checking the agent’s internal statistics:
# On the agent host
cat /var/ossec/var/run/wazuh-agentd.state | grep -E "msg_count|recv_count|queue_size"
If queue_size approaches queue_limit consistently, tune the agent’s log collection rules to reduce volume — add ignore patterns for known high-frequency, low-value events, or increase the manager’s thread count in ossec.conf under <analysis_threads>.
Summary
Wazuh’s agent model is flexible enough to cover virtually every node type in a heterogeneous fleet, but each platform has its quirks: FreeBSD defaults to UDP, Windows needs Group Policy or SCCM for scale, Docker needs the sidecar pattern, and LXC is treated as a first-class Linux host. Automating enrollment with Puppet or Ansible eliminates the toil of manual key exchange and ensures new nodes are monitored from their first boot. Pairing this with proactive agent health monitoring — disconnection alerts and queue depth checks — closes the observability loop and ensures your SIEM coverage remains complete even as the fleet evolves.
