Skip to content
Go back

Wazuh: Open Source SIEM for Your Home Lab

By SumGuy 5 min read
Wazuh: Open Source SIEM for Your Home Lab

Your logs are everywhere and you’re flying blind

Here’s the thing: if you’ve got more than three Linux machines in your home lab, you’re already losing the security plot. Logs are scattered across syslog, application logs, firewall logs, auth logs — and when something goes sideways at 2 AM, you’re SSHing into five different boxes trying to piece together what actually happened.

It’s like hiring a forklift to move a couch. Technically you could manage everything manually, but your future self at 2 AM will hate you.

That’s where Wazuh comes in. It’s an open-source SIEM (Security Information and Event Management) that does way more than just centralize logs. Out of the box, you get:

One stack. No duct tape. No buying five different SaaS tools.

Let’s get it running in Docker.

The Wazuh stack: three containers, one pain point solved

Wazuh is built on three components: the manager (brains), the indexer (storage), and the dashboard (the pretty pictures). We’re going to run all three via Docker Compose.

docker-compose.yml
version: '3.8'
services:
wazuh-indexer:
image: docker.io/wazuh/wazuh-indexer:4.7.0
container_name: wazuh-indexer
environment:
- discovery.type=single-node
- INDEXER_SECURITY_SSL_ENABLED=true
- INDEXER_SECURITY_SSL_VERIFICATION_MODE=full
- INDEXER_SECURITY_SSL_KEYSTORE_FILEPATH=/usr/share/wazuh-indexer/certs/node-key.pem
- INDEXER_SECURITY_SSL_CERTIFICATE_FILEPATH=/usr/share/wazuh-indexer/certs/node-cert.pem
- INDEXER_SECURITY_SSL_CERTIFICATEAUTHORITIES_FILEPATH=/usr/share/wazuh-indexer/certs/root-ca.pem
- INDEXER_ADMIN_IDENTITY_FILE=/usr/share/wazuh-indexer/certs/admin-identity.xml
- INDEXER_PLUGINS_SECURITY_SSL_HTTP_KEYSTORE_FILEPATH=/usr/share/wazuh-indexer/certs/node-key.pem
- INDEXER_PLUGINS_SECURITY_SSL_HTTP_CERTIFICATE_FILEPATH=/usr/share/wazuh-indexer/certs/node-cert.pem
- INDEXER_PLUGINS_SECURITY_SSL_HTTP_CERTIFICATEAUTHORITIES_FILEPATH=/usr/share/wazuh-indexer/certs/root-ca.pem
volumes:
- wazuh-indexer-data:/var/lib/wazuh-indexer
- ./certs/indexer-node1.pem:/usr/share/wazuh-indexer/certs/node-cert.pem:ro
- ./certs/indexer-node1-key.pem:/usr/share/wazuh-indexer/certs/node-key.pem:ro
- ./certs/root-ca.pem:/usr/share/wazuh-indexer/certs/root-ca.pem:ro
- ./certs/admin-identity.xml:/usr/share/wazuh-indexer/certs/admin-identity.xml:ro
ports:
- "9200:9200"
networks:
- wazuh-net
healthcheck:
test: curl -s https://localhost:9200 -k -u admin:admin >/dev/null 2>&1
interval: 30s
timeout: 10s
retries: 5
wazuh-manager:
image: docker.io/wazuh/wazuh-manager:4.7.0
container_name: wazuh-manager
environment:
- INDEXER_URL=https://wazuh-indexer:9200
- INDEXER_USERNAME=admin
- INDEXER_PASSWORD=admin
- FILEBEAT_SSL_VERIFICATION_MODE=full
- SSL_CERTIFICATE_AUTHORITIES=/etc/ssl/certs/root-ca.pem
- SSL_CERTIFICATE=/etc/ssl/certs/manager.pem
- SSL_KEY=/etc/ssl/certs/manager-key.pem
volumes:
- wazuh-manager-data:/var/ossec/data
- wazuh-manager-etc:/var/ossec/etc
- ./certs/root-ca.pem:/etc/ssl/certs/root-ca.pem:ro
- ./certs/manager.pem:/etc/ssl/certs/manager.pem:ro
- ./certs/manager-key.pem:/etc/ssl/certs/manager-key.pem:ro
ports:
- "1514:1514"
- "1515:1515"
networks:
- wazuh-net
depends_on:
- wazuh-indexer
healthcheck:
test: curl -s https://localhost:55000 -k -u wazuh:wazuh >/dev/null 2>&1
interval: 30s
timeout: 10s
retries: 5
wazuh-dashboard:
image: docker.io/wazuh/wazuh-dashboard:4.7.0
container_name: wazuh-dashboard
environment:
- INDEXER_USERNAME=admin
- INDEXER_PASSWORD=admin
- WAZUH_API_URL=https://wazuh-manager:55000
- WAZUH_API_USERNAME=wazuh
- WAZUH_API_PASSWORD=wazuh
ports:
- "443:443"
networks:
- wazuh-net
depends_on:
- wazuh-indexer
- wazuh-manager
volumes:
- ./certs/dashboard.pem:/usr/share/wazuh-dashboard/certs/dashboard.pem:ro
- ./certs/dashboard-key.pem:/usr/share/wazuh-dashboard/certs/dashboard-key.pem:ro
volumes:
wazuh-indexer-data:
wazuh-manager-data:
wazuh-manager-etc:
networks:
wazuh-net:
driver: bridge

