Linux Tutorials

Install Wazuh SIEM on Ubuntu 26.04 LTS: All-in-One Setup

One script puts the entire Wazuh stack on a single Ubuntu 26.04 server. It installs the indexer, the manager, Filebeat and the dashboard, generates every certificate, and prints an admin password at the end. The whole run took 15 minutes on a 4 vCPU, 8 GB VM.

Original content from computingforgeeks.com - post 166285

This guide shows how to install Wazuh on Ubuntu 26.04 LTS as an all-in-one node with the official installation assistant, then the parts the assistant leaves to you: firewall ports, a trusted TLS certificate for the dashboard, a fix for an indexer heap bug in the script, enrolling a Linux agent, and proving the SIEM works with a real SSH brute-force alert. Everything below was run on Ubuntu 26.04.1 LTS with Wazuh 4.14.8, and the release status was checked again in November 2026. Wazuh 5.0 is still a release candidate, so this guide stays on the stable 4.x line.

Running Ubuntu 24.04 instead, or want to install each component by hand so you can split it across nodes later? The step-by-step Wazuh server installation on Ubuntu 24.04 covers that path.

How the all-in-one install fits together

The assistant puts four services on one host. Agents and browsers need only three ports, plus port 80 if you use HTTP-01 renewals later.

Wazuh all-in-one architecture diagram on Ubuntu 26.04: browser to dashboard on 443, web01 agent to manager on 1514 and 1515, Filebeat to indexer on 127.0.0.1:9200

The dashboard serves the web UI on 443 and calls the manager API on 55000. Agents talk to the manager on 1514 (events) and 1515 (enrollment). The manager writes alerts to alerts.json, Filebeat ships them to the indexer, and the dashboard queries the indexer. In an all-in-one install the indexer binds to 127.0.0.1:9200, so it is never exposed. The API on 55000 does listen on all addresses, so the firewall is what keeps it private.

Prerequisites

Size the server from the number of agents and how long you keep alerts. Event rate drives CPU and indexer heap. Retention drives disk. The Wazuh quickstart sizing for a single host is a good starting point:

AgentsvCPURAMDisk (90 days of alerts)
1 to 2548 GB50 GB
26 to 5088 GB100 GB
51 to 10088 GB200 GB

Past 100 agents, plan a distributed deployment. Our lab VM had 4 vCPU, 8 GB RAM and a 60 GB disk. That is a floor for following along, not a production recommendation. A fresh install used 17 GB of disk before a single agent connected.

  • A fresh Ubuntu 26.04 LTS server with sudo access. Nothing else listening on port 443.
  • A DNS name for the dashboard (we use wazuh.example.com) with an A record pointing at the server, and port 80 reachable for the HTTP-01 challenge. Any DNS provider works.
  • One Linux machine to enroll as an agent. Ours is web01 at 192.168.1.137, also on Ubuntu 26.04.

If the server is still raw, run through the initial server setup first and set up SSH key logins before you open more ports.

Set the shell variables

Two values are yours: the dashboard hostname and the email certbot registers for expiry notices. The other two are detected. The version line asks GitHub for the newest stable 4.x tag, which also names the installer branch on packages.wazuh.com.

export WAZUH_FQDN="wazuh.example.com"
export ADMIN_EMAIL="[email protected]"
export WAZUH_VER=$(curl -s "https://api.github.com/repos/wazuh/wazuh/releases?per_page=30" | grep -oE '"tag_name": "v4\.[0-9]+\.[0-9]+"' | grep -oE '4\.[0-9]+\.[0-9]+' | sort -V | tail -1)
export WAZUH_MINOR="${WAZUH_VER%.*}"
echo "Wazuh ${WAZUH_VER}, installer branch ${WAZUH_MINOR}, dashboard ${WAZUH_FQDN}"

Confirm both versions printed before going further. An empty value means the GitHub API call failed:

Wazuh 4.14.8, installer branch 4.14, dashboard wazuh.example.com

The grep filters out release candidates and the 5.0 line on purpose. These exports live only in the current shell. Run the block again if you reconnect.

Open the firewall

