Use case · Security monitoring

Wazuh server on one dedicated machine: sizing, install and ports

One machine runs a Wazuh server for up to about 100 agents: the official quickstart installs the server, the indexer and the dashboard on a single host and recommends 4 vCPU, 8 GiB and 50 GB for 1-25 agents, up to 8 vCPU and 200 GB for 51-100, with 90 days of indexed alerts.

See the machines

The three components and what they need

Wazuh is an open-source platform for log analysis and security monitoring of servers and workstations. A lightweight agent on each endpoint ships events to three central parts: the Wazuh server (the manager that decodes events, applies rules and keeps agent state), the Wazuh indexer (stores and searches alerts) and the Wazuh dashboard (the web interface). The indexer is a fork of OpenSearch and the dashboard a fork of OpenSearch Dashboards, as the README.md of each repository states.

AgentsCPURAMStorage, 90 days
1-254 vCPU8 GiB50 GB
26-508 vCPU8 GiB100 GB
51-1008 vCPU8 GiB200 GB

That is the quickstart table for all three on one host. The per-component pages are stricter: the indexer lists 4 GB and 2 cores as its minimum and 16 GB and 8 cores as recommended per node, and the server 2 GB/2 cores minimum, 4 GB/8 cores recommended. The server also needs at least 20 GB free on the volume holding /var/ossec before its first start, because the vulnerability detection database unpacks there and settles at about 11 GB. For 90 days of alerts the indexer docs estimate 1.5 GB per workstation, 3.7 GB per server and 7.4 GB per network device.

Supported systems for 4.14 are Ubuntu 16.04 to 24.04, Red Hat Enterprise Linux 7 to 10, Amazon Linux 2 and 2023 and CentOS Stream 10, on x86_64 or ARM64. This page uses Ubuntu 24.04.

Choosing the machine

The indexer is the part that grows: its disk need scales with alerts per second, and it carries the highest memory recommendation of the three, 16 GB per node. On a whole machine it gets all the RAM and all the disks, and nobody else's processes share them. Size memory first, as our dedicated server range advises, then disk for the retention you want.

  • Up to 25 agents: the m710x cartridge, Intel Xeon E3-1585L v5, 4 cores at 3 GHz, 16-64 GB and NVMe. Its 16 GB entry size is already double the table's 8 GiB and equals the indexer page's per-node recommendation; we would go to 32 GB for retention past 90 days (our judgement). It has an out-of-band console.
  • 26-100 agents or longer retention: a dual-socket rack server, for instance 2 x Xeon E5-2630L v3 (16 cores, memory up to 1 TB), with disks chosen in the configurator to fit the per-agent figures above. Every racked single-, dual- and quad-socket server has an out-of-band console (HPE iLO, Dell iDRAC or a Supermicro BMC).
  • Beyond 100 agents: the docs recommend a distributed deployment, with multi-node clusters for the server and the indexer; that is several machines, not a bigger one.
  • Not the X-Gene cartridge: it installs only Ubuntu 16.04 and 18.04, both past standard support, and every command here targets 24.04.

The port is unmetered, so agent traffic and the vulnerability feed downloads are never a line on the bill. Once payment is approved, handover of a racked machine takes about 30 minutes; a build to order takes 4 to 24 hours. The console matters here: the install block below turns on ufw, and a wrong rule is undone from it.

Ports and who may reach them

The docs list these defaults. The all-in-one binds the indexer to 127.0.0.1 (wazuh-install.sh writes network.host: "127.0.0.1"), while the API listens on 0.0.0.0 and :: by default and the dashboard on 0.0.0.0. The firewall decides the rest.

PortServiceWho may reach it
1514/tcpAgent connection (encrypted, authenticated)Your agents only
1515/tcpAgent enrollmentYour agents, while enrolling
55000/tcpWazuh server APINobody outside; the dashboard calls it locally
9200/tcpIndexer APINobody outside (loopback on all-in-one)
443/tcpDashboardYou, by SSH tunnel or from named addresses
1516, 9300-9400/tcpServer and indexer clusteringClosed on a single node
514 udp/tcpSyslog collectorOff by default; open only to named senders

Enrollment needs care. The manager's default auth section in ossec.conf has use_password set to no, so anything that reaches 1515 can register as an agent. Turn on the enrollment password before opening it, and allow 1514 and 1515 from your agents' networks only. If laptops roam with changing addresses, 1514 has to be open more widely; keep 1515 password-protected, and open it only while you add agents.

Installing the all-in-one

