This page walks you through deploying the three server-side Wazuh components — Wazuh Indexer (OpenSearch-based data store), Wazuh Manager (analysis and correlation engine with Filebeat), and Wazuh Dashboard (web UI) — as Docker Compose services on a single host. You can use the convenience scriptDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/rsol9000-01/wazuh/llms.txt
Use this file to discover all available pages before exploring further.
wazuh-dev.sh for a guided deployment, or follow the manual steps to drive each stage yourself.
Prerequisites
Before starting, ensure the following are in place on the target host:-
Docker Engine 20.10+ and Docker Compose 2.0+ installed and available in
$PATH -
vm.max_map_count≥ 262144 — required by the OpenSearch-based Indexer.wazuh-dev.shsets this automatically; for manual deployments run:To make it persistent across reboots, addvm.max_map_count=262144to/etc/sysctl.conf. -
The following TCP/UDP ports open and not already bound by another process:
Port Protocol Service 1514 TCP Agent event ingestion 1515 TCP Agent auto-enrollment (authd) 514 UDP Syslog collection 55000 TCP Wazuh REST API 9200 TCP OpenSearch / Wazuh Indexer 6443 TCP Wazuh Dashboard (maps to internal 5601) -
A populated
.envfile at the project root (copy from.env.example— see Environment Variables) -
TLS certificates generated in
./config/wazuh_indexer_ssl_certs/(see Certificates)
Using wazuh-dev.sh (Recommended)
The helper scriptscripts/wazuh-dev.sh automates every pre-deployment check and then starts the stack. Run it as root or with sudo from the project root:
- Sets
vm.max_map_count— reads the current value from/proc/sys/vm/max_map_countand, if it is below 262144, appliessysctl -w vm.max_map_count=262144automatically. - Validates Docker and curl — exits with a clear error message if either binary is absent.
- Checks
.envexists — if not found, it copies.env.exampleto.envand asks you to fill in the values before continuing. - Verifies required files — confirms
docker-compose.yml,config/wazuh_indexer/internal_users.yml,generate-indexer-certs.yml, and theSCRIPT_POST_INSTALLpath are all present. - Resolves
LOCAL_AGENT_HOSTNAME— if the value in.envislocalhost, substitutes the actual system FQDN returned byhostname -f. - Updates API credentials in
wazuh.yml— writesAPI_USERNAMEandAPI_PASSWORDfrom.envintoconfig/wazuh_dashboard/wazuh.yml, after validating that neither value contains a$character. - Hashes
MY_PASSWORDintointernal_users.yml— runs the Wazuh Indexer image’s built-in/usr/share/wazuh-indexer/plugins/opensearch-security/tools/hash.shto bcrypt-hash the password, then creates or updates theMY_USERNAMEentry inconfig/wazuh_indexer/internal_users.yml. - Generates TLS certificates — runs
docker compose -f generate-indexer-certs.yml run --rm generatorto produce all inter-service certificates. - Starts the stack — executes
docker compose -f docker-compose.yml --env-file .env up -dand tailsdocker compose logs -f wazuh-init.
Manual Deployment
If you prefer to control each step individually, follow the sequence below.Copy and edit the environment file
Copy the example file and open it in an editor to set all required credentials and network values:Refer to the Environment Variables reference for a description of every variable.
Generate TLS certificates
Run the certificate generator container. It reads See Certificates for the full list of generated files and their purposes.
./config/certs.yml and writes all certificates to ./config/wazuh_indexer_ssl_certs/:Start the services
Bring up all three server services in detached mode:Docker Compose reads the
.env file automatically from the project root.Check service status
Verify that all containers reached a running state and that health checks are passing:The Indexer health check polls
https://localhost:9200 with INDEXER_USERNAME/INDEXER_PASSWORD credentials (interval 30 s, timeout 10 s, 3 retries, start period 30 s). The Manager polls https://localhost:55000 and the Dashboard polls https://localhost:5601/api/status (both at 10 s interval, 10 s timeout, 10 retries). Allow up to two minutes for all three services to become healthy on first boot.The
depends_on directives for all three services are commented out in docker-compose.yml. This means Docker Compose starts the Indexer, Manager, and Dashboard concurrently without waiting for upstream health checks. The Manager and Dashboard may log transient connection errors during startup until the Indexer is ready — this is expected behaviour. Uncomment the depends_on blocks if your environment requires strict start ordering.Service Images and Versions
All images are official Wazuh images from Docker Hub, pinned to version 4.14.5:| Service | Container Name | Image |
|---|---|---|
| Wazuh Indexer | wazuh.indexer | wazuh/wazuh-indexer:4.14.5 |
| Wazuh Manager | wazuh.manager | wazuh/wazuh-manager:4.14.5 |
| Wazuh Dashboard | wazuh.dashboard | wazuh/wazuh-dashboard:4.14.5 |
| Wazuh Agent (co-located) | wazuh.agent | wazuh/wazuh-agent:4.14.5 |
restart: always so they come back automatically after a host reboot or container crash.
Resource Limits
Thedocker-compose.yml includes commented-out resource constraint blocks for each service. These are disabled by default so you can assess actual usage before enforcing limits. Uncomment the relevant block to enable them.
Wazuh Indexer — up to 2 GB memory / 2 vCPUs, with a 1 GB reservation:
-Xms and -Xmx together whenever you change memory limits to avoid heap pressure.
Wazuh Manager — up to 1.5 GB / 1.5 vCPUs, with a 512 MB reservation:
ulimits blocks (memlock and nofile) that may be needed in high-throughput production environments. Uncomment and tune them alongside the memory limits.
Stopping and Restarting
Stop the entire stack (containers are removed; volumes and data are preserved):.env or config changes):