To use the Wazuh agent, install it on each host you want to watch, enroll it with your Wazuh server, and put it in a group. Then manage what it collects from the server through that group's shared agent.conf file. Check its health with agent_control on the server and its own ossec.log.
Think of the agent as a field reporter on each machine: it watches that one host and phones every finding back to the newsroom, the Wazuh server, which decides what becomes an alert. Your job is to tell each reporter what to watch, and to notice when one stops calling in.
Our getting-started guide to Wazuh covers installing the server and enrolling a first agent. This guide picks up where that one stops: how to run agents across many machines without editing each one by hand, and how to fix the ones that go quiet.
What does the Wazuh agent actually do?
The Wazuh agent is a small program that collects security data on one host and sends it, encrypted, to the Wazuh server for analysis. It runs on Linux, Windows, and macOS. It does very little thinking itself: decoding and rule matching happen on the server. That split is why one server can watch hundreds of hosts.
The agent is really a bundle of modules, each watching one kind of thing. You turn them on and tune them in configuration, which is most of what "using the agent" means day to day.
| Module | What it watches | Typical use |
|---|---|---|
| Log collection | Log files and, on Windows, the event channels | Failed logins, web server errors, application logs |
| File integrity monitoring (FIM) | Changes to files and directories you list | A modified /etc/passwd or a new file in a web root |
| Security configuration assessment (SCA) | System settings, checked against policies such as CIS benchmarks | Finding weak SSH or password settings |
| System inventory | Installed packages, open ports, running processes | Feeding vulnerability detection on the server |
| Active response | Nothing; it runs scripts the server tells it to | Blocking an IP after a brute-force rule fires |
Step 1: create a group on the server
A group is a named set of agents that share one configuration. Create the group before you install any agents, so each new agent can land in it on day one. On the Wazuh server, use the agent_groups tool:
$ sudo /var/ossec/bin/agent_groups -a -g webservers -q $ sudo /var/ossec/bin/agent_groups -l
The first command creates a group called webservers (-q skips the confirmation prompt). The second lists every group. New agents land in a group called default unless you name another one at enrollment.
Step 2: install the agent and enroll it into the group
Enrollment is how the agent and the server agree on an ID and a secret key. You can do it at install time by passing deployment variables. On a Debian or Ubuntu host with the Wazuh package repository already added:
$ sudo WAZUH_MANAGER="10.0.0.2" WAZUH_AGENT_NAME="web-01" WAZUH_AGENT_GROUP="webservers" apt-get install wazuh-agent $ sudo systemctl daemon-reload $ sudo systemctl enable --now wazuh-agent
Replace 10.0.0.2 with your server's address. The agent enrolls over TCP port 1515, then sends its events over TCP port 1514. Both ports must be open from the host to the server.
Step 3: confirm the agent is connected
Check from both ends, because each one tells you something different. On the agent, read its state file. On the server, list every agent with agent_control.
$ sudo grep ^status /var/ossec/var/run/wazuh-agentd.state status='connected'
$ sudo /var/ossec/bin/agent_control -l Wazuh agent_control. List of available agents: ID: 000, Name: wazuh-server (server), IP: 127.0.0.1, Active/Local ID: 002, Name: web-01, IP: any, Active
Note the ID, here 002. You will use it in the commands below. Agent 000 is the server itself.
Where do the agent's settings live?
An agent reads two files: its own local ossec.conf, and a shared agent.conf pushed from the server for each group it belongs to. The local file is read first, then the shared one, so when the same setting appears in both, agent.conf wins. For lists such as monitored log files, the entries from both are combined.
On the server, each group's shared file lives at /var/ossec/etc/shared/<group>/agent.conf. With each keepalive, every 10 seconds by default, the agent sends a checksum of its shared files. If it differs from the server's copy, the server pushes the new version. According to the Wazuh centralized configuration documentation, the agent then reloads it without a manual restart.
The practical rule: put anything that should be the same on many hosts in a group's agent.conf, and keep ossec.conf for the few things specific to one machine, such as the server address. Editing ossec.conf by hand on fifty servers does not scale, and it drifts.
Worked example: watch nginx access logs on every web server
Here is the scenario. You run nginx on several web servers, and you want an alert when someone scans for files that do not exist, such as old backups. Every one of those hosts is in the webservers group. You will add the log once, on the server, and every agent in the group picks it up.
First, write the change to a temporary file and validate it. A broken shared file reaches every agent in the group, so check it before it goes live.
<agent_config> <localfile> <location>/var/log/nginx/access.log</location> <log_format>syslog</log_format> </localfile> </agent_config>
$ sudo /var/ossec/bin/verify-agent-conf -f /var/ossec/etc/shared/webservers/agent.conf.tmp $ sudo mv /var/ossec/etc/shared/webservers/agent.conf.tmp /var/ossec/etc/shared/webservers/agent.conf $ sudo chown wazuh:wazuh /var/ossec/etc/shared/webservers/agent.conf
The chown matters because the server reads the file as the wazuh user. Give it a few seconds, then confirm agent 002 has the new version:
$ sudo /var/ossec/bin/agent_groups -S -i 002 Agent '002' is synchronized.
Now prove the server will turn a line from that log into an alert. Take a real 404 line from the access log and paste it into wazuh-logtest on the server (sudo /var/ossec/bin/wazuh-logtest):
203.0.113.50 - - [05/Nov/2026:10:14:02 +0000] "GET /backup.zip HTTP/1.1" 404 153 "-" "Mozilla/5.0" **Phase 2: Completed decoding. name: 'web-accesslog' id: '404' protocol: 'GET' srcip: '203.0.113.50' url: '/backup.zip' **Phase 3: Completed filtering (rules). id: '31101' level: '5' description: 'Web server 400 error code.' **Alert to be generated.
The built-in web access decoder pulled out the source IP, the URL, and the status code. Rule 31101 fired at level 5. One 404 is noise, which is why level 5 is low. The useful part comes next: the stock ruleset also includes rule 31151, which fires at level 10 when the same source IP produces 14 of these errors within 90 seconds. That is the signature of a scanner walking a wordlist, and you got it without writing a single rule. All it took was getting the log to the server.
Why is my agent "Never connected" or "Disconnected"?
Almost always, the agent cannot reach the server, or the server does not recognize it. "Never connected" means the agent never finished its first handshake. "Disconnected" means it was working and then stopped reporting. Start with the agent's own log at /var/ossec/logs/ossec.log (on Windows, C:\Program Files (x86)\ossec-agent\ossec.log), then test the ports from the agent:
$ nc -zv 10.0.0.2 1514 $ nc -zv 10.0.0.2 1515 $ sudo grep -iE "error|warn" /var/ossec/logs/ossec.log | tail -20
| What you see | Likely cause | Fix |
|---|---|---|
nc times out on 1514 or 1515 | A firewall or security group blocks the port | Allow outbound TCP 1514 and 1515 from the agent to the server |
Invalid agent name or Duplicate agent name in the agent log | Another enrolled host already uses this name | Give the host a unique name, or set one with WAZUH_AGENT_NAME |
Wrong key or corrupt payload in the server log | The agent's key does not match the server's record | Remove the stale agent on the server and re-enroll this one |
Invalid password in the agent log | Enrollment password is on and missing or wrong | Set the same password on both sides |
| Was Active, now Disconnected | Agent service stopped, host down, or network path changed | Check systemctl status wazuh-agent, then the ports |
One cause deserves its own warning: cloned machines. If you build a VM image with an enrolled agent baked in, every clone ships with the same ID and key. The server sees several hosts claiming one identity and rejects them. Install the agent in the image, but enroll at first boot.
Where the agent breaks (the honest limits)
-
The group file silently overrides local edits. Someone changes a setting in
ossec.confon a host, it does nothing, and nobody knows why. The same setting lives inagent.conf, which is read last. When a local change has no effect, check the group file first. -
It sees only what you point it at. An agent with the default settings does not know about your custom app's log file. Coverage gaps are configuration gaps, and the server cannot alert on a log it never received. It also collects and runs response scripts rather than blocking at the kernel; we covered that line in using Wazuh as an EDR.
-
Enrollment is open unless you close it. Anyone who can reach port 1515 can enroll an agent unless you turn on password or certificate verification. Restrict that port to your own networks, and enable a password for anything internet-facing.
-
A quiet agent looks like a quiet host. No alerts from a host can mean nothing happened, or that the agent died. Watch for Disconnected agents as an alert in itself; our Wazuh API guide shows how to list every agent that stopped reporting.
Where Suriq fits
Everything above is standard, open-source Wazuh that you can run yourself. If you would rather not operate the central stack, Suriq runs it for you as a managed service, with tuned detections and alerts mapped to MITRE ATT&CK, so the server-side work in this guide is ours rather than yours.