Skip to main content

01.1 Wazuh Installation

Einleitung

Wazuh ist mit einem einzigen Herstellerkommando erstaunlich schnell installiert. Das heißt aber noch lange nicht, dass daraus automatisch ein gut betriebener Security-Server wird. Die eigentliche Arbeit steckt in der VM, den Dateisystemen, der Zeitsynchronisation, den Netzgrenzen und einer Installation, die sich später noch nachvollziehen lässt.

Diese Seite enthält deshalb beides:

  • die Rahmenbedingungen, mit denen sich Architektur und Größe sinnvoll planen lassen;
  • eine echte Schritt-für-Schritt-Anleitung auf Basis meiner Installation im Homelab.

Mein Ergebnis ist eine native All-in-one-Installation von Wazuh 4.14.7 auf Rocky Linux 10.2. Manager, Indexer, Dashboard und Filebeat laufen gemeinsam auf einer Proxmox-VM. Die Anleitung ist absichtlich so geschrieben, dass man sie für eine neue Umgebung wiederverwenden kann. Interne Namen und Adressen sind als Beispiel erkennbar; Passwörter, Schlüssel und andere Secrets fehlen natürlich vollständig.

Kurz erklärt: Welche Komponenten werden installiert?

Wazuh besteht zentral aus drei Komponenten:

  • Wazuh Server: nimmt Agentendaten an, dekodiert Ereignisse, wertet Regeln aus und verwaltet die Agents;
  • Wazuh Indexer: indexiert und speichert Alerts und weitere sicherheitsrelevante Daten;
  • Wazuh Dashboard: stellt Suche, Visualisierung und Administration bereit.

Auf den überwachten Systemen läuft normalerweise ein Wazuh-Agent. Filebeat transportiert die vom Manager erzeugten Alerts zum Indexer.

Welche Bauform passt?

Modell Aufbau Geeignet für Wesentliche Grenze
All-in-one Server, Indexer und Dashboard auf einem Host Labor, Homelab, kleine Umgebung gemeinsamer Ausfallpunkt, konkurrierende Ressourcen
Getrennter Single-Node-Aufbau Komponenten auf getrennten Hosts mittlere Umgebung oder klare Ressourcentrennung noch keine Hochverfügbarkeit
Multi-Node Server- und Indexer-Cluster, optional mehrere Dashboards hohe Ereignisrate, hohe Verfügbarkeit, große Umgebung deutlich mehr Betriebs- und Zertifikatsaufwand

Für zuhause oder eine kleine, kontrollierte Umgebung ist All-in-one meistens genau richtig. Man muss daraus nicht künstlich einen Cluster bauen. Allerdings sitzt dann alles in derselben VM: Ist sie weg oder die Platte voll, ist auch die komplette Sicherheitsoberfläche weg. Backup, Retention und Kapazitätsüberwachung gehören deshalb von Anfang an dazu.

Mein Aufbau im Homelab

Die folgende Installation ist kein ausgedachtes Beispiel, sondern mein konkret betriebener Aufbau. Interne Namen, IDs und Adressen sind für die öffentliche Fassung durch neutrale Dokumentationswerte ersetzt:

Baustein Homelab-Wert Für eine eigene Umgebung
Architektur native All-in-one-Installation für ungefähr 1 bis 25 Agents ein guter Start
Hypervisor Proxmox VE jeder sauber unterstützte Hypervisor funktioniert
VM wazuh01 eigene ID und eigenen Namen verwenden
CPU 4 vCPU 4 vCPU als sinnvoller kleiner Startwert
RAM 12 GiB mindestens 8 GiB; für etwas Reserve 12 GiB
Systemdisk 40 GiB auf schnellem Storage Rocky, Pakete und temporäre Updates
Managerdisk 50 GiB, davon 40 GiB als LV /var/ossec
Indexerdisk 150 GiB, davon 120 GiB als LV /var/lib/wazuh-indexer
Betriebssystem Rocky Linux 10.2 Minimal Rocky 10 war der von mir getestete RHEL-kompatible Weg
Hostname wazuh01.example.internal dauerhaften FQDN vorab festlegen
Management-IP 192.0.2.10/24 Beispielwert; feste Adresse oder feste DHCP-Reservierung verwenden
Dashboard interner TLS-Reverse-Proxy alternativ zunächst Wazuh-eigenes HTTPS verwenden
Indexer-Heap 2 GiB fest für diese kleine 12-GiB-All-in-one-VM bewusst gewählt
Zeit drei PTB-Server mit NTS eigene vertrauenswürdige NTS-Quellen sind ebenfalls möglich

