Wazuh в Docker Compose: готовый файл
Если вам нужно видеть, что происходит на серверах — кто логинится, какие файлы меняются, есть ли следы компрометации — и при этом не платить за коммерческий SIEM, Wazuh закрывает эту задачу почти полностью бесплатно. Проблема в том, что развернуть его руками долго: три сервиса, сертификаты между ними, куча переменных окружения, которые легко перепутать. Ниже — рабочий docker-compose.yml, который поднимает Wazuh с нуля, и разбор, что в нём происходит и куда чаще всего утыкаются при первом запуске.
Содержание
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →Что такое Wazuh и зачем он нужен
Wazuh — это open source платформа класса SIEM/XDR: она собирает логи и события безопасности с серверов, анализирует их по правилам, ищет аномалии и складывает всё в единую консоль с алертами. Изначально Wazuh был форком OSSEC (агент-серверная система обнаружения вторжений на хостах), но за последние годы вокруг него вырос полноценный стек — свой поисковый индекс (форк OpenSearch/Elasticsearch) и веб-дашборд.
Из коробки Wazuh умеет:
- анализировать логи (syslog, журналы приложений, Windows Event Log) на предмет подозрительных паттернов;
- мониторить целостность файлов (FIM) — кто и когда изменил конфиг или бинарник;
- обнаруживать руткиты и аномальное поведение процессов;
- проверять конфигурацию хостов на соответствие CIS-бенчмаркам (compliance-аудит);
- собирать инвентарь ПО и уязвимостей по установленным пакетам;
- реагировать активно — например, банить IP через встроенный active response.
Для одиночного VPS с парой сервисов это, возможно, избыточно — там хватит fail2ban и базового аудита. Но если у вас несколько серверов, инфраструктура растёт, или требуется что-то предъявить аудитору (PCI DSS, ISO 27001, просто внутренняя политика безопасности) — Wazuh даёт централизованную картину по всем хостам сразу.
Архитектура: три сервиса и зачем каждый нужен
Wazuh в контейнерном виде — это не один процесс, а три взаимосвязанных сервиса:
| Сервис | Роль | Порты |
|---|---|---|
wazuh.indexer | хранилище и полнотекстовый поиск по событиям (форк OpenSearch) | 9200 (внутренний) |
wazuh.manager | ядро: правила, декодеры, приём событий от агентов, API | 1514/udp, 1515, 55000 |
wazuh.dashboard | веб-интерфейс поверх индексатора | 443 |
Агенты (легковесный демон, который ставится на каждый мониторимый сервер) шлют события на manager по порту 1514, manager обрабатывает их по правилам и пишет результат в indexer, а dashboard визуализирует то, что лежит в индексаторе. Все три сервиса общаются между собой по TLS — отсюда требование сертификатов, о котором ниже.
Важный нюанс: сам indexer (на базе OpenSearch) — самый тяжёлый компонент по памяти. Даже на однохостовой установке "для теста" закладывайте не меньше 4 ГБ RAM под весь стек, а для рабочей нагрузки с несколькими агентами и историей логов — от 8 ГБ. Это ориентир, а не гарантия: конкретное потребление зависит от числа агентов и объёма событий, у вас цифры могут отличаться заметно.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверМинимальные требования и подготовка сервера
Перед разворачиванием:
# Docker Engine + Compose plugin (если ещё не стоит)
curl -fsSL https://get.docker.com | sh
sudo usermod -aG docker $USER
# OpenSearch (движок индексатора) требует увеличенного vm.max_map_count
sudo sysctl -w vm.max_map_count=262144
echo 'vm.max_map_count=262144' | sudo tee -a /etc/sysctl.conf
Последняя команда критична — без неё indexer падает при старте с ошибкой max virtual memory areas vm.max_map_count is too low. Это самая частая причина, почему "docker compose up" не взлетает с первого раза.
Создайте рабочую директорию и структуру для конфигов и сертификатов:
mkdir -p ~/wazuh-docker/config/wazuh_indexer_ssl_certs
cd ~/wazuh-docker
Готовый docker-compose.yml
Ниже — минимальная однохостовая конфигурация: все три сервиса на одном сервере, с самоподписанными сертификатами и персистентными volume для данных.
services:
wazuh.manager:
image: wazuh/wazuh-manager:4.9.2
hostname: wazuh.manager
restart: always
ports:
- "1514:1514"
- "1515:1515"
- "514:514/udp"
- "55000:55000"
environment:
- INDEXER_URL=https://wazuh.indexer:9200
- INDEXER_USERNAME=admin
- INDEXER_PASSWORD=${INDEXER_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=${API_PASSWORD}
volumes:
- wazuh_api_configuration:/var/ossec/api/configuration
- wazuh_etc:/var/ossec/etc
- wazuh_logs:/var/ossec/logs
- wazuh_queue:/var/ossec/queue
- ./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
networks:
- wazuh-net
depends_on:
- wazuh.indexer
wazuh.indexer:
image: wazuh/wazuh-indexer:4.9.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:
- 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
networks:
- wazuh-net
wazuh.dashboard:
image: wazuh/wazuh-dashboard:4.9.2
hostname: wazuh.dashboard
restart: always
ports:
- "443:5601"
environment:
- INDEXER_USERNAME=admin
- INDEXER_PASSWORD=${INDEXER_PASSWORD}
- WAZUH_API_URL=https://wazuh.manager
- DASHBOARD_USERNAME=kibanaserver
- DASHBOARD_PASSWORD=${DASHBOARD_PASSWORD}
- API_USERNAME=wazuh-wui
- API_PASSWORD=${API_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
- wazuh-dashboard-config:/usr/share/wazuh-dashboard/data/wazuh/config
- wazuh-dashboard-custom:/usr/share/wazuh-dashboard/plugins/wazuh/public/assets/custom
networks:
- wazuh-net
depends_on:
- wazuh.indexer
networks:
wazuh-net:
driver: bridge
volumes:
wazuh_api_configuration:
wazuh_etc:
wazuh_logs:
wazuh_queue:
wazuh-indexer-data:
wazuh-dashboard-config:
wazuh-dashboard-custom:
Пароли вынесены в .env рядом с compose-файлом:
cat > .env <<'EOF'
INDEXER_PASSWORD=ЗамениНаСложныйПароль1
API_PASSWORD=ЗамениНаСложныйПароль2
DASHBOARD_PASSWORD=ЗамениНаСложныйПароль3
EOF
chmod 600 .env
Версии образов (4.9.2 в примере) стоит сверить с актуальным релизом на Docker Hub Wazuh на момент установки — проект выпускает обновления регулярно, и слепо тянуть старый тег означает пропустить фиксы безопасности.
Генерация сертификатов и первый запуск
Три сервиса общаются по TLS, и без сертификатов indexer откажется стартовать. Официальный путь — утилита wazuh-certs-generator, которая работает через отдельный конфиг:
cat > config.yml <<'EOF'
nodes:
indexer:
- name: wazuh.indexer
ip: wazuh.indexer
server:
- name: wazuh.manager
ip: wazuh.manager
dashboard:
- name: wazuh.dashboard
ip: wazuh.dashboard
EOF
docker run --rm -ti \
-v "$(pwd)/config.yml:/config/config.yml" \
-v "$(pwd)/config/wazuh_indexer_ssl_certs/:/certificates/" \
wazuh/wazuh-certs-generator:0.0.2
Эта команда создаёт корневой CA и по сертификату на каждый узел прямо в config/wazuh_indexer_ssl_certs/, куда их и подключает compose-файл выше. Дальше — обычный запуск:
docker compose up -d
docker compose logs -f wazuh.indexer # дождитесь "started" перед следующим шагом
Indexer поднимается дольше остальных (обычно минуту-две на первый старт, конкретное время зависит от диска и памяти сервера) — не спешите ругать конфиг, если он ещё не готов. Проверить статус кластера индексатора:
curl -k -u admin:${INDEXER_PASSWORD} https://localhost:9200/_cluster/health?pretty
Дашборд открывается по https://ваш_ip/ (порт 443), логин по умолчанию admin с паролем из .env. Сертификат самоподписанный — браузер предупредит, это ожидаемо; для продакшена стоит поставить обратный прокси с Let's Encrypt перед dashboard или сразу настроить свой SSL-терминатор.
Подключение агентов для мониторинга
Wazuh без агентов — это просто пустая консоль. Агент ставится на каждый сервер, за которым нужно наблюдать, и указывает на manager. На Ubuntu/Debian:
curl -s https://packages.wazuh.com/key/GPG-KEY-WAZUH | gpg --dearmor -o /usr/share/keyrings/wazuh.gpg
echo "deb [signed-by=/usr/share/keyrings/wazuh.gpg] https://packages.wazuh.com/4.x/apt/ stable main" | \
tee /etc/apt/sources.list.d/wazuh.list
apt update && WAZUH_MANAGER='адрес_вашего_manager' apt install -y wazuh-agent
systemctl enable --now wazuh-agent
Проверить, что агент появился в manager: docker exec -it <container_wazuh.manager> /var/ossec/bin/agent_control -l.
Регистрация по умолчанию идёт через автоматическую авторизацию на порту 1515 — для продакшена лучше включить проверку по паролю (authd.pass в конфиге manager) или ограничить порт 1515 firewall'ом до момента регистрации, чтобы посторонний хост не смог примазаться к вашей группе агентов.
Если у вас уже есть VPN между серверами — например, разворачивали стек VPN в Docker Compose — логично слать трафик агент-manager через него, а не через открытый интернет, тогда порт 1514 наружу вообще не публикуется.
Настройка правил и алертов под задачу
Из коробки Wazuh уже включает сотни правил (SSH-брутфорс, изменение системных файлов, попытки эскалации привилегий и т.д.), но полезность SIEM определяется тем, насколько правила подогнаны под вашу инфраструктуру. Базовые шаги:
- Файловый мониторинг (FIM). В
/var/ossec/etc/ossec.confна агенте укажите директории для отслеживания:<syscheck><directories check_all="yes" realtime="yes">/etc,/usr/bin,/usr/sbin,/var/www/html</directories></syscheck>.
- Свои правила. Кастомные декодеры и правила кладутся в
/var/ossec/etc/rules/local_rules.xmlна manager (томwazuh_etcв compose-файле) — например, правило на подозрительный User-Agent в логах nginx или на серию неудачных попыток входа в вашу CMS.
- Active response. Можно настроить автоматическую реакцию — например, бан IP через iptables при срабатывании правила брутфорса, аналогично тому, как это делает fail2ban, но с централизованным управлением со всех серверов сразу.
- Compliance-модули. Для CIS-бенчмарков и PCI DSS/HIPAA-отчётов включите соответствующие wodles в конфиге manager — они периодически прогоняют проверки конфигурации на агентах и складывают результат в те же дашборды.
Если Wazuh стоит не ради галочки, а для реального compliance-аудита с логами VPN-подключений, посмотрите отдельный разбор интеграции VPN и SIEM для комплаенса — там про то, какие именно события VPN-сервера стоит заворачивать в SIEM и зачем.
Типичные проблемы и что делать
- Indexer не стартует, в логах
vm.max_map_count is too low. Забылиsysctl -w vm.max_map_count=262144на хосте — контейнер не может выставить этот параметр сам. - Manager не достучаться до indexer, SSL handshake failed. Почти всегда рассинхрон сертификатов: имена в
config.ymlпри генерации должны буква в букву совпадать сhostname:сервисов в compose-файле. - Dashboard висит на экране ожидания индексатора. Обычно индексатор ещё не поднялся полностью, либо пароли в
.envне совпадают с тем, что прописано вinternal_users.yml— сверьте оба файла при первом запуске. - Агент не появляется в списке на manager. Проверьте, что порты 1515 (регистрация) и 1514 (события) реально открыты между хостами в firewall, а не только опубликованы в compose.
- Indexer съедает память сервера.
OPENSEARCH_JAVA_OPTSв примере жёстко держит heap на 1 ГБ — для рабочей нагрузки увеличивайте вместе с общим RAM, ориентируясь наdocker stats, а не на цифры по умолчанию. - После
docker compose downпропали события. Проверьте, что не запускали с флагом-v— он удаляет именованные volumes вместе с данными.
Если в целом Wazuh кажется избыточным для вашего масштаба, а нужен просто централизованный сбор и разбор логов без правил безопасности — присмотритесь к более лёгким вариантам вроде Grafana Loki или почитайте про ротацию логов, если задача — просто не забить диск.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверНужны сами нейросети для контента?
Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.
Частые вопросы
Сколько ресурсов реально нужно на одном сервере?
Для теста с 1-3 агентами хватит 4 ГБ RAM и 2 vCPU. Для продакшена с десятком агентов и хранением истории от 30 дней закладывайте от 8 ГБ RAM и SSD-диск — indexer активно пишет и читает с диска, на HDD производительность просядет заметно.
Можно ли развернуть indexer, manager и dashboard на разных серверах?
Да, это рекомендованная схема для нагруженных инсталляций — тот же compose-файл разбивается на три отдельных, сервисы общаются по внутренней сети или VPN, а не по localhost. Файл в этой статье — однохостовый вариант для старта.
Wazuh правда бесплатный?
Ядро платформы (агент, manager, indexer, dashboard) — open source под GPLv2, без ограничений по числу агентов. Компания Wazuh Inc. продаёт коммерческую поддержку и облачный SaaS-вариант, но self-hosted версия из этой статьи полностью бесплатна в использовании.
Чем Wazuh отличается от связки Grafana + Prometheus?
Это разные классы инструментов: Grafana с Prometheus — про метрики производительности (CPU, память, latency), Wazuh — про события безопасности (кто зашёл, что изменилось, есть ли атака). Их часто ставят рядом, а не вместо друг друга.
Нужен ли отдельный сервер под Wazuh или можно на том же, где крутится сайт?
Технически можно, но не рекомендуется: indexer нагружает диск и память, а сам сервер, за которым наблюдают, логичнее держать отдельно от системы наблюдения — иначе при компрометации сайта под угрозой окажется и сама SIEM.
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →