Useful virtual machine for cyber security - Wazuh
Posted on 25 May 2025 by Mino — 5 min

Post focuses on virtual machine with installed Wazuh XDR solution. Used technologies are, beside wazuh, only debian as hosting OS and docker for easier deployment.
Prerequisites
- Software
- Hardware / VM parameters
- CPU: 4 i* or ryzen * cores
- RAM: 8GB+
- Disk: 256GB
Wazuh
Wazuh did a great job on doing their installation guide very readable, so I'm not attempting to rewrite their words, maybe just to squish them into less text (link to the guide is here).
sudo sysctl -w vm.max_map_count=262144
git clone https://github.com/wazuh/wazuh-docker.git -b v4.12.0
cd wazuh-docker
docker-compose -f generate-indexer-certs.yml run --rm generator
I customized following files/variables under yml
.
File | Variable name | Notes |
---|---|---|
wazuh_dashboard/wazuh.yml |
password |
-- |
wazuh_indexer/internal_users.yml |
All hash with different values |
Run docker run --rm -ti wazuh/wazuh-indexer:4.11.2 bash /usr/share/wazuh-indexer/plugins/opensearch-security/tools/hash.sh to produce the hash |
wazuh_indexer_ssl_certs/wazuh.dashboard.pem |
Replace the whole file | See this guide for information on how to create custom signed certificates |
wazuh_indexer_ssl_certs/wazuh.dashboard-key.pem |
Replace the whole file | See this guide for information on how to create custom signed certificates |
Updated a few values based on the hashed passwords I changed using the script provided by wazuh also in the docker-compose.yml
and started the whole system.
docker-compose up -d
services:
wazuh.manager:
image: wazuh/wazuh-manager:4.11.2
hostname: wazuh.manager
restart: always
ulimits:
memlock:
soft: -1
hard: -1
nofile:
soft: 655360
hard: 655360
ports:
- "1514:1514"
- "1515:1515"
- "514:514/udp"
- "55000:55000"
environment:
- INDEXER_URL=https://wazuh.indexer:9200
- INDEXER_USERNAME=admin
- INDEXER_PASSWORD=[PASSWORD]
- FILEBEAT_SSL_VERIFICATION_MODE=full
- SSL_CERTIFICATE_AUTHORITIES=/etc/ssl/root-ca.pem
- SSL_CERTIFICATE=/etc/ssl/filebeat.pem
- SSL_KEY=/etc/ssl/filebeat.key
- API_USERNAME=wazuh-wui
- API_PASSWORD=[PASSWORD]
volumes:
- ./data/wazuh_api_configuration:/var/ossec/api/configuration
- ./data/wazuh_etc:/var/ossec/etc
- ./data/wazuh_logs:/var/ossec/logs
- ./data/wazuh_queue:/var/ossec/queue
- ./data/wazuh_var_multigroups:/var/ossec/var/multigroups
- ./data/wazuh_integrations:/var/ossec/integrations
- ./data/wazuh_active_response:/var/ossec/active-response/bin
- ./data/wazuh_agentless:/var/ossec/agentless
- ./data/wazuh_wodles:/var/ossec/wodles
- ./data/filebeat_etc:/etc/filebeat
- ./data/filebeat_var:/var/lib/filebeat
- ./config/wazuh_indexer_ssl_certs/root-ca-manager.pem:/etc/ssl/root-ca.pem
- ./config/wazuh_indexer_ssl_certs/wazuh.manager.pem:/etc/ssl/filebeat.pem
- ./config/wazuh_indexer_ssl_certs/wazuh.manager-key.pem:/etc/ssl/filebeat.key
- ./config/wazuh_cluster/wazuh_manager.conf:/wazuh-config-mount/etc/ossec.conf
wazuh.indexer:
image: wazuh/wazuh-indexer:4.11.2
hostname: wazuh.indexer
restart: always
ports:
- "9200:9200"
environment:
- "OPENSEARCH_JAVA_OPTS=-Xms1g -Xmx1g"
ulimits:
memlock:
soft: -1
hard: -1
nofile:
soft: 65536
hard: 65536
volumes:
- ./data/wazuh-indexer-data:/var/lib/wazuh-indexer
- ./config/wazuh_indexer_ssl_certs/root-ca.pem:/usr/share/wazuh-indexer/certs/root-ca.pem
- ./config/wazuh_indexer_ssl_certs/wazuh.indexer-key.pem:/usr/share/wazuh-indexer/certs/wazuh.indexer.key
- ./config/wazuh_indexer_ssl_certs/wazuh.indexer.pem:/usr/share/wazuh-indexer/certs/wazuh.indexer.pem
- ./config/wazuh_indexer_ssl_certs/admin.pem:/usr/share/wazuh-indexer/certs/admin.pem
- ./config/wazuh_indexer_ssl_certs/admin-key.pem:/usr/share/wazuh-indexer/certs/admin-key.pem
- ./config/wazuh_indexer/wazuh.indexer.yml:/usr/share/wazuh-indexer/opensearch.yml
- ./config/wazuh_indexer/internal_users.yml:/usr/share/wazuh-indexer/opensearch-security/internal_users.yml
wazuh.dashboard:
image: wazuh/wazuh-dashboard:4.11.2
hostname: wazuh.dashboard
restart: always
ports:
- 443:5601
environment:
- INDEXER_USERNAME=admin
- INDEXER_PASSWORD=[PASSWORD]
- WAZUH_API_URL=https://wazuh.manager
- DASHBOARD_USERNAME=kibanaserver
- DASHBOARD_PASSWORD=[PASSWORD]
- API_USERNAME=wazuh-wui
- API_PASSWORD=[PASSWORD]
volumes:
- ./config/wazuh_indexer_ssl_certs/wazuh.dashboard.pem:/usr/share/wazuh-dashboard/certs/wazuh-dashboard.pem
- ./config/wazuh_indexer_ssl_certs/wazuh.dashboard-key.pem:/usr/share/wazuh-dashboard/certs/wazuh-dashboard-key.pem
- ./config/wazuh_indexer_ssl_certs/root-ca.pem:/usr/share/wazuh-dashboard/certs/root-ca.pem
- ./config/wazuh_dashboard/opensearch_dashboards.yml:/usr/share/wazuh-dashboard/config/opensearch_dashboards.yml
- ./config/wazuh_dashboard/wazuh.yml:/usr/share/wazuh-dashboard/data/wazuh/config/wazuh.yml
- ./data/wazuh-dashboard-config:/usr/share/wazuh-dashboard/data/wazuh/config
- ./data/wazuh-dashboard-custom:/usr/share/wazuh-dashboard/plugins/wazuh/public/assets/custom
depends_on:
- wazuh.indexer
links:
- wazuh.indexer:wazuh.indexer
- wazuh.manager:wazuh.manager
Rulesets
- Wazuh-Rules from SOC FORTRESS - even-though this rule-set contains script for easy deployment, I prefer a way of deploying it on my own, for overall better understanding. For this purpose I checked the script and run following commands on my own (https://github.com/socfortress/Wazuh-Rules/blob/main/wazuh_socfortress_rules.sh).
# all commands are executed as root for simplicity
mkdir ~/ruleset && cd ~/ruleset && wget 'https://github.com/socfortress/Wazuh-Rules/archive/refs/heads/main.zip'
unzip main.zip
find ~/ruleset -iname '*xml' -exec mv '{}' '/home/god/data/wazuh_etc/rules' \;
cd /home/god/data/wazuh_etc/rules
mv decoder-* ../decoders/
mv yara_decoders.xml ../decoders/
mv auditd_decoders.xml ../decoders/
mv naxsi-opnsense_decoders.xml ../decoders/
mv maltrail_decoders.xml ../decoders/
cd /home/god && docker compose restart
This post was written without the help of AI.