Eine getrennte Testumgebung wird bewusst nicht überwacht. Erwartet werden damit grob 15 bis 20 bekannte Systeme statt eines unkontrollierten Agenten-Wachstums.

Wazuh nennt für die zentralen Komponenten aktuell unter anderem RHEL 10 und CentOS Stream 10, Rocky Linux 10 aber nicht separat. Rocky 10.2 war bei mir deshalb ein bewusster Kompatibilitätstest. Pakete, Dienste, API, Indexer und SELinux funktionierten ohne distributionsspezifischen Workaround. Wer strikt innerhalb der ausdrücklich genannten Systeme bleiben möchte, verwendet für dieselben Schritte RHEL 10 oder CentOS Stream 10.

Sizing: Was empfiehlt Wazuh?

Wazuh nennt für eine All-in-one-Installation mit etwa 90 Tagen durchsuchbarer Alert-Historie folgende Richtwerte:

Anzahl Agents vCPU RAM Speicher für 90 Tage
1–25 4 8 GiB 50 GB
25–50 8 8 GiB 100 GB
50–100 8 8 GiB 200 GB

Die Tabelle ist ein Startpunkt, keine Garantie. Ein einziger sehr gesprächiger Agent kann mehr Last verursachen als zwanzig ruhige Systeme. Das habe ich mit ungefiltertem Journald und Docker-Healthchecks schon recht anschaulich ausprobiert :D

Für den Wazuh Server allein nennt der Hersteller kleinere Komponentenwerte. Diese dürfen nicht mit dem Bedarf eines All-in-one-Systems verwechselt werden: Der Indexer ist der deutlich speicherhungrigere Teil.

Meine praktische Planungshilfe

Umgebung Architektur Startwert CPU/RAM Nutzbarer Datenspeicher Hinweise
Labor, 1–10 Agents All-in-one 4 vCPU / 8 GiB 80–150 GiB kurze Aufbewahrung, keine HA-Anforderung
Homelab oder klein produktiv, 10–25 Agents All-in-one 4–8 vCPU / 12–16 GiB 150–300 GiB getrennte virtuelle Disks und tägliches Backup
Kleine Firma, 25–50 Agents kräftiges All-in-one oder getrennte Komponenten 8 vCPU / 16 GiB beim All-in-one 250–500 GiB Last- und Wiederherstellungstest vor Produktivstart
Mittel, 50–250 Agents Server, Indexer und Dashboard trennen komponentenbezogen ab 4–8 vCPU / 8–16 GiB ab 500 GiB, nach Messwert Indexer zuerst skalierbar planen
Groß oder hochverfügbar Multi-Node mindestens drei Indexer-Nodes und mehrere Server-Nodes nach Lasttest nach APS, Replikation und Aufbewahrung Load Balancer, Quorum, Zertifikats- und DR-Konzept erforderlich

Spätestens in der Pilotphase sollte man Alerts und Events pro Sekunde, tägliches Indexwachstum, FIM-Umfang, Vulnerability Detection, Syscollector und laute Logquellen messen. Für Datenträger plane ich zusätzlich mindestens 20 bis 30 Prozent freie Betriebsreserve ein.

Warum drei virtuelle Disks und LVM?

Mein Layout trennt Betriebssystem, Managerdaten und Indexerdaten:

Disk Volume Group / Logical Volume Mount Brutto / LV Reserve
Systemdisk rl_wazuh/root / 40 / 30 GiB 6,41 GiB plus Bootbereiche
Managerdisk vg_wazuh_manager/lv_var_ossec /var/ossec 50 / 40 GiB knapp 10 GiB
Indexerdisk vg_wazuh_indexer/lv_wazuh_indexer /var/lib/wazuh-indexer 150 / 120 GiB knapp 30 GiB