The block turns on ufw with SSH only, then runs the assistant with -a (all-in-one). The assistant itself refuses to run over an existing install unless given -o. It generates random passwords for every indexer and API user, shows the admin one in its summary, and keeps all of them in wazuh-install-files.tar, which the block makes root-only and prints. It then disables the Wazuh apt repository, as the quickstart recommends, so a routine apt upgrade cannot upgrade Wazuh by accident; the docs warn that such an upgrade could break the environment. With ufw active, the assistant also prints a reminder to allow 1515, 1514 and 443; leave them closed for now. The enrollment block below opens 1514 and 1515 to your agents only, and the dashboard is reached over SSH.

# as root on a fresh Ubuntu 24.04 machine
sed -i 's/^IPV6=.*/IPV6=yes/' /etc/default/ufw &&
ufw allow OpenSSH && ufw --force enable &&
cd /root && curl -sO https://packages.wazuh.com/4.14/wazuh-install.sh &&
bash ./wazuh-install.sh -a &&
chmod 600 /root/wazuh-install-files.tar &&
sed -i "s/^deb /#deb /" /etc/apt/sources.list.d/wazuh.list && apt update &&
tar -O -xf /root/wazuh-install-files.tar wazuh-install-files/wazuh-passwords.txt &&
echo "install done; only SSH is open" ||
echo "STOP - read the assistant output above before going on"
  1. From your workstation: ssh -L 8443:127.0.0.1:443 you@your-server, then open https://localhost:8443. The certificate is self-signed, so the browser warns once; that is expected.
  2. Log in as admin. To replace the password that sits in the archive and your scrollback, run bash /usr/share/wazuh-indexer/plugins/opensearch-security/tools/wazuh-passwords-tool.sh -u admin as root. With no -p it generates and prints a new one; on an all-in-one it updates Filebeat and the manager and restarts them itself.
  3. Copy wazuh-install-files.tar to a safe place off the server; it holds the certificates as well as the passwords.

Enrolling agents

Set AGENTS to the network your endpoints connect from. The block creates the enrollment password once (re-running it keeps the existing one), switches use_password on, checks the edit took, restarts the manager and only then opens 1514 and 1515 to that network. This assumes agents connect over IPv4: the auth reference shows the enrollment service's ipv6 option off by default.

# as root on the Wazuh server
P=/var/ossec/etc/authd.pass; C=/var/ossec/etc/ossec.conf
AGENTS=""   # e.g. 198.51.100.0/24, the network your agents connect from
if [ -z "$AGENTS" ]; then echo "STOP - set AGENTS first"; else
  { [ -s "$P" ] || { s=$(openssl rand -hex 16) && [ -n "$s" ] &&
    install -m 640 -o root -g wazuh /dev/null "$P" && printf '%s\n' "$s" > "$P"; }; } &&
  sed -i 's|<use_password>no</use_password>|<use_password>yes</use_password>|' "$C" &&
  grep -q '<use_password>yes</use_password>' "$C" &&
  systemctl restart wazuh-manager &&
  ufw allow from "$AGENTS" to any port 1514,1515 proto tcp &&
  echo "enrollment password is in $P; agents allowed from $AGENTS" ||
  echo "STOP - a step did not finish; check $C and the ufw output, then run again"
fi

On each Linux endpoint, add the Wazuh repository and install with WAZUH_MANAGER set to your server, as the agent install page shows; the dashboard's deploy-agent screen writes the same command. Then put the password in /var/ossec/etc/authd.pass on the agent (create it with install -m 640 -o root -g wazuh /dev/null, then write to it) and systemctl restart wazuh-agent. The WAZUH_REGISTRATION_PASSWORD variable also works (it writes the same authd.pass), but the password then lands in your shell history. Keep agents at or below the manager's version.

To reach the dashboard without a tunnel, run ufw allow from 203.0.113.10 to any port 443 proto tcp with your own address, or put a team behind a WireGuard VPN.

Backups, restores and upgrades

