Linux Tutorials

Install Wazuh 5 on Ubuntu 26.04: New Cluster Architecture

When you’ve run Wazuh 4.x for a while, your hands know the drill: config in /var/ossec, a Filebeat service to babysit, agents on port 1514. Bring that muscle memory to Wazuh 5 and most checks come back empty. The manager has no /var/ossec, there is no Filebeat unit, and a new agent never touches 1514, because the 5.x line rebuilt the server side so even a single all-in-one box runs as a cluster node and ships events to the indexer itself.

Original content from computingforgeeks.com - post 178262

Below you’ll install Wazuh 5 on one Ubuntu 26.04 server with the official assistant, verify the cluster node and the indexer connector that replaced Filebeat, and enroll an agent with a token over 1517/TCP. It also connects a legacy 4.x agent and explains why leaving 4.x means a new indexer. If you’re staying on 4.x, our Wazuh 4.x all-in-one guide for Ubuntu 26.04 still covers it. Every step was tested on Ubuntu 26.04.1 LTS against Wazuh 5.0.0-rc1 in October 2026, and every output block comes from those lab VMs.

Comparing Wazuh 5 with Wazuh 4.x

Wazuh 5 moves the manager to /var/wazuh-manager, drops Filebeat for a built-in indexer connector, makes every server a cluster node, and gives new agents an HTTPS channel on 1517/TCP with token enrollment. The agent itself still lives in /var/ossec, which is why mixed fleets confuse people: the paths you knew are right on endpoints and wrong on the server. The table below is what we checked on the lab manager against a 4.x install:

ItemWazuh 4.xWazuh 5
Manager home/var/ossec/var/wazuh-manager (no /var/ossec on the manager)
Manager configetc/ossec.conf, root <ossec_config>etc/wazuh-manager.conf, root <wazuh_config>, schema-validated
Log shipping to the indexerFilebeat serviceIndexer connector inside the manager, <indexer> block
ClusterOptional, <disabled>yes</disabled> by defaultAlways on; <disabled> is rejected
Agent connection1514/TCP, enrollment on 1515/TCPHTTPS on 1517/TCP; 1514/1515 kept for 4.x agents
Agent enrollmentOptional shared password (authd.pass)Enrollment tokens from wazuh-manager-authd
Daemons and toolswazuh-remoted, wazuh-controlwazuh-manager-remoted, wazuh-manager-control
systemd unitwazuh-managerwazuh-manager (unchanged)
Generated passwordswazuh-install-files.tar/etc/wazuh/credentials.env
Event indiceswazuh-alerts-4.x-*wazuh-events-v5-*, wazuh-findings-v5-*, wazuh-states-*
Indexer baseOpenSearch 2.xOpenSearch 3.x

Two rows trip up 4.x admins first. The systemd unit is still plain wazuh-manager, so systemctl restart wazuh-manager works as before, but every daemon behind it now carries the wazuh-manager- prefix, and scripts that grep the process list for wazuh-remoted find nothing. The other is the index names: saved searches and alert rules built on wazuh-alerts-* point at an index that Wazuh 5 never creates.

Here is how the pieces sit on a single server once the assistant finishes. The dashboard (443), the manager API (55000) and the agent ports listen on all interfaces, while the indexer and the cluster port bind to 127.0.0.1:

Wazuh 5 all-in-one architecture diagram: web01 agent to wazuh-manager over HTTPS 1517, legacy 4.x agents over 1514 and 1515, manager indexer connector to wazuh-indexer on 9200, analyst to wazuh-dashboard on 443

On a one-box install the cluster block is still there, with the node named node01 and typed master. That costs nothing on a small deployment, and it means adding a worker later is a config change on a second server, not a rebuild of the first one.

Preparing the Ubuntu 26.04 server

An all-in-one install puts the indexer, the manager and the dashboard on one machine, and the indexer’s Java heap is what sets the floor. Wazuh’s quickstart asks for 4 vCPU, 8 GB of RAM and 50 GB of disk for up to 25 agents with 90 days of indexed data. On our test server the install itself used about 3 GB of disk, and RAM sat at 4.3 GiB with one agent connected, almost 3 GB of it the indexer. Before you start, check the server has:

  • Ubuntu 26.04 LTS, x86_64 or ARM64
  • 4 vCPU, 8 GB RAM, 50 GB disk as the floor
  • A static IP or DNS name agents will use
  • A sudo user and outbound HTTPS to Wazuh’s package servers
  • A second Linux machine to enroll as an agent

Treat those numbers as a lab floor. Our test VM ran on a 19 GB disk, which is fine for a day of testing but nowhere near 90 days of events. Disk grows with the number of agents and how long you keep events, so the quickstart’s own table goes to 8 vCPU, 16 GB and 100 GB for 26 to 50 agents, and 200 GB for 51 to 100. Past about 100 endpoints, split the indexer onto its own nodes rather than growing one VM. Pick the address now as well, because the installer writes the server’s hostname and IP into the certificate agents check during enrollment, and an enrollment token can only carry an address that certificate lists.