Jede virtuelle Disk besitzt ihre eigene VG. Keine VG spannt mehrere Proxmox-Disks auf. Damit bleiben Backup-, Fehler- und Wachstumsgrenzen sichtbar. Wird eine Disk später in Proxmox vergrößert, folgen im Gast pvresize und lvextend --resizefs; ext4 wächst dabei online.

/var/ossec darf nicht mit noexec gemountet werden, weil dort Wazuh-Binaries und Active-Response-Skripte liegen. Ein bereits mit noexec gehärtetes /tmp braucht für die Indexerinstallation außerdem die von Wazuh dokumentierte Sonderbehandlung. Ich habe /tmp deshalb erst nach der Installation weiter gehärtet.

Vor dem Start festlegen

Bevor die erste VM bootet, sollten diese Werte auf einem Zettel stehen:

  • dauerhafter FQDN und IP-Adresse;
  • Gateway und DNS-Server;
  • Admin- und VPN-Netze;
  • gegebenenfalls Adresse des Reverse-Proxys;
  • erwartete Agentennetze;
  • gewünschte Aufbewahrungsdauer;
  • Speicherort für Installerarchiv, Passwörter und private Schlüssel;
  • Backup- und Rückweg für die frische VM.

Die öffentliche Anleitung verwendet bewusst reservierte Beispielnetze. Wer sie nachbaut, ersetzt diese Werte durch die eigenen:

FQDN:             wazuh01.example.internal
IPv4:             192.0.2.10/24
Gateway:          192.0.2.1
DNS:              192.0.2.53, 192.0.2.54
Admin-LAN:        192.0.2.0/24
VPN:              198.51.100.0/24
Reverse-Proxy:    192.0.2.20/32
Dashboard-Name:   wazuh.example.internal

Schritt 1: Die Proxmox-VM anlegen

Die VM wurde mit diesen Einstellungen erstellt:

  • Q35-Maschine mit OVMF/UEFI;
  • Secure-Boot-Schlüssel und EFI-Disk;
  • 4 vCPU und 12 GiB RAM;
  • VirtIO SCSI Single;
  • VirtIO-Netzwerkkarte;
  • QEMU Guest Agent in der VM-Konfiguration aktiviert;
  • SSD-Flag, Discard und I/O-Thread für die virtuellen Datendisks;
  • 40-GiB-Systemdisk, 50-GiB-Managerdisk und 150-GiB-Indexerdisk;
  • Rocky-Linux-Minimal-ISO als virtuelles DVD-Laufwerk.

Die System- und Managerdisk liegen bei mir auf dem schnellen NVMe-Storage, die größere Indexerdisk auf einem separaten SSD-Mirror. Das ist kein Muss. Für den Indexer zählt vor allem verlässliche Latenz und genügend freie Kapazität.

Ballooning ist für einen Indexer keine besonders schöne Überraschung. Wenn der Hypervisor RAM aggressiv zurückholt, konkurriert die JVM mit Manager und Dashboard. Für einen stabilen Betrieb sollte der zugesagte RAM deshalb fest oder zumindest verlässlich reserviert sein.

Rocky-Linux-Installer

Der echte Start meiner Rocky-Installation – für die öffentliche Fassung auf das Installerfenster zugeschnitten.

Schritt 2: Rocky Linux Minimal installieren

Im Installer habe ich bewusst nur eine schlanke Serverbasis gewählt:

  1. Sprache und Tastatur kontrollieren – in der Proxmox-Konsole war bei mir zwischenzeitlich Y und Z vertauscht.
  2. Minimal Install auswählen, keine Desktopoberfläche.
  3. Zeitzone Europe/Berlin setzen.
  4. Netzwerkschnittstelle aktivieren, statische Adresse und FQDN eintragen.
  5. Einen persönlichen Admin-Benutzer anlegen und der Gruppe wheel hinzufügen.
  6. Root-Login nicht als normalen Administrationsweg verwenden.
  7. Nur die 40-GiB-Systemdisk für das Betriebssystem auswählen.
  8. Benutzerdefiniertes LVM-Layout anlegen.