UFW ships inactive on Ubuntu 26.04. Allow SSH before enabling it, or you lock yourself out. The OpenSSH profile covers port 22 only, so if SSH runs on another port add sudo ufw allow 2222/tcp with your port first. Then open the dashboard and the two agent ports:

sudo ufw allow OpenSSH
sudo ufw allow 443/tcp comment 'Wazuh dashboard'
sudo ufw allow 1514/tcp comment 'Wazuh agent events'
sudo ufw allow 1515/tcp comment 'Wazuh agent enrollment'
sudo ufw --force enable
sudo ufw status numbered

Port 55000 (the manager API) and 9200 (the indexer) stay closed. The dashboard reaches both locally. The rule list should match:

Status: active

     To                         Action      From
     --                         ------      ----
[ 1] OpenSSH                    ALLOW IN    Anywhere
[ 2] 443/tcp                    ALLOW IN    Anywhere                   # Wazuh dashboard
[ 3] 1514/tcp                   ALLOW IN    Anywhere                   # Wazuh agent events
[ 4] 1515/tcp                   ALLOW IN    Anywhere                   # Wazuh agent enrollment
[ 5] OpenSSH (v6)               ALLOW IN    Anywhere (v6)
[ 6] 443/tcp (v6)               ALLOW IN    Anywhere (v6)              # Wazuh dashboard
[ 7] 1514/tcp (v6)              ALLOW IN    Anywhere (v6)              # Wazuh agent events
[ 8] 1515/tcp (v6)              ALLOW IN    Anywhere (v6)              # Wazuh agent enrollment

Port 80 opens later, in the certificate step. A cloud security group or upstream firewall in front of the server needs the same ports. The UFW firewall guide covers source-restricted rules if you want 1514 and 1515 open to your server subnet only.

Install Wazuh on Ubuntu 26.04 with the assistant

Download the script for the detected branch:

cd ~
curl -sO "https://packages.wazuh.com/${WAZUH_MINOR}/wazuh-install.sh"
ls -l wazuh-install.sh

Start the all-in-one install with -a. No other flag is needed on 26.04:

sudo bash wazuh-install.sh -a

Our run, with the generated admin password removed. Note the warning on the third and fourth lines:

07/10/2026 22:59:46 INFO: Starting Wazuh installation assistant. Wazuh version: 4.14.8
07/10/2026 22:59:46 INFO: Verbose logging redirected to /var/log/wazuh-install.log
07/10/2026 22:59:47 INFO: The recommended systems are: Red Hat Enterprise Linux 7, 8, 9; CentOS 7, 8; Amazon Linux 2; Amazon Linux 2023; Ubuntu 16.04, 18.04, 20.04, 22.04; Rocky Linux 9.4.
07/10/2026 22:59:48 WARNING: The current system does not match with the list of recommended systems. The installation may not work properly.
07/10/2026 22:59:53 INFO: Verifying that your system meets the recommended minimum hardware requirements.
07/10/2026 22:59:53 INFO: Wazuh web interface port will be 443.
07/10/2026 23:00:01 INFO: --- Dependencies ----
07/10/2026 23:00:01 INFO: Installing apt-transport-https.
07/10/2026 23:00:10 INFO: Wazuh repository added.
07/10/2026 23:00:10 INFO: --- Configuration files ---
07/10/2026 23:00:10 INFO: Generating configuration files.
07/10/2026 23:00:11 INFO: Generating the root certificate.
07/10/2026 23:00:11 INFO: Generating Admin certificates.
07/10/2026 23:00:11 INFO: Generating Wazuh indexer certificates.
07/10/2026 23:00:11 INFO: Generating Filebeat certificates.
07/10/2026 23:00:12 INFO: Generating Wazuh dashboard certificates.
07/10/2026 23:00:12 INFO: Created wazuh-install-files.tar. It contains the Wazuh cluster key, certificates, and passwords necessary for installation.
07/10/2026 23:00:13 INFO: --- Wazuh indexer ---
07/10/2026 23:00:13 INFO: Starting Wazuh indexer installation.
07/10/2026 23:01:18 INFO: Wazuh indexer installation finished.
07/10/2026 23:01:18 INFO: Wazuh indexer post-install configuration finished.
07/10/2026 23:01:18 INFO: Starting service wazuh-indexer.
07/10/2026 23:01:41 INFO: wazuh-indexer service started.
07/10/2026 23:01:41 INFO: Initializing Wazuh indexer cluster security settings.
07/10/2026 23:01:46 INFO: Wazuh indexer cluster security configuration initialized.
07/10/2026 23:01:46 INFO: Wazuh indexer cluster initialized.
07/10/2026 23:01:46 INFO: --- Wazuh server ---
07/10/2026 23:01:46 INFO: Starting the Wazuh manager installation.
07/10/2026 23:06:14 INFO: Wazuh manager installation finished.
07/10/2026 23:06:17 INFO: Wazuh manager vulnerability detection configuration finished.
07/10/2026 23:06:17 INFO: Starting service wazuh-manager.
07/10/2026 23:06:41 INFO: wazuh-manager service started.
07/10/2026 23:06:41 INFO: Starting Filebeat installation.
07/10/2026 23:06:53 INFO: Filebeat installation finished.
07/10/2026 23:06:56 INFO: Filebeat post-install configuration finished.
07/10/2026 23:06:56 INFO: Starting service filebeat.
07/10/2026 23:06:59 INFO: filebeat service started.
07/10/2026 23:06:59 INFO: --- Wazuh dashboard ---
07/10/2026 23:06:59 INFO: Starting Wazuh dashboard installation.
07/10/2026 23:13:44 INFO: Wazuh dashboard installation finished.
07/10/2026 23:13:44 INFO: Wazuh dashboard post-install configuration finished.
07/10/2026 23:13:44 INFO: Starting service wazuh-dashboard.
07/10/2026 23:13:47 INFO: wazuh-dashboard service started.
07/10/2026 23:13:49 INFO: Updating the internal users.
07/10/2026 23:13:53 INFO: A backup of the internal users has been saved in the /etc/wazuh-indexer/internalusers-backup folder.
07/10/2026 23:14:06 INFO: The filebeat.yml file has been updated to use the Filebeat Keystore username and password.
07/10/2026 23:14:40 INFO: Initializing Wazuh dashboard web application.
07/10/2026 23:14:42 INFO: Wazuh dashboard web application initialized.
07/10/2026 23:14:42 INFO: --- Summary ---
07/10/2026 23:14:42 INFO: You can access the web interface https://<wazuh-dashboard-ip>:443
    User: admin
    Password: <redacted>
07/10/2026 23:14:42 INFO: Installation finished.

The assistant does not list Ubuntu 26.04 as a recommended system, but it only warns and carries on. The -i flag that older guides add for 26.04 skips the hardware check, not this OS check, so it is not needed. The manager and the dashboard were the slow steps here at about five and seven minutes each. Every package then installed and started cleanly.

Copy the admin password from the summary now.

Back up the generated passwords and certificates

Everything the assistant generated sits in wazuh-install-files.tar next to the script, which is your home directory if you followed along. That covers every internal password, all node certificates and the root CA key. List it:

sudo tar -tf ~/wazuh-install-files.tar

You should see the passwords file, the CA, and one certificate pair per component:

wazuh-install-files/
wazuh-install-files/config.yml
wazuh-install-files/wazuh-passwords.txt
wazuh-install-files/wazuh-server.pem
wazuh-install-files/wazuh-server-key.pem
wazuh-install-files/wazuh-indexer.pem
wazuh-install-files/wazuh-indexer-key.pem
wazuh-install-files/wazuh-dashboard.pem
wazuh-install-files/wazuh-dashboard-key.pem
wazuh-install-files/root-ca.pem
wazuh-install-files/root-ca.key
wazuh-install-files/admin.pem
wazuh-install-files/admin-key.pem

Print the passwords file without extracting it to disk:

sudo tar -O -xf ~/wazuh-install-files.tar wazuh-install-files/wazuh-passwords.txt

Each internal user gets its own block. Values are masked here:

# Admin user for the web user interface and Wazuh indexer. Use this user to log in to Wazuh dashboard
  indexer_username: 'admin'
  indexer_password: '********'

# Password for wazuh API user
  api_username: 'wazuh'
  api_password: '********'

# Password for wazuh-wui API user
  api_username: 'wazuh-wui'
  api_password: '********'

Copy this archive off the server today. We learned why the hard way: running wazuh-install.sh -a a second time deletes it before the script notices Wazuh is already installed. The error section below shows that run.

Verify the services and ports

Four systemd units make up the stack. All four should be active:

systemctl is-active wazuh-indexer wazuh-manager filebeat wazuh-dashboard

Then check which addresses each service bound to:

sudo ss -tlnp | grep -E ":(443|1514|1515|9200|55000) " | awk '{print $4, $6}'

The capture below was taken after the agent from a later step enrolled. The indexer listens on loopback only, which is what you want on a single host:

Terminal showing the four Wazuh services active, agent web01 active and listening ports on Ubuntu 26.04

Filebeat should also reach the indexer over TLS. The tail of sudo filebeat test output ends with:

    TLS version: TLSv1.2
    dial up... OK
  talk to server... OK
  version: 7.10.2

The 7.10.2 is the OpenSearch compatibility version the indexer reports to Filebeat, not the Wazuh version.

Fix the indexer heap the assistant gets wrong

This catches people out. The assistant is meant to give the indexer half the RAM. In the 4.14 script the heap function reads total memory into ram_gb but divides an unset ram_mb, so the result is always zero and it falls back to 1 GB. Our 8 GB host got this:

grep -E '^-Xm' /etc/wazuh-indexer/jvm.options

The heap is fixed at 1 GB regardless of RAM:

-Xms1024m
-Xmx1024m

One GB won’t carry more than a handful of agents. Past that the indexer starts collecting garbage under load and the dashboard turns slow. Set it to half the RAM. On an 8 GB host that is 4 GB:

sudo sed -i -e 's/^-Xms1024m/-Xms4g/' -e 's/^-Xmx1024m/-Xmx4g/' /etc/wazuh-indexer/jvm.options
sudo systemctl restart wazuh-indexer
ps -o args= -C java | grep -oE "Xm[sx][0-9]+[mg]" | sort -u

The running JVM picks up the new values:

Xms4g
Xmx4g

With a 4 GB heap the host had 2 GB of RAM still available while serving one agent. Keep Xms and Xmx equal, never go above half the RAM, and on large hosts stop at about 31 GB so the JVM keeps compressed object pointers. The manager, Filebeat and the dashboard need the rest.

Log in to the Wazuh dashboard

Browse to https://wazuh.example.com (or the server IP for now). The browser warns about the certificate until the next step replaces it. Sign in as admin with the password from the summary:

Wazuh dashboard login page served over HTTPS on Ubuntu 26.04

The overview page shows agent counts and the last 24 hours of alerts by severity. This capture was taken after the agent enrolled and the brute-force test below ran:

Wazuh overview page on Ubuntu 26.04 showing one active agent and last 24 hours alert counts

Most of those medium and low alerts come from the first rootcheck and configuration scan. Expect a burst like this every time you enroll a new host.

Put a Let’s Encrypt certificate on the dashboard

The assistant signs the dashboard certificate with its own root CA. Every browser rejects it. The dashboard runs its own TLS listener on 443 with no web server in front, so we let certbot answer the HTTP-01 challenge on port 80 by itself and copy the result into place with a deploy hook. Nothing else on this host uses port 80, so renewals work the same way.

Open port 80 and install certbot. On a private server that will use the DNS-01 alternative below, skip the port 80 rule:

sudo ufw allow 80/tcp comment 'Lets Encrypt HTTP-01'
sudo apt install -y certbot

Request the certificate. Port 80 must be reachable from the internet and the A record must already resolve:

sudo certbot certonly --standalone -d "${WAZUH_FQDN}" \
  --non-interactive --agree-tos -m "${ADMIN_EMAIL}"

Certbot saves the files under /etc/letsencrypt/live/. Current certbot issues an ECDSA P-256 key by default; we fed the hook below a P-256 test certificate and the dashboard served it without complaint. The dashboard reads wazuh-dashboard.pem and wazuh-dashboard-key.pem from its own certs directory, under names the assistant chose. Confirm the paths on your install:

grep -E '^server.ssl' /etc/wazuh-dashboard/opensearch_dashboards.yml

An assistant install points at these files:

server.ssl.enabled: true
server.ssl.key: "/etc/wazuh-dashboard/certs/wazuh-dashboard-key.pem"
server.ssl.certificate: "/etc/wazuh-dashboard/certs/wazuh-dashboard.pem"

A step-by-step install names them dashboard.pem instead, so check before you copy. Create a deploy hook that copies the certificate over those two files and restarts the dashboard. Certbot runs every script in this directory after each successful renewal:

sudo vim /etc/letsencrypt/renewal-hooks/deploy/wazuh-dashboard.sh

Add the following:

#!/bin/bash
# Copies the renewed Let's Encrypt certificate into the Wazuh dashboard
set -euo pipefail
CERT_DIR=/etc/wazuh-dashboard/certs
install -m 400 -o wazuh-dashboard -g wazuh-dashboard "${RENEWED_LINEAGE}/fullchain.pem" "${CERT_DIR}/wazuh-dashboard.pem"
install -m 400 -o wazuh-dashboard -g wazuh-dashboard "${RENEWED_LINEAGE}/privkey.pem" "${CERT_DIR}/wazuh-dashboard-key.pem"
systemctl restart wazuh-dashboard

Make it executable and run it once by hand, pointing RENEWED_LINEAGE at the new certificate:

sudo chmod 755 /etc/letsencrypt/renewal-hooks/deploy/wazuh-dashboard.sh
sudo RENEWED_LINEAGE="/etc/letsencrypt/live/${WAZUH_FQDN}" /etc/letsencrypt/renewal-hooks/deploy/wazuh-dashboard.sh

The dashboard takes about 15 seconds to come back. Check what it serves now:

echo | openssl s_client -connect 127.0.0.1:443 -servername "${WAZUH_FQDN}" 2>/dev/null | openssl x509 -noout -subject -issuer

The subject should be your hostname and the issuer a public ACME intermediate. Leave root-ca.pem alone: the dashboard still uses it to trust the indexer. Then confirm renewals will work:

sudo certbot renew --dry-run

The Ubuntu certbot package installs a systemd timer that runs the renewal twice a day.

Alternative: DNS-01 for a server without public port 80

A dashboard on a private network cannot answer HTTP-01. Use a DNS plugin instead. It proves ownership with a TXT record, so the server needs no inbound access at all:

DNS providerUbuntu packagecertbot flag
Cloudflarepython3-certbot-dns-cloudflare–dns-cloudflare
Route 53python3-certbot-dns-route53–dns-route53
DigitalOceanpython3-certbot-dns-digitalocean–dns-digitalocean
Google Cloud DNSpython3-certbot-dns-google–dns-google
RFC2136 (BIND)python3-certbot-dns-rfc2136–dns-rfc2136

The Cloudflare example below works the same way for the others. Swap in the package, flag and credentials file for your provider. Create a root-only directory for the credentials:

sudo mkdir -p -m 700 /root/.secrets

Then create the credentials file with an API token that can edit DNS for the zone:

sudo vim /root/.secrets/cloudflare.ini

Add one line with your token:

dns_cloudflare_api_token = your-token-here

Lock it down and request the certificate:

sudo chmod 600 /root/.secrets/cloudflare.ini
sudo apt install -y python3-certbot-dns-cloudflare
sudo certbot certonly --dns-cloudflare --dns-cloudflare-credentials /root/.secrets/cloudflare.ini \
  -d "${WAZUH_FQDN}" --non-interactive --agree-tos -m "${ADMIN_EMAIL}"

Create the same deploy hook as above and run it once by hand to copy the certificate in. If issuance fails here, the token usually lacks Zone:DNS:Edit on that zone. With HTTP-01, a failure almost always means port 80 is blocked upstream or the A record does not resolve yet.

Enroll a Linux agent

The agent must not be newer than the manager, so read the exact manager package version on the Wazuh server first:

dpkg-query -W -f='${Version}\n' wazuh-manager

Ours printed:

4.14.8-1

Run the rest of this section on the machine you want to monitor, not on the Wazuh server. Set the manager address and the version you just read. Ours are 192.168.1.128 and 4.14.8-1:

export WAZUH_MANAGER="192.168.1.128"
export WAZUH_AGENT_VER="4.14.8-1" #https://github.com/wazuh/wazuh/releases

Add the Wazuh repository and its signing key:

sudo apt install -y gnupg apt-transport-https curl
curl -s https://packages.wazuh.com/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.wazuh.com/4.x/apt/ stable main" | sudo tee /etc/apt/sources.list.d/wazuh.list
sudo apt update

Install the agent. The package reads WAZUH_MANAGER and WAZUH_AGENT_NAME at install time and writes them into ossec.conf. The variables must sit after sudo or the package never sees them:

sudo WAZUH_MANAGER="${WAZUH_MANAGER}" WAZUH_AGENT_NAME="web01" apt install -y wazuh-agent="${WAZUH_AGENT_VER}"
sudo systemctl daemon-reload
sudo systemctl enable --now wazuh-agent

The agent enrolls on 1515, gets its key, then connects on 1514. Its log shows the handshake:

sudo tail -6 /var/ossec/logs/ossec.log

Look for the connected line:

2026/10/07 23:18:01 wazuh-agentd: INFO: (1410): Reading authentication keys file.
2026/10/07 23:18:01 wazuh-agentd: INFO: Using AES as encryption method.
2026/10/07 23:18:01 wazuh-agentd: INFO: Trying to connect to server ([192.168.1.128]:1514/tcp).
2026/10/07 23:18:01 wazuh-agentd: INFO: (4102): Connected to the server ([192.168.1.128]:1514/tcp).
2026/10/07 23:18:02 wazuh-syscheckd: INFO: Agent is now online. Process unlocked, continuing...
2026/10/07 23:18:02 rootcheck: INFO: Starting rootcheck scan.

Wazuh supports agents on the same version as the manager or older, never newer. Disable the repository on the agent so a routine upgrade cannot move it ahead of the server:

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

Back on the server, sudo /var/ossec/bin/agent_control -l lists the agent. It shows Pending for a few seconds, then Active. In the dashboard, Agents management > Summary shows the same:

Wazuh endpoints list showing agent web01 active on Ubuntu 26.04.1 LTS, version v4.14.8

For more than a few hosts, the Ansible-based Wazuh deployment handles enrollment at scale, and the Rocky Linux and AlmaLinux guide covers RPM agents.

Trigger an SSH brute-force alert

An empty dashboard doesn’t prove anything. Generate failed logins against web01 from another host. Ten attempts with a user that does not exist is enough:

for i in $(seq 1 10); do ssh -o BatchMode=yes -o StrictHostKeyChecking=no [email protected] true; done

On Ubuntu 26.04 the agent reads SSH events from the systemd journal, where the daemon logs as sshd-session. The stock decoders handle it. On the server, pull the new alerts for web01 out of the current alerts.json (the manager rotates it at midnight server time):

sudo grep -E '"id":"(5710|5712)"' /var/ossec/logs/alerts/alerts.json | grep '"name":"web01"' | python3 -c 'import sys,json; [print(a["timestamp"], a["rule"]["id"], a["rule"]["level"], a["rule"]["description"]) for a in map(json.loads, sys.stdin)]' | tail -5

Each line shows the time, rule ID, level and description:

2026-10-08T00:02:32.729+0000 5710 5 sshd: Attempt to login using a non-existent user
2026-10-08T00:02:32.729+0000 5710 5 sshd: Attempt to login using a non-existent user
2026-10-08T00:02:32.729+0000 5712 10 sshd: brute force trying to get access to the system. Non existent user.
2026-10-08T00:02:32.729+0000 5710 5 sshd: Attempt to login using a non-existent user
2026-10-08T00:02:32.729+0000 5710 5 sshd: Attempt to login using a non-existent user

Rule 5710 fires once per failed login at level 5. The eighth failed login from the same IP within 120 seconds fires rule 5712 at level 10, which then stays quiet for 60 seconds. That is the alert to wire into email or Slack. In the dashboard, open Threat intelligence > Threat Hunting, switch to Events, and search rule.id:5712 or rule.id:5710:

Wazuh threat hunting events showing rule 5710 and level 10 rule 5712 SSH brute force alerts from web01

Detection isn’t blocking. To ban the source IP automatically, pair the agent with Fail2ban or CrowdSec, or enable a Wazuh active response. Writing your own rules on top of 5710 and 5712 and running the alert queue day to day is a skill of its own, and our shortlist of Wazuh and SIEM books covers that side.

Errors we hit on Ubuntu 26.04

WARNING: The current system does not match with the list of recommended systems

Printed at the start of every run on Ubuntu 26.04, because the script only accepts Ubuntu up to 24.04 (its printed list even stops at 22.04). It is a warning, not a failure. The install completed. Adding -i does not silence it, since that flag only skips the CPU and RAM check.

ERROR: Wazuh indexer already installed.

We re-ran sudo bash wazuh-install.sh -a on the finished host to see what happens. The script stopped with:

07/10/2026 23:38:12 ERROR: Wazuh manager already installed.
07/10/2026 23:38:12 ERROR: Wazuh indexer already installed.
07/10/2026 23:38:12 ERROR: Wazuh dashboard already installed.
07/10/2026 23:38:12 ERROR: Filebeat already installed.
07/10/2026 23:38:12 INFO: If you want to overwrite the current installation, run this script adding the option -o/--overwrite. This will erase all the existing configuration and data.

Nothing was overwritten. That is the good part. But wazuh-install-files.tar was gone. In all-in-one mode the script deletes an existing archive before it checks for installed components. With the archive went the only copy of the generated passwords and the root CA key. Back it up right after the first install, and never re-run -a on a working host. To rebuild, use -o on purpose, which wipes all data.

The first failed logins after enrollment never became alerts

Our first brute-force run, started 20 seconds after enrollment, produced no 5710 alerts at all. The agent log explained it. The agent restarts its collectors once it receives the shared configuration from the manager, and our attempts landed in that gap:

2026/10/07 23:18:21 wazuh-logcollector: INFO: (1225): SIGNAL [(15)-(Terminated)] Received. Exit Cleaning...
2026/10/07 23:18:28 wazuh-logcollector: INFO: (9203): Monitoring journal entries.

Wait for Monitoring journal entries in the log on the agent before you test. It is usually there within 30 seconds. The second run, a minute later, alerted on every attempt.

Production hardening for a single-node Wazuh

The install works. These changes make it safe to leave running:

  • Pin the version. The assistant leaves the 4.x repository enabled, so a routine apt upgrade can move the indexer, manager and dashboard out of step. Comment it out with sudo sed -i 's/^deb /#deb /' /etc/apt/sources.list.d/wazuh.list and upgrade on purpose.
  • Rotate the admin password to one you control: sudo /usr/share/wazuh-indexer/plugins/opensearch-security/tools/wazuh-passwords-tool.sh -u admin -p 'Your.New.Pass1'. The new password worked on our host about five seconds after the tool finished.
  • Restrict 1514 and 1515 to the subnets your agents live in. We replaced the open rules with sudo ufw allow from 192.168.1.0/24 to any port 1514,1515 proto tcp comment 'Wazuh agents subnet', then sudo ufw delete allow 1514/tcp and sudo ufw delete allow 1515/tcp, and the agent stayed active.
  • Require a password for enrollment so a random host cannot register itself. The 24.04 step-by-step guide walks through authd.pass with the real error an agent prints without it.
  • Plan for retention. Alerts go into one daily index each. Set an index lifecycle policy before the disk fills, or snapshot old indices elsewhere.

Then harden the host underneath with the Ubuntu 26.04 server hardening guide. A SIEM on a soft host is the first thing an attacker turns off.

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 Upgrade a Single Package on Ubuntu / Debian with apt Debian Upgrade a Single Package on Ubuntu / Debian with apt APT Cheat Sheet: apt and apt-get Commands for Ubuntu/Debian Cheat Sheets APT Cheat Sheet: apt and apt-get Commands for Ubuntu/Debian Borg vs Restic vs Kopia: Backup Tools Benchmarked Debian Borg vs Restic vs Kopia: Backup Tools Benchmarked

Leave a Comment

Press ESC to close