Before you docker compose up, you need certificates. The Wazuh project provides a cert-generation script. Download it from their GitHub, run it to generate certs, then you’re good to go.

After the stack is healthy (check those health checks), hit https://localhost in your browser. Default creds are admin:admin for the dashboard. Change them immediately.

Getting your Linux host talking to Wazuh

Install the agent on any Linux host you want to monitor:

Terminal window
curl -s https://packages.wazuh.com/key/GPG-KEY-WAZUH | apt-key add -
echo "deb https://packages.wazuh.com/4.x/apt/ stable main" | tee /etc/apt/sources.list.d/wazuh.list
apt update && apt install -y wazuh-agent

Then enroll it with your Wazuh manager:

Terminal window
/var/ossec/bin/wazuh-control start

The agent auto-registers if you’ve configured the manager to accept auto-enrollment (it’s on by default). Check the dashboard under Agents — you should see your host within a minute.

File integrity monitoring: catch the sneaky changes

FIM is the feature that’ll actually wake you up at 2 AM because something changed that shouldn’t have. We’re going to monitor /etc/ and /home/ for unauthorized edits.

Add this to /var/ossec/etc/ossec.conf on the manager (inside the <ossec_config> block):

/var/ossec/etc/ossec.conf
<syscheck>
<frequency>3600</frequency>
<directories check_all="yes" realtime="yes">/etc</directories>
<directories check_all="yes" realtime="yes">/home</directories>
<ignore>/etc/mtab</ignore>
<ignore>/etc/resolv.conf</ignore>
<alert_new_files>yes</alert_new_files>
</syscheck>

The realtime="yes" means Wazuh checks those directories every time something changes, instead of waiting for the hourly scan. On a busy system, this might be noisy — dial it back to /etc only if you’re drowning in alerts.

Restart the manager and agent. Now when someone (or some script) modifies /etc/sudoers or adds a cron job to /var/spool/cron/, you’ll get an alert.

Tuning alerts: your first lesson in not crying wolf

Day one with Wazuh, you’re going to get flooded with alerts. Legitimate ones, sure, but also a ton of noise. Your automated patching routine is firing alerts. Docker is restarting containers. Cron is doing its thing.

Here’s how to suppress a false positive. Let’s say you’re getting hammered with alerts every time sudo runs with password entry — which is normal and expected.

Create a file /var/ossec/etc/rules/local_rules.xml:

/var/ossec/etc/rules/local_rules.xml
<group name="local,">
<rule id="100001" level="0">
<if_sid>5402</if_sid>
<match>sudo.*password</match>
<description>Suppress sudo password entry alerts</description>
</rule>
</group>

Rule ID 5402 is Wazuh’s built-in “sudo” rule. By creating a rule with level="0" (zero priority), you’re telling it to ignore that match. Restart, and the noise stops.

Spend your first week tuning. Your second week, you’ll have actual signal.

Your first real alert

You’ll know Wazuh is working when you see something like this in the dashboard:

This is the moment you care about. This is why you’re running a SIEM. Your 2 AM self is now equipped to make decisions instead of guessing.

One last thing

Wazuh won’t replace proper backups, patching, and access control. It’s the detective, not the cop. But honestly? Running a SIEM in your home lab makes you dramatically smarter about what’s actually happening on your machines. You stop flying blind.

Your 2 AM self will appreciate it.


Share this post on:

Send a Webmention

Written about this post on your own site? Send a webmention and it may appear here.


Previous Post
SBCs in 2026: Homelab on a Budget
Next Post
Steam on Linux: It Actually Works Now

Related Posts