Das Systemlayout bestand aus:

  • EFI-Systempartition: 600 MiB, vfat;
  • /boot: 1 GiB, ext4;
  • Root-LV: 30 GiB, ext4;
  • Swap-LV: 2 GiB;
  • verbleibende 6,41 GiB als freie Extents in der Root-VG.

Die Manager- und Indexerdisk wurden im Installer nicht formatiert. Das kam erst nach dem ersten Boot mit zusätzlichen Sicherheitsprüfungen.

Benutzerdefiniertes LVM-Layout der Systemdisk

Das Root-LV belegt bewusst nicht die gesamte VG; ein kleiner Puffer bleibt für spätere Erweiterungen frei. Host- und VG-Namen sind im öffentlichen Bild neutralisiert.

Vor dem Klick auf Installation beginnen noch einmal Netzwerk, Software, Zieldisk, Zeitzone und Benutzer kontrollieren. Ein versehentlich ausgewählter Datenträger ist an dieser Stelle deutlich leichter zu korrigieren als später.

Geprüfte Rocky-Installationszusammenfassung

Letzter Kontrollblick vor der Installation: Software, Zieldisk, Netzwerk, Zeit und Benutzer passen zusammen.

Schritt 3: Erster Boot, Updates und Guest Agent

Nach dem ersten Login wurde Rocky vollständig aktualisiert und nur die benötigte Basis ergänzt:

sudo dnf -y update
sudo dnf -y install qemu-guest-agent lvm2 chrony curl tar
sudo systemctl enable --now qemu-guest-agent chronyd firewalld sshd
sudo reboot

Danach prüfen:

cat /etc/rocky-release
uname -r
hostnamectl
getenforce
systemctl is-active qemu-guest-agent chronyd firewalld sshd

Bei mir war das Ergebnis Rocky Linux 10.2, SELinux Enforcing und ein über die Proxmox-API erreichbarer Guest Agent.

Das ISO wurde nach erfolgreichem Boot aus dem virtuellen CD-Laufwerk entfernt, damit die VM später nicht versehentlich wieder im Installer landet.

Schritt 4: Manager- und Indexerdisk vorbereiten

Hier bitte nicht blind /dev/sdb und /dev/sdc übernehmen. Die Zuordnung hat sich auf meiner VM nach einem Neustart tatsächlich geändert. Vor jedem destruktiven Schritt wurden Typ, Größe und vorhandene Signaturen geprüft:

lsblk -e7 -o NAME,PATH,SIZE,TYPE,FSTYPE,MOUNTPOINTS,MODEL,SERIAL
sudo wipefs -n /dev/sdb
sudo wipefs -n /dev/sdc
sudo blockdev --getsize64 /dev/sdb
sudo blockdev --getsize64 /dev/sdc

Erst nachdem eindeutig feststand, welche leere Disk 50 GiB und welche 150 GiB groß war, wurden PVs, VGs und LVs angelegt. In meiner Installationssitzung waren das folgende Geräte; in einer anderen VM können sie anders heißen:

sudo pvcreate /dev/sdb /dev/sdc
sudo vgcreate vg_wazuh_manager /dev/sdb
sudo vgcreate vg_wazuh_indexer /dev/sdc

sudo lvcreate --size 40G --name lv_var_ossec vg_wazuh_manager
sudo lvcreate --size 120G --name lv_wazuh_indexer vg_wazuh_indexer

sudo mkfs.ext4 -m 1 -L wazuh_ossec \
  /dev/vg_wazuh_manager/lv_var_ossec
sudo mkfs.ext4 -m 1 -L wazuh_indexer \
  /dev/vg_wazuh_indexer/lv_wazuh_indexer

sudo install -d -m 0755 /var/ossec /var/lib/wazuh-indexer

Die Dateisysteme wurden per UUID in /etc/fstab eingetragen. Sinngemäß sieht das so aus:

UUID=<MANAGER-UUID> /var/ossec ext4 defaults,nodev,nosuid,x-systemd.device-timeout=30s 0 2
UUID=<INDEXER-UUID> /var/lib/wazuh-indexer ext4 defaults,nodev,nosuid,x-systemd.device-timeout=30s 0 2

Die UUIDs liefert blkid. Danach unbedingt testen:

sudo systemctl daemon-reload
sudo mount -a
sudo findmnt --verify --verbose
findmnt /var/ossec
findmnt /var/lib/wazuh-indexer
sudo pvs
sudo vgs
sudo lvs
df -hT / /var/ossec /var/lib/wazuh-indexer

Ein fehlgeschlagener Datenmount darf nicht unbemerkt dazu führen, dass Wazuh in das Root-Dateisystem schreibt. Deshalb sind die Mounts bei mir zwingend und nicht mit nofail versehen.

Schritt 5: SSH, Zeit und kleine OS-Baseline

Der Admin-Zugang verwendet ausschließlich SSH-Keys. Erst einen zweiten, erfolgreichen Key-Login testen und danach Passwort- und Root-Login abschalten:

PermitRootLogin no
PubkeyAuthentication yes
PasswordAuthentication no
KbdInteractiveAuthentication no
PermitEmptyPasswords no
X11Forwarding no
MaxAuthTries 4
LoginGraceTime 30
AllowGroups wheel

Allgemeines sudo verlangt für das menschliche Administrationskonto weiterhin das Benutzerpasswort. Automationskonten erhalten – wenn überhaupt – nur eng begrenzte NOPASSWD-Kommandos und kein pauschales NOPASSWD: ALL.

Für die Zeit verwende ich die ersten drei öffentlichen PTB-Server mit NTS:

server ptbtime1.ptb.de iburst nts
server ptbtime2.ptb.de iburst nts
server ptbtime3.ptb.de iburst nts
authselectmode require
ntsdumpdir /var/lib/chrony

Nach einem Chrony-Neustart prüfen:

sudo systemctl restart chronyd
chronyc tracking
chronyc sources -n
chronyc authdata

Alle drei Quellen müssen authentifiziert sein. Eine gute Uhr ist bei Wazuh kein Luxus: Zertifikate, Korrelationen und forensische Zeitlinien hängen daran.

Zusätzlich habe ich Swap nur als Notreserve konfiguriert:

vm.swappiness = 1

Die Einstellung wird beispielsweise unter /etc/sysctl.d/99-wazuh.conf abgelegt und mit sudo sysctl --system aktiviert.

Schritt 6: Snapshot und Vorabkontrolle

Vor Wazuh wurde der Proxmox-Snapshot pre-wazuh-4_14_7 ohne RAM-Zustand angelegt. Ein Snapshot ist kein Backup, aber für den unmittelbaren Rückweg bei einer fehlgeschlagenen Erstinstallation sehr praktisch.

Vor dem Installer sollten diese Punkte stimmen:

hostname --fqdn
getent ahosts "$(hostname --fqdn)"
timedatectl status
getenforce
sudo findmnt --verify
df -hT / /var/ossec /var/lib/wazuh-indexer
sudo ss -lntup

Die beiden Wazuh-Datenmounts müssen wirklich aktiv und leer sein. Auf ext4 ist ein Verzeichnis lost+found normal.

Schritt 7: Wazuh-Assistent herunterladen und festhalten

Ich habe den offiziellen Assistenten für Wazuh 4.14 verwendet:

cd /tmp
curl --fail --silent --show-error --remote-name \
  https://packages.wazuh.com/4.14/wazuh-install.sh
sha256sum wazuh-install.sh
sudo install -o root -g root -m 0700 \
  wazuh-install.sh /root/wazuh-install.sh
sudo /root/wazuh-install.sh --help

Der bei meinem Lauf gespeicherte SHA-256-Wert war:

8ebe9514688ace8af9445805e8887cd491dd9f95fa9d421a70f0ea012ab06f3a

Der Wert dokumentiert exakt das von mir verwendete Skript. Er ist nicht als ewiger Sollwert für jeden späteren Download gedacht – der Hersteller kann den Assistenten innerhalb eines Versionszweigs aktualisieren. Deshalb bei jeder Neuinstallation selbst herunterladen, Prüfsumme erfassen und Release Notes lesen.

