Wazuh Docker deployment
Wazuh consists of a multi-platform Wazuh agent and three central components: the Wazuh manager, the Wazuh indexer, and the Wazuh dashboard. For more information, refer to the Wazuh components documentation.
Deployment options
Wazuh supports deploying its central components and agent on Docker.
Single-node stack: This stack deploys one of each Wazuh central component as a separate container. It includes:
Wazuh indexer container: Stores and indexes security data collected by the Wazuh manager. It also provides near real-time search and security analytics.
Wazuh manager container: Transforms data received from Wazuh agents into standardized schema documents using the Wazuh Common Schema (WCS).
Wazuh dashboard container: Centralized web interface for monitoring and searching security data, and managing Wazuh.
It provides persistent storage and certificates for secure communication.
Multi-node stack: This stack deploys each Wazuh component as a separate container. It includes:
Three Wazuh indexer containers: Work together in a cluster to store and replicate indexed data, ensuring scalability and fault tolerance.
Two Wazuh manager containers: one master node and one worker node. The master node runs the Wazuh manager API and keeps the Wazuh agent registry, enrollment tokens, and agent group configuration, which it syncs to the worker. Both nodes receive Wazuh agent connections, so the worker adds redundancy and load distribution.
One Wazuh dashboard container.
One Nginx container: the entry point for Wazuh agents. It passes each agent connection on ports 1517 and 1514 to the Wazuh manager master or worker node, chosen by the agent's IP address. Nginx hashes the source address it sees, so agents spread across the two nodes only when they connect from different addresses. Wazuh agent containers on the Docker host reach Nginx from the Docker network gateway, and agents behind one NAT share its address, so each of these groups goes to one Wazuh manager node. To see which node processes an agent's data, check the
wazuh.cluster.nodefield of its events. Nginx doesn't decrypt this traffic. Each Wazuh manager node presents its own certificate, and both certificates carry the address that agents connect to (see Prepare the certificates). The Wazuh manager master node publishes the other Wazuh manager ports itself, as listed in Exposed ports.
This deployment stack provides persistent storage and secure communication. All its containers run on one Docker host. If one Wazuh manager node stops, Nginx passes new agent connections to the other node. While the Wazuh manager master node is stopped, the Wazuh manager API on port 55000 and the Wazuh dashboard pages that use it are unavailable.
Wazuh agent: This deploys the Wazuh agent as a container on a Docker host.
Prerequisites
Before deploying Wazuh on Docker, ensure your environment meets the following requirements.
System requirements
Single-node stack deployment
Operating system: Linux, Windows, or macOS
Architecture: AMD64 or ARM64 (AARCH64)
CPU: At least 4 cores
Memory: At least 8 GB of RAM for the Docker host
Disk space: At least 50 GB of storage for Docker images and data volumes
Multi-node stack deployment
Operating system: Linux, Windows, or macOS
Architecture: AMD64 or ARM64 (AARCH64)
CPU: At least 4 cores
Memory: At least 16 GB for the Docker host
Disk space: At least 100 GB of storage for Docker images and data volumes
Wazuh agent deployment
Operating system: Linux, Windows, or macOS
Architecture: AMD64 or ARM64 (AARCH64)
CPU: At least 2 cores
Memory: At least 1 GB of RAM for the Docker host
Disk space: At least 10 GB of storage for Docker images and logs
Software requirements
Docker Engine:
Install Docker Engine (requires version 20.10.0 or newer)
Docker Compose plugin: provides the
docker composecommand that this guide uses. The Docker Engine installation installs it as thedocker-compose-pluginpackage. To install it separately, see Install the Docker Compose plugin. Rundocker compose versionto check that it's installed.Git: Required for cloning the Wazuh Docker repository
Docker Desktop:
Install Docker Desktop (requires WSL 2)
Docker Compose is included with Docker Desktop on Windows
Git: Required for cloning the Wazuh Docker repository
Docker Desktop:
Docker Compose is included with Docker Desktop on macOS
Git: Required for cloning the Wazuh Docker repository
Bash shell
GNU versions of apps:
Linux/Unix host requirements
Additional configuration is required to ensure proper functionality when running Wazuh Docker on a Linux/Unix operating system.
Check the
max_map_countvalue on your Docker host. The Wazuh indexer creates a large number of virtual memory-mapped areas (VMAs), so it needs a value of at least262144. The Linux kernel default is65530, but some distributions set a higher value. For example, Ubuntu 24.04 sets1048576. A VMA is a region of memory that the kernel reserves for applications like the Wazuh indexer to access files directly from disk as if they were in RAM.# sysctl vm.max_map_count
If the value is lower than
262144, run the following command to set it:# sysctl -w vm.max_map_count=262144
This setting is lost when the Docker host restarts. To keep it, add it to a sysctl configuration file and reload the settings:
# echo "vm.max_map_count=262144" > /etc/sysctl.d/99-wazuh-max-map-count.conf # sysctl --system
Warning
This configuration allows more files and index segments to be mapped to memory simultaneously without errors or crashes. If you don't set a minimum value of at least
262144formax_map_counton your Linux host, the Wazuh indexer will not work correctly.If you want to use Docker as a non-root user, you should add the user to the
dockergroup using the following command:# usermod -aG docker <USER>
Replace
<USER>with your username. Log out and back in for changes to take effect.
Exposed ports
The following ports are exposed when the Wazuh central components are deployed.
In the multi-node stack, the Nginx container publishes ports 1517 and 1514, and the Wazuh manager master node publishes ports 1515 and 55000. Neither stack publishes the Wazuh indexer API on port 9200. Only the other containers can reach it. The other ports are published on every network interface of the Docker host. The Wazuh dashboard container reaches the Wazuh manager API through the Docker network. If no other host needs port 55000, or the Wazuh 4.x agent ports 1514 and 1515, remove its line from the ports section of the service in docker-compose.yml, or bind it to the local host, for example, "127.0.0.1:55000:55000".
Port |
Component |
1517 |
Wazuh 5.x agent connection and enrollment |
1514 |
Wazuh 4.x agent connection |
1515 |
Wazuh 4.x agent enrollment |
55000 |
Wazuh manager API |
443 |
Wazuh dashboard HTTPS |
Wazuh central components
Below are the steps for deploying the Wazuh central components in single-node and multi-node stacks.
Warning
Do not run the single-node and multi-node stacks simultaneously on the same Docker host. Both stacks publish the same host ports: 443, 1514, 1515, 1517, and 55000. While one stack is running, starting the other stack fails with port is already allocated, and its Wazuh manager and the containers that depend on it don't start.
To switch stacks, run the following command from the directory of the running stack, wazuh-docker/single-node/ or wazuh-docker/multi-node/:
# docker compose down
This command removes the stack's containers and keeps its data volumes. The stacks do not share volumes, so switching does not need the -v flag, which deletes the stack's data. Docker Compose names the volumes after the directory of the stack. Another clone of the Wazuh Docker repository on the same Docker host uses the same volume names in its single-node or multi-node directory, so don't deploy a second stack from it while this one keeps its volumes.
If you already tried to start the other stack while this one was running, also run docker compose down in the other stack's directory before you start it. Otherwise, Docker can start its Wazuh manager without a network, and the stack doesn't work.
Deploying the central components
Follow the steps below to deploy the Wazuh central components. Steps that differ between the stacks show the single-node and multi-node values in tabs, so select the stack you chose. The tab you select applies to the whole procedure.
Note
You need root user privileges to run the commands below. If you use Docker as a non-root user, run them with sudo.
All deployment commands provided apply to Windows, macOS, and Linux environments. Some commands may require minor syntax adjustments depending on the shell or terminal in use.
Cloning the repository
Perform the following to clone the Wazuh Docker repository:
Clone the Wazuh Docker repository to your system:
# git clone https://github.com/wazuh/wazuh-docker.git -b v5.0.0-rc2
Navigate to the directory of your stack to execute all the following commands.
# cd wazuh-docker/single-node/
# cd wazuh-docker/multi-node/
Prepare the certificates
Secure communication between Wazuh components requires the use of certificates. Follow the steps below to prepare and generate the certificates:
Use the certificate creation tool from Wazuh 5.0.0 RC 2. Earlier versions don't create the Wazuh manager API certificates (
apid) that each Wazuh manager node needs. If you already ran the certificate creation script with an earlier version, runrm -rf wazuh-certificates/before you run it again. Run the following command to download the tool:# curl -fsS -o wazuh-certs-tool.sh https://packages-staging.xdrsiem.wazuh.info/pre-release/5.x/installation-assistant/wazuh-certs-tool-5.0.0-rc2.sh
Create a
config.ymlfile with the following content:nodes: # Wazuh indexer server nodes indexer: - name: wazuh.indexer dns: "wazuh.indexer" # Wazuh manager nodes # Use node_type only with more than one Wazuh manager manager: - name: wazuh.manager dns: "wazuh.manager" # Wazuh dashboard node dashboard: - name: wazuh.dashboard dns: "wazuh.dashboard"
nodes: # Wazuh indexer server nodes indexer: - name: wazuh1.indexer dns: "wazuh1.indexer" - name: wazuh2.indexer dns: "wazuh2.indexer" - name: wazuh3.indexer dns: "wazuh3.indexer" # Wazuh manager nodes # Use node_type only with more than one Wazuh manager manager: - name: wazuh.master dns: "wazuh.master" node_type: master - name: wazuh.worker dns: "wazuh.worker" node_type: worker # Wazuh dashboard node dashboard: - name: wazuh.dashboard dns: "wazuh.dashboard"
Run the certificate creation script and replace
<DOCKER_HOST_IP>with the IP address that Wazuh agents use to reach the Docker host:# bash ../tools/utils/deployment/certificates-conf.sh --cert --copy --priv --agent-san <DOCKER_HOST_IP>
Where:
--certgenerates the certificates.--copycopies the certificates to theconfig/directory, where thedocker-compose.ymlfile mounts them from.--privoption sets the file owners the Wazuh containers need.--agent-sanoption adds the address to the certificate the Wazuh manager presents to Wazuh agents. Wazuh agents check that this certificate names the address they connect to, and the Wazuh manager creates enrollment tokens only for addresses it names. Repeat--agent-sanfor each address agents use, such as a DNS name.
The script adds the address to the certificate of the Wazuh manager.
The script adds the address to the agent listener certificate of both Wazuh manager nodes so that an agent can verify whichever node answers. Don't add this address to
config.ymlinstead, because the script rejects an address repeated across Wazuh manager nodes.The certificate creation tool keeps the root CA certificate and its private key in the
wazuh-ca/directory, next towazuh-certs-tool.shin the directory of your stack. The containers receive only the root CA certificate fromconfig/root-ca/certs/root-ca.pem. Back upwazuh-ca/, because you need it to create certificates for new nodes or new Wazuh agent addresses. Always run the script from the directory of your stack. From another directory, the tool creates a new root CA, and Wazuh agents enrolled with the current root CA reject the certificates it signs. To keep the root CA in another directory, setWAZUH_CA_DIRto its absolute path before you run the script.
Create the credentials
The Wazuh Docker images ship no passwords. Generate the passwords for your deployment once, after you prepare the certificates and before you start the stack for the first time.
Run the credentials creation script:
# bash ../tools/utils/deployment/credentials-conf.sh
The script writes a random password for each account to config/credentials/indexer.env, config/credentials/manager.env, and config/credentials/dashboard.env. The stack does not start without these files. Keep them, because they are the only record of your passwords. Don't edit them after the first start: an edit doesn't change the passwords, and the files then no longer match your deployment. To change a password later, see Changing a password.
Deployment
Start the Wazuh Docker deployment using the docker compose command:
# docker compose up -d
# docker compose up
Check that the stack is ready. Run the following command from the directory of your stack. If you started the stack in the foreground, use another terminal.
# docker compose ps
The stack is ready when all three containers show (healthy) in the STATUS column. On a host with the minimum requirements, this takes about 2 minutes on the first run, image download included.
The stack is ready when the six Wazuh containers show (healthy) in the STATUS column. The Nginx container has no health check, so it shows only Up. On a host with the minimum requirements, this takes about 4 minutes on the first run, image download included.
To check that the Wazuh manager cluster and the Wazuh indexer cluster formed, run the following commands from the directory of your stack. The first one lists the master and worker01 nodes. The second one shows "status" : "green" and "number_of_nodes" : 3. Run the second one again after you restart a Wazuh indexer container.
# docker compose exec wazuh.master /var/wazuh-manager/bin/cluster_control -l
# docker compose exec wazuh1.indexer curl -sk -u "admin:$(grep '^WAZUH_INDEXER_ADMIN_PASSWORD=' config/credentials/indexer.env | cut -d= -f2-)" "https://localhost:9200/_cluster/health?pretty"
If the Wazuh manager doesn't start, check for either of these messages:
docker compose logs wazuh.manager shows the manager Server API certificate is missing or unreadable and UNSAFE /etc/wazuh-manager/certs/apid.pem: not a regular file, and the container restarts in a loop.
docker compose up -d stops with Are you trying to mount a directory onto a file (or vice-versa)?
Both mean that a Wazuh manager certificate was missing from config/ when the container started, and Docker created an empty directory in its place. Run the following commands from the directory of your stack to remove the directories and create the certificates again. Replace <DOCKER_HOST_IP> with the address you used when you prepared the certificates:
# docker compose stop wazuh.manager
# rm -rf config/wazuh_manager/certs/wazuh.manager-apid.pem config/wazuh_manager/certs/wazuh.manager-apid-key.pem
# rm -rf wazuh-certificates/
# bash ../tools/utils/deployment/certificates-conf.sh --cert --copy --priv --agent-san <DOCKER_HOST_IP>
# docker compose up -d
If docker compose up -d still stops with Are you trying to mount a directory onto a file, the Wazuh manager volume holds the same directories. Remove them, then start the stack again. If you upgraded the deployment, use the Wazuh manager image tag in your docker-compose.yml file:
# docker run --rm -v single-node_wazuh_etc:/v --entrypoint rmdir wazuh/wazuh-manager:5.0.0-rc2 /v/certs/apid.pem /v/certs/apid-key.pem
# docker compose up -d
If a Wazuh manager node doesn't start, check for either of these messages:
docker compose logs <SERVICE> shows the manager Server API certificate is missing or unreadable and UNSAFE /etc/wazuh-manager/certs/apid.pem: not a regular file, and the container restarts in a loop. Replace <SERVICE> with wazuh.master or wazuh.worker.
docker compose up -d stops with Are you trying to mount a directory onto a file (or vice-versa)?
Both mean that a certificate for that node was missing from config/ when the container started, and Docker created an empty directory in its place. Run the following commands from the directory of your stack to remove the directories and create the certificates again. The commands are for wazuh.worker. For the master node, use wazuh.master and the config/wazuh_master/certs/wazuh.master-apid.pem and wazuh.master-apid-key.pem files. Replace <DOCKER_HOST_IP> with the address you used when you prepared the certificates:
# docker compose stop wazuh.worker
# rm -rf config/wazuh_worker/certs/wazuh.worker-apid.pem config/wazuh_worker/certs/wazuh.worker-apid-key.pem
# rm -rf wazuh-certificates/
# bash ../tools/utils/deployment/certificates-conf.sh --cert --copy --priv --agent-san <DOCKER_HOST_IP>
# docker compose up -d
If docker compose up -d still stops with Are you trying to mount a directory onto a file, the volume of that node holds the same directories. Remove them, then start the stack again. For the master node, use the multi-node_master-wazuh-etc volume. If you upgraded the deployment, use the Wazuh manager image tag in your docker-compose.yml file:
# docker run --rm -v multi-node_worker-wazuh-etc:/v --entrypoint rmdir wazuh/wazuh-manager:5.0.0-rc2 /v/certs/apid.pem /v/certs/apid-key.pem
# docker compose up -d
The Wazuh central components don't reload their configuration while they run. After you change a configuration file inside a container, restart that container. Replace <SERVICE> with its service name, such as wazuh.manager in the single-node stack or wazuh.master in the multi-node stack:
# docker compose restart <SERVICE>
At each start, each Wazuh manager container sets its Wazuh indexer hosts, cluster settings, and listener addresses from the environment section of the docker-compose.yml file in the directory of your stack (wazuh-docker/single-node/ or wazuh-docker/multi-node/), so change those settings there. After you change docker-compose.yml, run docker compose up -d, because docker compose restart doesn't apply changes to that file.
Accessing the Wazuh dashboard
After deploying the stack, you can access the Wazuh dashboard using your Docker host's IP address or localhost.
https://<DOCKER_HOST_IP>
Note
If you open the Wazuh dashboard, your browser warns that it can't verify its certificate. The certificate creation script issued the certificate from a root CA that it created for your deployment, and for the name wazuh.dashboard, not the address you open.
Log in to the Wazuh dashboard with the admin username. The password is the WAZUH_INDEXER_ADMIN_PASSWORD value in config/credentials/indexer.env. Run the following command from the directory of your stack to print it:
# grep '^WAZUH_INDEXER_ADMIN_PASSWORD=' config/credentials/indexer.env | cut -d= -f2-
If the browser can't connect, or shows server is not ready yet, wait until docker compose ps shows the wazuh.dashboard container as (healthy), then reload the page.
Wazuh agent
Running the Wazuh agent in a Docker container provides a lightweight option for integrations and log collection via syslog without installing the Wazuh agent directly on a host. However, when deployed this way, the containerized Wazuh agent cannot directly access or monitor the host system.
Deployment
Follow these steps to deploy the Wazuh agent using Docker.
You need root user privileges to run the commands below. If you use Docker as a non-root user, run them with sudo.
On the Docker host that runs the Wazuh central components, create an enrollment token. Run the command from the
single-nodeormulti-nodedirectory. Replace<DOCKER_HOST_IP>with an address you added with--agent-sanwhen preparing the certificates:# docker compose exec wazuh.manager /var/wazuh-manager/bin/wazuh-manager-authd --create-enrollment-token --address <DOCKER_HOST_IP>
# docker compose exec wazuh.master /var/wazuh-manager/bin/wazuh-manager-authd --create-enrollment-token --address <DOCKER_HOST_IP>
The first line of the output is the enrollment token. Copy it. The token expires after 30 days, and any number of Wazuh agents can use it until then. You can also use the token to enroll a Wazuh agent installed from packages. Pass it in
WAZUH_ENROLLMENT_TOKENwhen you install the Wazuh agent.If the command returns
address not in certificate SAN, the address isn't in the Wazuh manager agent listener certificate. Use an address you passed with--agent-san, or add the address. To add it, run the following commands from thesingle-nodeormulti-nodedirectory. Pass every address agents use, because the script creates the certificates again fromconfig.ymland the--agent-sanvalues:# rm -rf wazuh-certificates/ # bash ../tools/utils/deployment/certificates-conf.sh --cert --copy --priv --agent-san <DOCKER_HOST_IP> # docker compose up -d --force-recreate --no-deps wazuh.manager
# rm -rf wazuh-certificates/ # bash ../tools/utils/deployment/certificates-conf.sh --cert --copy --priv --agent-san <DOCKER_HOST_IP> # docker compose up -d --force-recreate --no-deps wazuh.master wazuh.worker
The certificate creation script doesn't replace existing certificates. If you run it again without removing
wazuh-certificates/, it stops withError: wazuh-certs-tool.sh failed (exit code 1). No certificates were copied.The script signs the new certificates with the root CA inwazuh-ca/, so enrolled Wazuh agents keep trusting the Wazuh manager.Go to the
wazuh-agentdirectory of the Wazuh Docker repository.On the Docker host that runs the Wazuh central components, use the repository you cloned for the stack. Run the following command from the
wazuh-docker/single-node/orwazuh-docker/multi-node/directory:# cd ../wazuh-agent
On another Docker host: clone the Wazuh Docker repository, then go to its
wazuh-agentdirectory:# git clone https://github.com/wazuh/wazuh-docker.git -b v5.0.0-rc2 # cd wazuh-docker/wazuh-agent
Edit the
docker-compose.ymlfile. Replace<ENROLLMENT_TOKEN>with the enrollment token from step 1:# Wazuh App Copyright (C) Wazuh Inc. (License GPLv2) services: wazuh.agent: image: wazuh/wazuh-agent:5.0.0-rc2 restart: always environment: - WAZUH_ENROLLMENT_TOKEN=<ENROLLMENT_TOKEN> #- WAZUH_AGENT_NAME=<WAZUH_AGENT_NAME> volumes: - wazuh_agent_etc:/var/ossec/etc volumes: wazuh_agent_etc:
The token carries the Wazuh manager address and identifies its certificate authority, so the Wazuh agent needs no other connection settings. Don't set
WAZUH_MANAGER_SERVERorWAZUH_MANAGER_ENDPOINTtogether with the token. On the first start, the container exits with an error when both are set, and Docker restarts it in a loop. To name the Wazuh agent, uncommentWAZUH_AGENT_NAMEand replace<WAZUH_AGENT_NAME>.The
wazuh_agent_etcvolume keeps the Wazuh agent enrollment when you recreate the container. After the first start, the container keeps the connection settings stored in this volume and ignoresWAZUH_ENROLLMENT_TOKENandWAZUH_MANAGER_SERVER.Start the Wazuh agent deployment using
docker compose:# docker compose up -d
# docker compose up
Verify from your Wazuh dashboard that the Wazuh agent deployment was successful and visible. Navigate to Agents management > Summary, and you should see the Wazuh agent container active on your dashboard.
Next steps
To monitor more endpoints, deploy Wazuh agents on them as described in Wazuh agent. To remove the deployment, see Uninstalling the Wazuh Docker deployment.