The script follows the official backup list, simplified by taking whole directories (all of /var/ossec/etc, /etc/wazuh-indexer, /etc/wazuh-dashboard, the dashboard's data folder and the custom script folders) where the docs name single files, and skipping paths that do not exist. Like the docs, it stops the manager only while copying /var/ossec/queue/db; the trap starts it again even if a step breaks. The archive is listed back before anything older than 14 days is pruned. It stages a full copy under /tmp first, so keep free space of about twice the size of /var/ossec/logs.

# /root/wazuh-backup.sh, run as root with bash /root/wazuh-backup.sh
set -euo pipefail; umask 077
D=/root/wazuh-backups; mkdir -p "$D"; T=$(mktemp -d)
trap 'systemctl start wazuh-manager; rm -rf "$T"' EXIT
R="rsync -aR --ignore-missing-args"
$R /etc/filebeat/ /etc/postfix/ /var/ossec/api/configuration/ /var/ossec/etc/ \
  /var/ossec/logs/ /var/ossec/queue/agentless/ /var/ossec/queue/agents-timestamp \
  /var/ossec/queue/fts/ /var/ossec/queue/rids/ /var/ossec/stats/ \
  /var/ossec/var/multigroups/ /var/ossec/active-response/bin/ \
  /var/ossec/integrations/ /var/ossec/wodles/ /etc/wazuh-indexer/ \
  /usr/lib/sysctl.d/wazuh-indexer.conf /etc/wazuh-dashboard/ \
  /usr/share/wazuh-dashboard/config/opensearch_dashboards.keystore \
  /usr/share/wazuh-dashboard/data/wazuh/ \
  /usr/share/wazuh-dashboard/plugins/wazuh/public/assets/custom/images/ "$T/"
systemctl stop wazuh-manager
$R /var/ossec/queue/db/ "$T/"
systemctl start wazuh-manager
F="$D/wazuh-$(date +%F-%H%M%S).tar.gz"
tar -czf "$F" -C "$T" .
tar -tzf "$F" > /dev/null
find "$D" -name 'wazuh-*.tar.gz' -mtime +14 -delete
echo "backup ok, $F"

Run it once by hand, then schedule it in /etc/cron.d/wazuh-backup as 30 2 * * * root umask 077; bash /root/wazuh-backup.sh > /root/wazuh-backups/last.log 2>&1. Copy the archives off the machine yourself. They include the alert files under /var/ossec/logs, but not the indexed copy; the docs suggest a snapshot of the indices and cluster state for that.

To restore, check the archive reads cleanly (tar -tzf must list it without complaint), install the same Wazuh version with the assistant on a clean machine, extract the archive into an empty directory, cd into it, and follow the official restore guide for the central components file by file; its relative paths (etc/..., var/...) match this archive's layout. For upgrades, take a backup and an index snapshot, re-enable the repository and follow the upgrade guide in its order: indexer, then server, then dashboard. Since 4.12 the indexer cannot be downgraded to 4.11 or earlier without a fresh install, and from 4.14.1 decoded user fields are mapped to dstuser, which can break saved searches.

Licence and limits

In the v4.14.9 tag, the LICENSE file of wazuh/wazuh puts the server and agent under GPLv2. The wazuh-indexer and wazuh-dashboard repositories ship LICENSE.txt with Apache 2.0, and the dashboard plugins are GPLv2. Our general reading, not legal advice: running it for your own estate owes nothing. Distributing copies of the GPL parts, modified or not, means passing on their source under GPLv2; the Apache parts need their copyright notices and licence text kept. The LICENSE on the main development branch already puts the Wazuh engine (src/engine/) under AGPL-3.0 or later, which adds a duty to offer source for modified versions used over a network, so read it again before moving to a release built from that branch.

One host is the wrong design if you need the dashboard to survive the loss of a machine, or past about 100 agents. Wazuh is also not a metrics system; for CPU, disk and service graphs pair it with Zabbix or Prometheus and Grafana. For plain log search without the Wazuh rules, see self-hosted OpenSearch.

Questions

How much RAM does a Wazuh all-in-one host need?

The quickstart table gives 8 GiB for 1 to 100 agents, with CPU and disk growing with the agent count. The indexer's own page recommends 16 GB per node, so 16 GB or more is the comfortable choice; that last point is our judgement, not a documented figure.

Which ports must face the internet?

Only 1514/tcp and 1515/tcp, and only toward your agents. The API on 55000 and the indexer on 9200 stay closed; the dashboard on 443 is reached over an SSH tunnel or from addresses you name.

Where are the admin and API passwords after the install?

The assistant prints them at the end and stores them in wazuh-passwords.txt inside wazuh-install-files.tar, in the directory where it ran. The quickstart shows a tar -O -xvf command that prints them. Rotate them with the passwords tool when needed.

How do I keep agents from enrolling without permission?

Set use_password to yes in the auth section of /var/ossec/etc/ossec.conf, put the password in /var/ossec/etc/authd.pass (640, root:wazuh) and restart the manager. Agents then need the same password, and the firewall can still limit 1515 to your own networks.

Give the indexer a machine of its own

Whole servers with root, an out-of-band console on rack servers and the m710x, on unmetered ports, rented by the month.

See the machines

Related on Server Room

Other use cases