Wenn /tmp bereits noexec ist, das Skript nicht einfach mit immer weiteren Ausnahmen irgendwie zum Laufen zwingen. Wazuh beschreibt für gehärtete Systeme eine eigene Indexer-Vorbereitung. Das Skript wurde aus /root gestartet; die weitere Härtung von /tmp folgte erst danach.

Schritt 8: Wazuh wirklich installieren

Der offizielle Quickstart verwendet kurz -a. Der von mir dokumentierte Aufruf war die ausgeschriebene Variante:

sudo bash /root/wazuh-install.sh --all-in-one --overwrite

Warum --overwrite? Der Assistent wertete die bereits vorhandenen Mountpoints /var/ossec und /var/lib/wazuh-indexer als Installationsreste, obwohl dort nur die neuen, leeren ext4-Dateisysteme mit lost+found lagen. Ich habe vor dem Lauf geprüft, dass es wirklich keine alte Installation und keine zu erhaltenden Daten gab. Erst dann wurde --overwrite verwendet.

Ohne diese ganz konkrete Situation gehört --overwrite nicht gedankenlos in jeden Installationsbefehl. Auf einem bestehenden System könnte es genau die Daten beseitigen, die man eigentlich retten wollte.

Der Assistent installiert und verbindet:

  • wazuh-manager;
  • wazuh-indexer;
  • wazuh-dashboard;
  • filebeat;
  • Zertifikate und initiale Dienstkonten.

Am Ende erscheinen Dashboard-Adresse und Admin-Passwort. Diese Ausgabe nicht in Terminalmitschnitte, Tickets oder Git kopieren.

Schritt 9: Installerarchiv und Secrets sichern

Der Assistent legt wazuh-install-files.tar an. Darin stecken Zertifikate, private Schlüssel und Passwörter. Das Archiv ist kein gewöhnliches Installationslog, sondern ein Secret:

sudo chown root:root wazuh-install-files.tar
sudo chmod 0600 wazuh-install-files.tar
sudo tar -O -xvf wazuh-install-files.tar \
  wazuh-install-files/wazuh-passwords.txt

Die letzte Ausgabe dient nur zur einmaligen Übernahme in einen Passwort- oder Secret-Store. In meinem Projekt liegt das Archiv ausschließlich verschlüsselt außerhalb des Dokumentationsrepositorys.

Schritt 10: Pakete und Dienste kontrollieren

Direkt nach dem Assistenten:

rpm -q wazuh-manager wazuh-indexer wazuh-dashboard filebeat
systemctl is-active wazuh-indexer wazuh-manager filebeat wazuh-dashboard
systemctl is-enabled wazuh-indexer wazuh-manager filebeat wazuh-dashboard
rpm -qi wazuh-manager wazuh-indexer wazuh-dashboard filebeat \
  | grep -E '^(Name|Version|Release|Signature)[[:space:]]*:'

Bei mir wurden überall Wazuh 4.14.7-Pakete installiert; alle vier Dienste waren aktiv und für den Boot aktiviert. Die RPM-Signaturen wurden ebenfalls geprüft.

Schritt 11: Indexer für die kleine All-in-one-VM einstellen

Die oft genannte Faustregel „halber RAM für den Heap“ passt schlecht, wenn Manager, Indexer und Dashboard nur 12 GiB gemeinsam nutzen. Ich habe deshalb im vorhandenen /etc/wazuh-indexer/jvm.options die Heap-Werte auf 2 GiB gesetzt:

-Xms2g
-Xmx2g

In /etc/wazuh-indexer/opensearch.yml wurde Memory Lock aktiviert:

bootstrap.memory_lock: true

Der systemd-Drop-in ergänzt:

[Service]
LimitMEMLOCK=infinity

Anschließend:

sudo systemctl daemon-reload
sudo systemctl restart wazuh-indexer
systemctl show wazuh-indexer -p LimitMEMLOCK

Mit einem Indexer-Admin-Konto aus dem Secret-Store wurde danach geprüft, dass mlockall=true und der Cluster green meldet. Das Passwort wird dabei nicht in eine dauerhaft gespeicherte Shell-History geschrieben.

Der erste Managerstart mit Vulnerability Feed und Syscollector dauerte auf der kleinen VM etwas länger als der Paketstandard. Der von mir verwendete Drop-in setzt daher:

[Service]
TimeoutStartSec=120s
TimeoutStopSec=120s

Schritt 12: API, Indexer und Dashboard ans richtige Netz binden

In meinem All-in-one-Aufbau brauchen Wazuh-API und Indexer keine externen Listener:

127.0.0.1:55000   Wazuh Server API
127.0.0.1:9200    Wazuh Indexer API

Die API-Bindung steht in /var/ossec/api/configuration/api.yaml:

host: ['127.0.0.1']
port: 55000
https:
  enabled: yes

In /etc/wazuh-indexer/opensearch.yml ist der einzelne Indexer ebenfalls an Loopback gebunden:

network.host: 127.0.0.1

Der Browser greift bei mir über den vorhandenen internen Reverse-Proxy zu:

Browser -- HTTPS --> wazuh.example.internal / Reverse-Proxy
        -- HTTP  --> wazuh01.example.internal:5601

Das Dashboard lauscht deshalb intern auf 0.0.0.0:5601 ohne eigenes TLS. Firewalld erlaubt diesen Port ausschließlich von 192.0.2.20/32. Der Indexer bleibt auch für das Dashboard über HTTPS auf Loopback angebunden.

Die entscheidenden Dashboard-Werte in /etc/wazuh-dashboard/opensearch_dashboards.yml lauten bei mir:

server.host: 0.0.0.0
server.port: 5601
server.ssl.enabled: false
opensearch.hosts: https://127.0.0.1:9200
opensearch_security.cookie.secure: true

Im Nginx Proxy Manager ist dazu ein Proxy Host mit diesen Werten angelegt:

Feld Wert bei mir
Domain wazuh.example.internal
Scheme http
Forward Host wazuh01.example.internal
Forward Port 5601
Browserseite HTTPS mit intern vertrauenswürdigem Zertifikat

Nach Änderungen wurden Indexer, API beziehungsweise Dashboard gezielt neu gestartet und die Listener erneut mit ss -lntup kontrolliert.

Wer keinen Reverse-Proxy einsetzt, lässt zunächst die vom Assistenten erzeugte HTTPS-Konfiguration des Dashboards bestehen. Niemals den unverschlüsselten Port 5601 pauschal für ein ganzes LAN oder gar das Internet öffnen.

Schritt 13: Firewalld auf die echten Wege begrenzen

Mein finaler Listener- und Firewallplan lautet:

Zielport Quelle Zweck
22/TCP Admin-LAN und VPN SSH
1514/TCP vorgesehene Agentennetze dauerhafte Agentenkommunikation
1515/TCP nur Haupt-LAN Enrollment
5601/TCP exakt der Reverse-Proxy Dashboard-Backend
55000/TCP keine externe Freigabe API bleibt lokal
9200/TCP keine externe Freigabe Indexer bleibt lokal
9300–9400/TCP keine externe Freigabe kein Indexer-Cluster vorhanden

Beispiel für die Agentenkommunikation aus dem Haupt-LAN:

sudo firewall-cmd --permanent --zone=public \
  --add-rich-rule='rule family="ipv4" source address="192.0.2.0/24" port port="1514" protocol="tcp" accept'

Vor dem Entfernen einer pauschalen SSH-Freigabe immer zuerst die neue, eingeschränkte Regel setzen und in einer zweiten SSH-Sitzung testen. Danach können unbenötigte Dienste wie Cockpit aus der Zone entfernt werden:

sudo firewall-cmd --permanent --zone=public --remove-service=cockpit
sudo firewall-cmd --reload
sudo firewall-cmd --zone=public --list-all
sudo ss -lntup

Cockpit selbst ist auf meiner Wazuh-VM nicht installiert.

Schritt 14: Wazuh-Repository nach der Installation deaktivieren

Wazuh empfiehlt, das Paketrepository nach erfolgreicher Installation zu deaktivieren. Damit läuft nicht versehentlich nur eine zentrale Komponente auf eine neue Version:

sudo sed -i 's/^enabled=1/enabled=0/' /etc/yum.repos.d/wazuh.repo
grep -E '^(\[|enabled=)' /etc/yum.repos.d/wazuh.repo