Ubuntu ships UFW inactive, so nothing is filtered until you turn it on. If you do, open SSH first so the enable step doesn’t cut your own session, then the dashboard and the 5.x agent port. Our UFW guide for Ubuntu 26.04 covers the rest of the tool:

sudo ufw allow 22/tcp
sudo ufw allow 443/tcp
sudo ufw allow 1517/tcp
sudo ufw --force enable

Check the rule list before you log out:

sudo ufw status numbered

Each port should appear twice, once for IPv4 and once for IPv6, and SSH must be among them or your next login fails.

Status: active

     To                         Action      From
     --                         ------      ----
[ 1] 22/tcp                     ALLOW IN    Anywhere
[ 2] 443/tcp                    ALLOW IN    Anywhere
[ 3] 1517/tcp                   ALLOW IN    Anywhere
[ 4] 22/tcp (v6)                ALLOW IN    Anywhere (v6)
[ 5] 443/tcp (v6)               ALLOW IN    Anywhere (v6)
[ 6] 1517/tcp (v6)              ALLOW IN    Anywhere (v6)             

Leave 1514 and 1515 closed unless you still have 4.x agents, because the manager listens on both by default and a closed firewall is the only thing keeping them private. The section on legacy agents opens them when you need them. Port 55000 (the manager API) only needs to be reachable from wherever you run API scripts, and 9200 never needs to leave the box on an all-in-one install.

Installing Wazuh 5 with the assistant

Wazuh’s installation assistant is one shell script that installs and wires the three components in order, generates the certificates and writes every password to a root-only file. Keep the version in a variable, detected from GitHub, so the download and the run always match. The 5.x packages currently come from Wazuh’s staging repository, which is why the URL points at packages-staging.xdrsiem.wazuh.info and the run passes -d pre-release. A lab or a test SIEM is the right home for this build, and production should wait for a general-availability release on Wazuh’s main package repository; when that lands, take the installer URL from the quickstart instead of this staging path. The Wazuh releases page shows the same tags if you would rather pick one by hand.

export WAZUH_VERSION=$(curl -s "https://api.github.com/repos/wazuh/wazuh/releases?per_page=30" | grep -o '"tag_name": *"v5[^"]*"' | head -1 | cut -d '"' -f 4 | sed 's/^v//')
echo "${WAZUH_VERSION}"

The API lists releases newest first, so the first v5 tag is the current 5.x build. On our run it printed:

5.0.0-rc1

Download the assistant for that version:

wget https://packages-staging.xdrsiem.wazuh.info/pre-release/5.x/installation-assistant/wazuh-install-${WAZUH_VERSION}.sh

Run it with -a for all components on this host and -id so it installs missing OS packages without asking. We wrapped it in time to see how long a small VM takes:

time sudo bash ./wazuh-install-${WAZUH_VERSION}.sh -a -id -d pre-release

On a 4 vCPU, 8 GB VM the run took 8 minutes 20 seconds. The order is worth reading, because it shows the indexer comes up and gets its security config before the manager is installed, and there is no Filebeat step anywhere:

27/10/2026 05:41:28 INFO: Starting Wazuh installation assistant. Wazuh version: 5.0.0
27/10/2026 05:41:28 INFO: Verbose logging redirected to /var/log/wazuh-install.log
27/10/2026 05:41:41 INFO: --- Dependencies ----
27/10/2026 05:41:41 INFO: Installing apt-transport-https.
27/10/2026 05:41:41 INFO: Another process is using APT. Waiting for it to release the lock. Next retry in 30 seconds (1/10)
27/10/2026 05:42:15 INFO: Verifying that your system meets the recommended minimum hardware requirements.
27/10/2026 05:42:18 INFO: --- Wazuh indexer ---
27/10/2026 05:42:18 INFO: Downloading wazuh_indexer package: wazuh-indexer_5.0.0-rc1_amd64.deb
27/10/2026 05:42:59 INFO: wazuh_indexer package downloaded successfully: /home/mary/wazuh-install-packages/wazuh-indexer_5.0.0-rc1_amd64.deb
27/10/2026 05:42:59 INFO: Starting Wazuh indexer installation.
27/10/2026 05:43:58 INFO: Wazuh indexer installation finished.
27/10/2026 05:43:58 INFO: Wazuh indexer post-install configuration finished.
27/10/2026 05:43:58 INFO: Starting service wazuh-indexer.
27/10/2026 05:44:24 INFO: wazuh-indexer service started.
27/10/2026 05:44:43 INFO: Wazuh indexer cluster security configuration initialized.
27/10/2026 05:44:43 INFO: --- Wazuh manager ---
27/10/2026 05:44:43 INFO: Downloading wazuh_manager package: wazuh-manager_5.0.0-rc1_amd64.deb
27/10/2026 05:44:52 INFO: wazuh_manager package downloaded successfully: /home/mary/wazuh-install-packages/wazuh-manager_5.0.0-rc1_amd64.deb
27/10/2026 05:44:52 INFO: Starting the Wazuh manager installation.
27/10/2026 05:47:26 INFO: Wazuh manager installation finished.
27/10/2026 05:47:26 INFO: Starting service wazuh-manager.
27/10/2026 05:47:38 INFO: wazuh-manager service started.
27/10/2026 05:47:38 INFO: --- Wazuh dashboard ---
27/10/2026 05:47:38 INFO: Downloading wazuh_dashboard package: wazuh-dashboard_5.0.0-rc1_amd64.deb
27/10/2026 05:47:51 INFO: wazuh_dashboard package downloaded successfully: /home/mary/wazuh-install-packages/wazuh-dashboard_5.0.0-rc1_amd64.deb
27/10/2026 05:47:51 INFO: Starting Wazuh dashboard installation.
27/10/2026 05:49:14 INFO: Wazuh dashboard installation finished.
27/10/2026 05:49:14 INFO: Starting service wazuh-dashboard.
27/10/2026 05:49:18 INFO: wazuh-dashboard service started.
27/10/2026 05:49:18 INFO: Initializing Wazuh dashboard web application.
27/10/2026 05:49:48 INFO: Wazuh dashboard web application initialized.
27/10/2026 05:49:48 INFO: --- Summary ---
27/10/2026 05:49:48 INFO: You can access the web interface https://192.168.1.142:443
27/10/2026 05:49:48 INFO:     User: admin (Wazuh dashboard login and Wazuh indexer administrator)
27/10/2026 05:49:48 INFO:     Password: to read it from the credentials file, run:
27/10/2026 05:49:48 INFO:         sudo grep '^WAZUH_INDEXER_ADMIN_PASSWORD=' /etc/wazuh/credentials.env | cut -d= -f2-
27/10/2026 05:49:48 INFO: The other users of the deployment are listed at the top of /etc/wazuh/credentials.env.
27/10/2026 05:49:48 INFO: Installation finished.

real	8m20.576s
user	2m20.967s
sys	1m29.827s

Cloud-init or unattended-upgrades holding APT on a fresh VM explains the lock line, and the assistant waits it out on its own. Unlike 4.x, the summary never prints the admin password. It points you at /etc/wazuh/credentials.env instead, which holds five generated passwords, so list the keys without printing the values.

sudo sed -E 's/=.*/=REDACTED/' /etc/wazuh/credentials.env

Read the header before you copy anything, because it explains which key belongs to which login. Only admin (dashboard and indexer) and wazuh (manager API) are accounts you log in with. The other three are service accounts the components use to talk to each other.

# Written by the Wazuh packages and tools. Editing a value here changes nothing.
# To change a password: wazuh-passwords-tool.sh -u <user>
# A host only holds the keys of the components installed on it.
#
#                 User           Key                                  Used for
# Logins:
#                 admin          WAZUH_INDEXER_ADMIN_PASSWORD         Wazuh dashboard (web UI) and Wazuh indexer API
#                 wazuh          WAZUH_MANAGER_API_PASSWORD           Wazuh server API (curl, scripts)
# Service accounts the components connect with, not logins:
#                 kibanaserver   WAZUH_INDEXER_KIBANASERVER_PASSWORD  dashboard to indexer
#                 wazuh-manager  WAZUH_INDEXER_MANAGER_PASSWORD       manager to indexer
#                 wazuh-wui      WAZUH_MANAGER_WUI_PASSWORD           dashboard to server API
#
WAZUH_INDEXER_ADMIN_PASSWORD=REDACTED
WAZUH_INDEXER_KIBANASERVER_PASSWORD=REDACTED
WAZUH_INDEXER_MANAGER_PASSWORD=REDACTED
WAZUH_MANAGER_API_PASSWORD=REDACTED
WAZUH_MANAGER_WUI_PASSWORD=REDACTED
# >>> end wazuh generated <<<

Copy those passwords into your password manager before you do anything else. Editing the file changes nothing, as its own header says, so password changes go through /usr/share/wazuh-indexer/tools/wazuh-passwords-tool.sh. Keep /etc/wazuh/ca too: it holds the root CA that signed every certificate in the deployment, and you need it to add a node or rebuild a cert later.

Checking the cluster node and indexer connector

Before touching agents, confirm the three services are up and the manager really is running as a cluster node, because a manager that failed its config validation stops quietly and agents then sit in “never connected”. Start with systemd:

systemctl list-units 'wazuh*' --all --no-pager

Three units, all running and enabled by the assistant. There is no fourth one for log shipping:

  UNIT                    LOAD   ACTIVE SUB     DESCRIPTION
  wazuh-dashboard.service loaded active running wazuh-dashboard
  wazuh-indexer.service   loaded active running wazuh-indexer
  wazuh-manager.service   loaded active running Wazuh manager

Ask the manager’s own control tool for its daemons. The names show the new prefix, and wazuh-manager-clusterd is in the list even though this is the only server:

sudo /var/wazuh-manager/bin/wazuh-manager-control status

Each daemon reports itself running. If wazuh-manager-remoted is missing here, nothing is listening for agents on 1514 or 1517, so this is the first command to run when the dashboard shows agents as disconnected.

wazuh-manager-clusterd is running...
wazuh-manager-modulesd is running...
wazuh-manager-remoted is running...
wazuh-manager-analysisd is running...
wazuh-manager-db is running...
wazuh-manager-authd is running...
wazuh-manager-apid is running...

Now look at the cluster itself with cluster_control, the same tool 4.x shipped, now under the new home:

sudo /var/wazuh-manager/bin/cluster_control -l

One node, the master, listening on loopback. A worker node added later shows up in this same list.

NAME    TYPE    VERSION  ADDRESS
node01  master  5.0.0    127.0.0.1  

Wazuh 5 validates the manager config against a schema, and the new wazuh-manager-conf tool can read single keys back with defaults applied. That’s handier than grepping the XML, because it shows what the daemons actually loaded:

sudo /var/wazuh-manager/bin/wazuh-manager-conf validate
sudo /var/wazuh-manager/bin/wazuh-manager-conf get cluster.node_type
sudo /var/wazuh-manager/bin/wazuh-manager-conf get indexer.hosts

validate is silent when the file is good, so the only output is the two values:

master
["https://127.0.0.1:9200"]

Behind that second value sits the indexer connector, the piece that replaced Filebeat. It’s a library loaded by the manager, not a separate service, and the assistant wrote its settings into the <indexer> block of /var/wazuh-manager/etc/wazuh-manager.conf.

sudo grep -A11 '<indexer>' /var/wazuh-manager/etc/wazuh-manager.conf

Notice what the block holds and what it doesn’t. It points at the local indexer and authenticates with a client certificate of its own (indexer-connector.pem and its key), so there is no password in the file to rotate.

  <indexer>
    <hosts>
      <host>https://127.0.0.1:9200</host>
    </hosts>
    <ssl>
      <certificate_authorities>
        <ca>etc/certs/root-ca.pem</ca>
      </certificate_authorities>
      <certificate>etc/certs/indexer-connector.pem</certificate>
      <key>etc/certs/indexer-connector-key.pem</key>
    </ssl>
  </indexer>

Wazuh’s indexer connector page notes one thing a 4.x admin would not expect. The connector buffers events in memory, and whatever is queued when the manager stops or restarts is discarded, so schedule manager restarts for quiet periods. The <indexer> block also lives in the manager’s own config file, which is local to each node, so a multi-node setup needs it edited on every node.

One terminal capture puts the whole server-side check on one screen: three units, the master node, the listening agent and cluster ports, and the missing Filebeat unit.

Wazuh 5 manager on Ubuntu 26.04 showing three services, cluster_control node01 master, listening ports 1514 1515 1516 1517 55000 and no filebeat unit

Read the port lines closely. 1516 (cluster) binds to 127.0.0.1 because there is no second node to talk to, while 1514, 1515 and 1517 bind to all interfaces. The legacy ports are open by default, so if you have no 4.x agents, your firewall is what keeps them closed.

Monitoring scripts ask the same question over HTTPS on 55000. Get a token with the wazuh user, then ask for cluster status:

API_PASS=$(sudo grep '^WAZUH_MANAGER_API_PASSWORD=' /etc/wazuh/credentials.env | cut -d= -f2-)
TOKEN=$(curl -sk -u "wazuh:${API_PASS}" -X POST "https://localhost:55000/security/user/authenticate?raw=true")
curl -sk -H "Authorization: Bearer ${TOKEN}" https://localhost:55000/cluster/status

A running cluster returns "running": "yes". If the call times out instead, look for wazuh-manager-apid in the control-tool output above, since that daemon serves the API.

{
    "data": {
        "running": "yes"
    },
    "error": 0
}

One habit to drop from 4.x scripts: /manager/info and /manager/status return 404 on the 5.x API, so health checks built on them break silently. The troubleshooting section shows the replacement calls.

Logging in to the Wazuh dashboard