Wazuh-Updates finden bei mir nur in einem dokumentierten Wartungsfenster nach Backup, Release-Note-Prüfung und Funktionstest statt. Normale Rocky- Sicherheitsupdates werden davon getrennt behandelt.

Schritt 15: Neustart und erste technische Abnahme

Zum Abschluss wurde die VM kontrolliert neu gestartet. Danach liefen diese Prüfungen:

rpm -q wazuh-manager wazuh-indexer wazuh-dashboard filebeat
systemctl is-active wazuh-indexer wazuh-manager filebeat wazuh-dashboard
systemctl is-enabled wazuh-indexer wazuh-manager filebeat wazuh-dashboard
sudo /var/ossec/bin/wazuh-control status
sudo ss -lntup
sudo firewall-cmd --zone=public --list-all
sysctl vm.swappiness
systemctl show wazuh-indexer -p LimitMEMLOCK
getenforce
sudo ausearch -m AVC,USER_AVC -ts boot -i
df -hT / /var/ossec /var/lib/wazuh-indexer

Mein Sollzustand war:

  • vier zentrale Dienste aktiv und beim Boot aktiviert;
  • Indexer green, ein Node, keine unzugewiesenen Shards;
  • mlockall=true und LimitMEMLOCK=infinity;
  • vm.swappiness=1;
  • SELinux weiterhin Enforcing, keine neuen AVC-Verweigerungen;
  • API und Indexer nur auf Loopback;
  • Dashboard nur über den TLS-Reverse-Proxy erreichbar;
  • genügend freie Blöcke und Inodes auf allen drei Dateisystemen.

Die vollständige Sammlung der Prüfkommandos steht auf der nächsten Seite: Wazuh Installation prüfen.

Was bei meinem Aufbau alles schief gelaufen ist :D

Ein paar Dinge waren erst beim echten Aufbau sichtbar:

  • Der Rocky-Installer und die Proxmox-Konsole hatten zunächst ein vertauschtes Tastaturlayout. Bei Passwörtern merkt man das leider gern erst später.
  • Linux vertauschte nach einem Neustart die Namen der zusätzlichen Disks. Persistente Mounts müssen deshalb UUIDs verwenden; /dev/sdX ist keine dauerhafte Identität (sollte aber ja sowieso standard sein, oder?).
  • Leere, bereits gemountete ext4-Dateisysteme wurden vom Wazuh-Assistenten als Installationsreste erkannt. --overwrite war hier begründet, ist aber kein allgemeiner Standardparameter.
  • Ein 6-GiB-Indexer-Heap hätte auf der 12-GiB-All-in-one-VM Manager und Dashboard unnötig unter Druck gesetzt. Praktisch funktionieren 2 GiB für die kleine Zahl meiner Agents besser.
  • Der Manager brauchte beim ersten Feed-Start mehr als 45 Sekunden. Ein dokumentiertes 120-Sekunden-Timeout ist sinnvoller als einen gesunden Start vorschnell abzubrechen.
  • Das selbstsignierte Dashboard-Zertifikat war für den ersten lokalen Test okay, aber nicht für den dauerhaften Browserzugriff. Deshalb endet TLS heute am vorhandenen internen Reverse-Proxy.

Genau solche Punkte sind der Grund, warum die Installation nicht beim Assistentenkommando endet.

Danach geht es mit der Grundkonfiguration weiter

Nach der technischen Installation folgen getrennt:

  • persönliche Admin-, Read-only- und Reporting-Konten;
  • Agent Enrollment und Gruppen;
  • Rollen für Docker, Nextcloud, Reverse-Proxy und andere Dienste;
  • Alarmierung über E-Mail und weitere Kanäle;
  • tägliche Betriebs- und wöchentliche Sicherheitsberichte;
  • Retention, Indexer-Snapshots, Backups und Restore-Tests.

Das steht bewusst im Artikel Wazuh Grundkonfiguration, damit Installation und späterer Betrieb nicht wieder zu einem einzigen langen „müsste man mal“-Block werden.

Weiterlesen

Zuletzt aktualisiert am 18.08.2026 · 15 Aufrufe