Port 443 serves the dashboard with a certificate signed by the deployment’s own CA, so your browser warns about it until you import /etc/wazuh/ca/root-ca.pem or put a proper certificate in front. Read the admin password on the server:

sudo grep '^WAZUH_INDEXER_ADMIN_PASSWORD=' /etc/wazuh/credentials.env | cut -d= -f2-

Then open https://192.168.1.142 (your server’s address) and sign in as admin with that password:

Wazuh 5 dashboard login page served on port 443 from Ubuntu 26.04

Expect a slow first load: about 45 seconds on our 8 GB VM while the dashboard ran its health checks, so a spinner on an empty Overview page is normal for a fresh install. Once an agent has been reporting for a few minutes, the Overview fills in with agent status, findings by severity, MITRE ATT&CK tactics and the CIS benchmark score for each endpoint.

Wazuh 5 overview dashboard with one active agent, findings by severity, MITRE ATT&CK tactics and configuration assessment

We took that screenshot after the agent in the next section had run for about fifteen minutes. The 51.9% CIS Ubuntu Linux 26.04 score is a stock cloud image, and the 3,778 file integrity entries are the agent’s first baseline of /etc and the system binaries.

Enrolling a Wazuh 5 agent with a token

Wazuh 5 agents enroll with a token instead of the optional shared authd.pass password. The token carries the manager’s address and a pin of its CA, so the agent trusts the right manager from its first connection, and you can set an expiry and revoke it without touching other agents. The address you put in the token has to be in the manager’s certificate, so check the SAN list first:

sudo openssl x509 -in /var/wazuh-manager/etc/certs/remoted.pem -noout -ext subjectAltName

Here the assistant added the hostname, the LAN IP and loopback, which covers agents on the same network.

X509v3 Subject Alternative Name:
    DNS:siem01, IP Address:192.168.1.142, DNS:localhost, IP Address:127.0.0.1, IP Address:0:0:0:0:0:0:0:1

If agents will reach the manager through a public IP, NAT or a DNS name that is not listed, add it when you install: the assistant’s -as (--agent-san) option puts extra names in that certificate. On a server that is already installed, the listener certificate has to be reissued with the new name before a token for it will work.

Create a token on the manager. --ttl 24h keeps it short-lived (the default is 30 days). Uses are unlimited until it expires, so add --max-uses 1 when the token is meant for a single machine:

sudo /var/wazuh-manager/bin/wazuh-manager-authd --create-enrollment-token --address 192.168.1.142 --ttl 24h

Only stdout carries the token itself (masked here), and the details follow on stderr. Copy the token now, because neither the CLI nor the dashboard shows it again.

eyJ2ZXIiOjEs***REDACTED***9nVSJ9
id: gU2Y9PsC-e4h2Wxp9XBhOA
endpoint: 192.168.1.142
expires: 2026-10-28T05:51:19Z (1793166679)
pin: a39009d523dd3a7ff0f100125cd2ce233afe861b9dde3eb7e6cefa48df7e83cd
credential: yes

Switch to the endpoint. Our agent box, web01, is another Ubuntu 26.04 VM. Add Wazuh’s signing key and the 5.x repository, which today is the same staging host the server installer came from:

sudo apt-get install -y gnupg apt-transport-https curl
curl -s https://packages-staging.xdrsiem.wazuh.info/key/GPG-KEY-WAZUH | sudo gpg --no-default-keyring --keyring gnupg-ring:/usr/share/keyrings/wazuh.gpg --import
sudo chmod 644 /usr/share/keyrings/wazuh.gpg
echo "deb [signed-by=/usr/share/keyrings/wazuh.gpg] https://packages-staging.xdrsiem.wazuh.info/pre-release/5.x/apt/ unstable main" | sudo tee /etc/apt/sources.list.d/wazuh.list
sudo apt-get update

Put the token in a variable, then install the agent with the token and a name in the environment. The variables go after sudo so the package scripts see them; that’s where they write the enrollment and manager settings into the agent config:

ENROLL_TOKEN='paste-the-token-here'
sudo WAZUH_ENROLLMENT_TOKEN="${ENROLL_TOKEN}" WAZUH_AGENT_NAME='web01' apt-get install -y wazuh-agent

On the agent side nothing moved: it stays in /var/ossec. Its ossec.conf now opens with an <enrollment> block and a <manager><endpoint> instead of the 4.x <client><server> address, and the token itself is not stored there.

<ossec_config>
  <agent>
    <enrollment>
      <enabled>yes</enabled>
      <agent_name>web01</agent_name>
    </enrollment>
    <manager>
      <endpoint>192.168.1.142</endpoint>
    </manager>
    <config-profile>ubuntu, ubuntu26, ubuntu26.04</config-profile>
  </agent>

Enroll and connect by starting the service. The agent presents the token on its first start and keeps its own key after that:

sudo systemctl daemon-reload
sudo systemctl enable --now wazuh-agent
sudo grep ^status /var/ossec/var/run/wazuh-agentd.state
sudo grep 'Token bootstrap: enrollment succeeded' /var/ossec/logs/ossec.log

Both lines should come back. The log line is the one to look for, because it confirms the agent pinned the manager’s CA rather than trusting whatever answered:

status='connected'
2026/10/27 05:52:23 wazuh-agentd: INFO: Token bootstrap: enrollment succeeded; the manager's CA is now the agent's trust anchor.

Now disable the Wazuh repository on the endpoint. Wazuh only guarantees an agent works with a manager of the same version or newer, and this repository is a staging channel, so a routine apt upgrade must not move the agent past the manager:

sudo sed -i 's/^deb /#deb /' /etc/apt/sources.list.d/wazuh.list
sudo apt-get update

Re-enable the line when you upgrade the manager and want agents to follow. Proving the agent uses 1517 takes a little patience. The 5.x transport is short HTTPS requests, not one long-lived socket like 4.x, so a single ss run often shows nothing. Sampling for about 20 seconds caught these, each with a new source port and none to 1514 or 1515:

for i in $(seq 1 40); do sudo ss -tnp | grep -E ':(1514|1515|1517)\b'; sleep 0.5; done | sort | uniq -c

Every connection goes from wazuh-agentd to the manager on 1517, so a firewall that only allows 1517 is enough for 5.x agents.

      1 ESTAB 0      0      192.168.1.135:37290 192.168.1.142:1517  users:(("wazuh-agentd",pid=30063,fd=13))
      1 ESTAB 0      0      192.168.1.135:37310 192.168.1.142:1517  users:(("wazuh-agentd",pid=30063,fd=13))
      1 ESTAB 0      0      192.168.1.135:57640 192.168.1.142:1517  users:(("wazuh-agentd",pid=30063,fd=13))                               

On the dashboard, the agent shows up on the Endpoints summary page (https://192.168.1.142/app/endpoints-summary) with its OS and version. Ours is ID 003 because we enrolled web01 more than once while testing, and IDs keep counting up on every enrollment:

Wazuh 5 endpoints summary showing agent 003 web01 on Ubuntu 26.04.1 LTS active with version 5.0.0

Tokens you no longer need should be revoked, since a 30-day token left lying in a wiki is a standing invitation to enroll rogue agents. List them, then revoke by ID:

sudo /var/wazuh-manager/bin/wazuh-manager-authd --list-enrollment-tokens
sudo /var/wazuh-manager/bin/wazuh-manager-authd --revoke-enrollment-token gU2Y9PsC-e4h2Wxp9XBhOA

Each row shows how many agents used the token, and the revoke confirms by ID. Revoking a token only stops new enrollments with it.

ID                      ENDPOINT                          EXPIRES               USES            REVOKED  DESCRIPTION
gU2Y9PsC-e4h2Wxp9XBhOA  192.168.1.142                     2026-10-28T05:51:19Z  1/unlimited     no       -
omCkRbhddH7HwXejrUE0Pw  192.168.1.142                     2026-10-28T05:56:27Z  1/unlimited     no       -
Enrollment token gU2Y9PsC-e4h2Wxp9XBhOA revoked.

Prefer clicking? The dashboard has the same controls on its Enrollment tokens page (/app/enrollment-tokens), with a Create token button for people who would rather not SSH to the manager. As the page itself says, the token text is only readable at the moment it is created.

Wazuh 5 dashboard enrollment tokens page listing two revoked agent enrollment tokens

To see events land in the indexer, we created and deleted a throwaway user on web01 and waited about 45 seconds. Wazuh 5 has no wazuh-alerts-* index; events, findings and agent state live in separate families, so query those:

ADMIN_PASS=$(sudo grep '^WAZUH_INDEXER_ADMIN_PASSWORD=' /etc/wazuh/credentials.env | cut -d= -f2-)
curl -sk -u "admin:${ADMIN_PASS}" "https://localhost:9200/_cat/indices/*wazuh-events*,*wazuh-findings*,wazuh-states*?v&h=index,docs.count,store.size&s=docs.count:desc"

After the test events, with one agent reporting, the top of the list looked like this.

index                                          docs.count store.size
wazuh-states-fim-files                               3778      1.8mb
wazuh-states-sca                                      279      599kb
.ds-wazuh-events-v5-system-activity-000001            227    189.7kb
wazuh-states-inventory-services                       206    101.9kb
wazuh-states-inventory-processes                      123     48.2kb
wazuh-states-inventory-groups                          65     27.8kb
wazuh-states-inventory-users                           35     32.1kb
wazuh-states-inventory-ports                           24     22.8kb
.ds-wazuh-findings-v5-system-activity-000001           20     56.8kb

Events are the raw decoded records and findings are what the rules flagged, here 20 findings out of 227 system events. That split is the thing to rebuild in any 4.x saved search: alert queries now go against wazuh-findings-v5-*. In the dashboard, the Threat Hunting page (/app/threat-hunting) reads the findings indices and breaks them down by level, agent and rule:

Wazuh 5 threat hunting dashboard with medium, low and informational findings from the web01 agent

In that chart, web01-v4 is the legacy agent from the next section, which ran on the same VM for a few minutes.

Connecting existing Wazuh 4.x agents

A Wazuh 5 manager still accepts 4.x agents, because the <legacy> block inside <remote> keeps 1514 listening and the <auth> block keeps enrollment on 1515, both enabled by default. That lets you replace the server first and upgrade endpoints later, which is the order Wazuh’s own migration guide uses. Open the two legacy ports on the manager:

sudo ufw allow 1514/tcp
sudo ufw allow 1515/tcp

A 4.x agent enrolls with the shared password, which the 5.x manager generates and keeps in /var/wazuh-manager/etc/authd.pass. Read it on the manager:

sudo cat /var/wazuh-manager/etc/authd.pass

Use an endpoint that has no 5.x agent on it, because apt refuses to downgrade wazuh-agent from 5.x to 4.x with -y. We reused web01, so we removed the 5.x agent and commented out its repository first; skip this block on a clean endpoint:

sudo systemctl stop wazuh-agent
sudo apt-get purge -y wazuh-agent
sudo rm -rf /var/ossec
sudo sed -i 's/^deb /#deb /' /etc/apt/sources.list.d/wazuh.list

On the Ubuntu endpoint, add the 4.x repository (the Rocky and AlmaLinux agent guide has the RPM side):

curl -s https://packages.wazuh.com/key/GPG-KEY-WAZUH | sudo gpg --no-default-keyring --keyring gnupg-ring:/usr/share/keyrings/wazuh4.gpg --import
sudo chmod 644 /usr/share/keyrings/wazuh4.gpg
echo 'deb [signed-by=/usr/share/keyrings/wazuh4.gpg] https://packages.wazuh.com/4.x/apt/ stable main' | sudo tee /etc/apt/sources.list.d/wazuh4.list
sudo apt-get update

Install a 4.x agent pointed at the new manager, passing the password from that file. We pinned the agent version so the test matched the 4.x fleet we were simulating. If you later move that box to a 5.x agent, delete /etc/apt/sources.list.d/wazuh4.list first so apt doesn’t mix the two trees:

sudo WAZUH_MANAGER=192.168.1.142 WAZUH_AGENT_NAME=web01-v4 WAZUH_REGISTRATION_PASSWORD='password-from-authd.pass' apt-get install -y wazuh-agent=4.14.9-1 #https://github.com/wazuh/wazuh/releases
sudo systemctl daemon-reload
sudo systemctl enable --now wazuh-agent

Start the service as usual. The agent log shows the old two-step, a key from 1515 and then a session on 1514.

2026/10/27 05:55:45 wazuh-agentd: INFO: Valid key received
2026/10/27 05:56:05 wazuh-agentd: INFO: (4102): Connected to the server ([192.168.1.142]:1514/tcp).

Our manager listed it as active, with a 4.x version string, next to the 5.x agent. Treat that as a bridge, though, not a destination. Wazuh’s agent migration page says FIM, SCA, system inventory, active response and vulnerability detection are not fully supported until the agent is upgraded, so a 4.x agent on a 5.x manager mostly gives you log data. The reverse isn’t supported: Wazuh only guarantees agent compatibility when the manager runs the same version as the agent or a newer one, so a 5.x agent does not belong on a 4.x manager.

Moving from Wazuh 4.x to Wazuh 5

There is no in-place upgrade from 4.x to 5.x. Wazuh’s migration guide says it directly: 4.x environments “cannot be upgraded in place”, and the move means migrating or recreating data, configuration, certificates and security settings. The indexer is the hard part, since 5.x is built on OpenSearch 3.x and treats restored 4.x indices as history it never writes to. We did not run a migration in this lab, so the order below is the documented one, not a tested runbook:

  1. Build a new 5.x stack beside the 4.x one
  2. Snapshot the 4.x indices and restore them into the new indexer
  3. Move agent registrations and groups to the new manager
  4. Recreate users, roles, rules and decoders by hand
  5. Point agents at the new manager, then upgrade them to 5.x

Restored 4.x indices keep their old mappings, Wazuh 5 never writes to them, and only indices from 4.4.0 or later can be restored. Agent IDs, keys and groups carry over (the release adds a wazuh-migrate-identity.py tool for that), but the manager’s ossec.conf does not: the docs say plainly that 4.x configuration files cannot be migrated, and custom XML rules and decoders have to be rebuilt in the new content management. Budget the most time for that last item if your team has years of local rules.

Upgraded agents need the new manager’s root-ca.pem copied to /var/ossec/etc/certs/, or they connect with TLS verification disabled. If a parallel stack is more than you want to run, the 4.x line is still the stable release: our Wazuh server guide for Ubuntu 24.04, the Docker Compose deployment and the Ansible deployment all keep working until you’re ready to cut over.

Troubleshooting Wazuh 5 errors from the lab

Every error below came up on the lab manager, most of them from habits carried over from 4.x. When something misbehaves, the one log to watch is /var/wazuh-manager/logs/wazuh-manager.log, which replaced /var/ossec/logs/ossec.log on the server.

“Invalid configuration at ‘/cluster/disabled’: unknown option”

Paste a 4.x cluster block, with its <disabled> line, into the 5.x config and validation fails. We added the line to a copy of the config and validated it.

(1244): Invalid configuration at '/cluster/disabled': unknown option (does not satisfy 'additionalProperties') [schema /properties/cluster].

Every manager is a cluster node now, so the option no longer exists. Delete the line, run sudo /var/wazuh-manager/bin/wazuh-manager-conf validate until it prints nothing, then restart wazuh-manager. Make validate a habit before every restart, since it checks the same file the daemons load and every agent connection depends on the manager coming back.

“the root element must be <wazuh_config>, found <ossec_config>”

An old ossec.conf copied over as the manager config fails before any option is even read:

(1244): Invalid configuration at '/': invalid XML: the root element must be <wazuh_config>, found <ossec_config> (line 7).

Renaming the root element isn’t enough, because the schema also rejects removed options. Start from the 5.x file the package installed and move your settings across one block at a time, validating after each. Agents are the exception: their config is still ossec.conf with an <ossec_config> root.

API returns “404: Not Found” for /manager/info

Monitoring scripts that poll /manager/info or /manager/status get this back from the 5.x API:

{
    "title": "Not Found",
    "detail": "404: Not Found"
}

Use GET / for the API and manager version, and /cluster/status plus /cluster/nodes for health, because a single manager is a cluster node now and reports its state there. All three answered normally on our server, so updating a monitoring check is a path change, not a rewrite.

“Cannot search on field [event.original] since it is both not indexed”

We hit this with a 4.x-style match_phrase query for a log line against the findings index:

"reason": "failed to create query: Cannot search on field [event.original] since it is both not indexed, and does not have doc_values enabled.",
"index": ".ds-wazuh-findings-v5-system-activity-000001",

Wazuh 5’s schema stores the raw line in event.original but does not index it, so a phrase search on it can’t work. Filter on wazuh.agent.name and sort on @timestamp instead, which is how we pulled web01’s events once the query error cleared.

“WARNING: (1408): Invalid ID 002 for the source ip”

Deleting the 4.x agent through the API while it was still running on web01 flooded the manager log with this line.

2026/10/27 05:56:41 wazuh-manager-remoted: WARNING: (1408): Invalid ID 002 for the source ip: '192.168.1.135' (name 'unknown').

An agent that keeps running after you delete it keeps sending with a key the manager no longer has. Stop or remove the agent on the endpoint first, then delete it on the manager, and the warnings stop. A related line, The inventory sync server answered HTTP 503, showed up once right after a new agent’s first inventory sync and cleared by itself within a minute.

Once the manager has run cleanly for a day, back up /etc/wazuh/ca and the passwords from credentials.env somewhere off the box, then delete the credentials file as the quickstart suggests. Those two are what you need to add a worker node or rebuild a certificate. Lose the CA and every certificate it signed has to be replaced, so treat that directory like any other root key.

Keep reading

Upgrade Ubuntu 24.04 to Ubuntu 26.04 LTS (Step by Step) Ubuntu Upgrade Ubuntu 24.04 to Ubuntu 26.04 LTS (Step by Step) UFW Firewall Commands with Examples on Ubuntu 26.04 / 24.04 Security UFW Firewall Commands with Examples on Ubuntu 26.04 / 24.04 PHP2Shell (CVE-2026-109618, CVE-2026-109619): Check and Patch PHP Php PHP2Shell (CVE-2026-109618, CVE-2026-109619): Check and Patch PHP Best Laptops for Kali Linux and Pentesting Kali Linux Best Laptops for Kali Linux and Pentesting Upgrade Ubuntu 26.04 LTS to 26.10 (Stonking Stingray) Ubuntu Upgrade Ubuntu 26.04 LTS to 26.10 (Stonking Stingray) 6 Linux Security Best Practices for Enterprises Security 6 Linux Security Best Practices for Enterprises

Leave a Comment

Press ESC to close