How to Build a Home SOC Lab on a Budget (2026): SIEM, IDS & Log Management from Scratch

·

You do not learn detection engineering by reading about it. You learn it by generating a real attack, watching whether your sensors caught it, and fixing the gap when they didn't. That loop needs a lab — and the good news is a capable one costs nothing if you already own a laptop with 16 GB of RAM, or roughly $300–$500 for a dedicated mini-PC that runs 24/7.

This guide builds a full blue-team lab from scratch: Wazuh 4.14.x as the SIEM/XDR core, Suricata as the network IDS, a Sysmon-instrumented Windows endpoint, and a Kali attacker running Atomic Red Team to safely fire MITRE ATT&CK techniques at it. You get three deployment paths — VirtualBox on an existing PC, a Docker single-node stack, and a Proxmox mini-PC build — with every command laid out to copy and paste.

By the end you will have log collection, network IDS, endpoint telemetry, working detections and a repeatable attack-and-detect workflow. This is a lab, not a production SOC: keep it isolated from your home network and never point internet-facing services at it.

◈ Table of Contents

01 What a Home SOC Lab Is 02 Architecture & Budget Tiers 03 Method 1 — VirtualBox on Your PC 04 Method 2 — Wazuh via Docker 05 Method 3 — Proxmox Mini-PC 06 Initial Wazuh Configuration 07 Core Config — Endpoints & IDS 08 Integration & Network Design 09 Advanced — Attack & Detect 10 Monitoring & Troubleshooting 11 Sources & References
🛰️

01 · What a Home SOC Lab Is — and Why Build One

Phase 1 / 11

A Security Operations Center lab is a self-contained set of virtual machines that reproduces the three things a real SOC runs on: telemetry (endpoint and network logs), a SIEM to centralise and correlate that telemetry, and a target and threat so you have something to detect. The point is not to defend real assets — it is to practise the analyst loop: an alert fires, you pivot through the evidence, you decide true-positive or false-positive, and you write or tune a rule so the next occurrence is caught faster.

Commercial SIEM licences run into five figures a year, which is exactly why open-source Wazuh anchors this build. It ships file-integrity monitoring, vulnerability detection, log analysis, MITRE ATT&CK mapping and pre-written rulesets that parse Sysmon and Suricata out of the box — for the price of the hardware it runs on.

🎯

SOC Analyst Trainees

Practise triage on real alerts — process-injection, brute force, suspicious PowerShell — before you ever touch a production console.

🔬

Detection Engineers

Write a rule, fire the matching Atomic Red Team test, confirm it triggers, then tune out false positives. The whole detection lifecycle in one box.

🛡️

Blue Teamers

Rehearse incident response — isolate a host, pull the timeline, verify eradication — on disposable VMs you can revert with a snapshot.

🎓

Students & Certs

Hands-on evidence for CompTIA Security+, BTL1 and SC-200 study — a lab you can screenshot for a portfolio recruiters actually respect.

Treat every VM as disposable. Take a clean snapshot of each machine the moment it is configured and working. When an attack simulation trashes a host — and it will — you revert in seconds instead of rebuilding for an hour.

🧱

02 · Lab Architecture & Budget Tiers

Phase 2 / 11

The whole lab is four VMs on one isolated virtual network. The SIEM does the heavy lifting, so it gets most of the RAM; the endpoints and attacker are deliberately lightweight. Below is the architecture, followed by three budget tiers so you can build with whatever you have.

Four VMs, one host-only subnet. The attacker fires at the endpoints; the endpoints and IDS ship telemetry to Wazuh.
2.1Component Roles & Resource PlanSpec

Allocate resources to match each VM's job. Wazuh's indexer is Java/OpenSearch-based and memory-hungry; everything else is modest. These are working figures for a single-analyst lab.

VMRolevCPURAMDiskIP
WazuhSIEM: indexer + manager + dashboard2–44–8 GB rec50 GB10.10.10.20
Win11Victim endpoint, Sysmon telemetry24 GB40 GB10.10.10.30
UbuntuSuricata network IDS + Linux agent1–22 GB25 GB10.10.10.40
KaliAttacker / red-team tooling22–4 GB30 GB10.10.10.50

Wazuh's indexer will refuse to start with less than ~2 GB free. 4 GB is a hard floor for the SIEM VM; 6–8 GB makes the dashboard usable. If your host has only 16 GB total, run the endpoints one at a time rather than all four at once.

2.2Three Budget TiersSpec

Pick the tier that matches your wallet. The zero-dollar path is real — it runs on the laptop you already own — it just can't run 24/7.

TierCostHardwareTrade-off
Zero$0Existing PC/laptop, 16 GB RAM, VirtualBoxNo 24/7 uptime; close other apps while labbing
Budget$200–350Used mini-PC / SFF (e.g. i5, 16–32 GB, 512 GB SSD)Runs headless 24/7; buy a second-hand enterprise SFF
Comfort$400–500New/refurb mini-PC, 32 GB RAM, NVMe, ProxmoxRoom to add pfSense, a domain controller, more agents

Second-hand enterprise small-form-factor PCs (Dell OptiPlex Micro, Lenovo ThinkCentre Tiny, HP EliteDesk Mini) are the sweet spot: 32 GB of DDR4 and an NVMe slot for well under $300, and they idle near-silent under 15 W.

2.3Software Bill of MaterialsPrereqs

Everything below is free and open source or free-to-use. Pin the exact versions in a notes file so a rebuild is deterministic.

SoftwareVersion (Sep 2026)Purpose
Wazuh4.14.x (4.14.7 stable)SIEM/XDR: agents, rules, dashboard
Ubuntu Server24.04 LTSHost OS for Wazuh & Suricata VMs
Suricata7.xNetwork IDS/IPS & EVE JSON logs
Sysmonv15.x + SwiftOnSecurity / Sysmon Modular configRich Windows endpoint telemetry
Kali Linux2026.xAttacker toolkit
Atomic Red TeamcurrentSafe, atomic MITRE ATT&CK tests
VirtualBox / Proxmox VE7.1 / 9.xHypervisor
📘
Wazuh Installation Guide (official)
documentation.wazuh.com — always check current hardware & version notes
↗
💻

03 · Method 1 — VirtualBox on Your Existing PC

Phase 3 / 11

This is the zero-dollar path and the one most people should start with. VirtualBox is free, cross-platform, and its Host-Only network is perfect for keeping the lab off your real LAN. We create an isolated network, spin up the Ubuntu VM that will host Wazuh, then install Wazuh's all-in-one package on it.

3.1Install VirtualBox & Create the Isolated NetworkHost

Install VirtualBox and its Extension Pack, then define a Host-Only network. Every lab VM attaches to this network and to nothing else — no bridging to your home router.

Debian/Ubuntu host
# Install VirtualBox from Oracle's repo (or your distro package) $ sudo apt update && sudo apt install -y virtualbox virtualbox-ext-pack
Create a host-only network (CLI, any platform)
# Create the adapter and give it a static gateway $ VBoxManage hostonlyif create $ VBoxManage hostonlyif ipconfig vboxnet0 --ip 10.10.10.1 --netmask 255.255.255.0 # Confirm it exists $ VBoxManage list hostonlyifs

Do NOT enable the VirtualBox Host-Only DHCP server if you want fixed IPs — assign static addresses inside each guest instead. Mixed DHCP + static is the #1 cause of "my agent can't find the manager" in home labs.

3.2Build the Wazuh VM (Ubuntu Server 24.04)VM

Download the Ubuntu Server 24.04 ISO, create a VM with 2 vCPU / 6 GB RAM / 50 GB disk, and attach the host-only adapter. You can do it in the GUI, or scripted with VBoxManage below.

Scripted VM creation
$ VBoxManage createvm --name "wazuh" --ostype Ubuntu_64 --register $ VBoxManage modifyvm "wazuh" --memory 6144 --cpus 2 --nic1 hostonly --hostonlyadapter1 vboxnet0 $ VBoxManage createhd --filename "wazuh.vdi" --size 51200 $ VBoxManage storagectl "wazuh" --name SATA --add sata --controller IntelAhci $ VBoxManage storageattach "wazuh" --storagectl SATA --port 0 --device 0 --type hdd --medium "wazuh.vdi" $ VBoxManage storageattach "wazuh" --storagectl SATA --port 1 --device 0 --type dvddrive --medium "ubuntu-24.04-live-server-amd64.iso" $ VBoxManage startvm "wazuh"

Complete the Ubuntu installer, then give the VM a static address. On 24.04 that means a netplan file:

/etc/netplan/01-lab.yaml — inside the Wazuh VM
network: version: 2 ethernets: enp0s3: dhcp4: false addresses: [10.10.10.20/24] routes: - to: default via: 10.10.10.1 $ sudo netplan apply $ ip a show enp0s3 # confirm 10.10.10.20
3.3Install Wazuh All-in-OneSIEM

Wazuh's assisted installer deploys the indexer, manager and dashboard on a single node in one command. This is the fastest way to a working SIEM.

On the Wazuh VM
# Kernel tuning the indexer needs BEFORE install $ sudo sysctl -w vm.max_map_count=262144 $ echo 'vm.max_map_count=262144' | sudo tee -a /etc/sysctl.conf # Download and run the assisted installer (all-in-one) $ curl -sO https://packages.wazuh.com/4.14/wazuh-install.sh $ sudo bash ./wazuh-install.sh -a

When it finishes it prints the admin password. Capture it — you need it for the dashboard and for the password tool later.

# Retrieve the generated credentials at any time $ sudo tar -O -xvf wazuh-install-files.tar wazuh-install-files/wazuh-passwords.txt
Method 1 complete when
  • Browsing https://10.10.10.20 shows the Wazuh login (self-signed cert warning is expected)
  • You can log in as admin with the generated password
  • sudo systemctl status wazuh-manager wazuh-indexer wazuh-dashboard shows all three active

Snapshot the Wazuh VM right now, labelled "clean-siem". If a later change breaks the stack, revert to this instead of re-running the installer.

🐳

04 · Method 2 — Wazuh via Docker (Single-Node)

Phase 4 / 11

If your SIEM host already runs Docker, the single-node stack is cleaner than the bare-metal installer: three containers (indexer, manager, dashboard) defined in one Compose file, easy to tear down and rebuild. This is my preferred path on a dedicated mini-PC.

4.1Install Docker Engine & Prepare the HostHost

Install Docker Engine and the Compose plugin, then apply the same kernel setting the indexer requires. Without vm.max_map_count the indexer container crash-loops immediately.

# Docker Engine via the convenience script $ curl -fsSL https://get.docker.com | sudo sh $ sudo usermod -aG docker $USER # log out/in after this # Required for the Wazuh indexer $ sudo sysctl -w vm.max_map_count=262144 $ echo 'vm.max_map_count=262144' | sudo tee -a /etc/sysctl.conf
4.2Clone the Repo & Generate CertificatesCerts

Wazuh publishes an official wazuh-docker repository. Check out the tag that matches your version, then run the one-shot certificate generator before starting the stack.

$ git clone https://github.com/wazuh/wazuh-docker.git -b v4.14.7 $ cd wazuh-docker/single-node # Generate the indexer/manager/dashboard TLS certs (one time) $ docker compose -f generate-indexer-certs.yml run --rm generator $ ls config/wazuh_indexer_ssl_certs/ # certs now present

Change the default admin and kibanaserver passwords in docker-compose.yml and the internal users file before exposing the dashboard to anything. The stock credentials are public knowledge.

4.3The docker-compose.yml (Single-Node)Compose

The repo ships a complete Compose file; the annotated version below shows the shape of the single-node stack so you understand what each service does. Adjust the RAM limits and passwords, then bring it up.

docker-compose.yml (abridged, single-node)
services: wazuh.manager: image: wazuh/wazuh-manager:4.14.7 hostname: wazuh.manager restart: always ulimits: { memlock: { soft: -1, hard: -1 }, nofile: { soft: 655360, hard: 655360 } } ports: - "1514:1514" # agent event channel - "1515:1515" # agent enrollment - "514:514/udp" # syslog - "55000:55000" # manager REST API volumes: - wazuh_etc:/var/ossec/etc - ./config/wazuh_indexer_ssl_certs/:/etc/ssl/ wazuh.indexer: image: wazuh/wazuh-indexer:4.14.7 hostname: wazuh.indexer restart: always environment: - "OPENSEARCH_JAVA_OPTS=-Xms2g -Xmx2g" # heap = ~half VM RAM ports: [ "9200:9200" ] volumes: [ wazuh-indexer-data:/var/lib/wazuh-indexer ] wazuh.dashboard: image: wazuh/wazuh-dashboard:4.14.7 hostname: wazuh.dashboard restart: always ports: [ "443:5601" ] depends_on: [ wazuh.indexer ] volumes: wazuh_etc: wazuh-indexer-data:
Launch the stack
$ docker compose up -d $ docker compose ps # all three healthy? $ docker compose logs -f wazuh.indexer | grep -i started
Method 2 complete when
  • docker compose ps shows manager, indexer and dashboard as running
  • https://SIEM-IP:443 serves the Wazuh dashboard login
  • curl -k -u admin:PASS https://localhost:9200 returns indexer cluster JSON
🖥️

05 · Method 3 — Proxmox VE on a Dedicated Mini-PC

Phase 5 / 11

For an always-on lab, a Type-1 hypervisor on dedicated hardware beats VirtualBox on your daily driver. Proxmox VE is free, manages all your lab VMs from one web UI, and its snapshot/clone workflow is ideal for rebuilding attack targets. Use this method if you bought the Budget or Comfort tier hardware.

5.1Install Proxmox & Add the No-Subscription RepoHost

Flash the Proxmox VE 9 ISO to a USB stick, install it on the mini-PC, then switch to the free no-subscription repository so apt updates work without a licence.

On the Proxmox host shell
# Disable the enterprise repo, enable no-subscription $ sed -i 's/^deb/#deb/' /etc/apt/sources.list.d/pve-enterprise.sources 2>/dev/null $ echo 'deb http://download.proxmox.com/debian/pve trixie pve-no-subscription' > /etc/apt/sources.list.d/pve-no-sub.list $ apt update && apt -y dist-upgrade
5.2Create the Isolated Lab BridgeNetwork

Add a second, internal-only Linux bridge (vmbr1) with no physical NIC attached. Every lab VM lives on this bridge, isolated from your home LAN, while Proxmox itself stays reachable on vmbr0.

/etc/network/interfaces — append
auto vmbr1 iface vmbr1 inet static address 10.10.10.1/24 bridge-ports none bridge-stp off bridge-fd 0 # internal lab network — no uplink $ ifreload -a

Leave the lab bridge with no gateway to the internet. When a VM genuinely needs updates, temporarily attach a second NIC on vmbr0, patch, then detach it. An air-gapped attack lab can't accidentally scan the neighbourhood.

5.3Provision the Wazuh VM via qmVM

Proxmox's qm CLI scripts VM creation. Upload the Ubuntu ISO to local storage first, then create and start the SIEM VM on the lab bridge.

$ qm create 120 --name wazuh --memory 6144 --cores 2 \ --net0 virtio,bridge=vmbr1 --scsihw virtio-scsi-pci $ qm set 120 --scsi0 local-lvm:50 $ qm set 120 --ide2 local:iso/ubuntu-24.04-live-server-amd64.iso,media=cdrom $ qm set 120 --boot order=ide2\;scsi0 $ qm start 120

From here the OS install, static IP and Wazuh deployment are identical to Method 1 (§3.2–3.3) or Method 2 (Docker). Clone this VM template to spin up the Windows, Ubuntu-IDS and Kali guests faster.

⚙️

06 · Initial Wazuh Configuration

Phase 6 / 11

With the SIEM running by whichever method, harden the defaults and confirm the manager is ready to accept agents. Never leave a lab with stock passwords — you will eventually expose it by accident.

6.1Rotate the Default PasswordsHarden

Wazuh ships a password-change tool that updates the indexer, dashboard and API users consistently. Run it before anything else.

Bare-metal install
# Interactive: rotate all internal users $ sudo /usr/share/wazuh-indexer/plugins/opensearch-security/tools/wazuh-passwords-tool.sh -a # Or change one user (admin) explicitly $ sudo bash wazuh-passwords-tool.sh -u admin -p 'S0me-Str0ng-Lab-Pass!'
Docker install
$ docker exec -it single-node-wazuh.indexer-1 bash $ export INSTALLATION_DIR=/usr/share/wazuh-indexer $ bash /usr/share/wazuh-indexer/plugins/opensearch-security/tools/wazuh-passwords-tool.sh -u admin -p 'S0me-Str0ng-Lab-Pass!'
6.2Confirm the Manager & APIVerify

Check the manager service and query the REST API. A healthy API response means agents will be able to enrol.

$ sudo /var/ossec/bin/wazuh-control status # Get an API token, then list agents (none yet) $ TOKEN=$(curl -sk -u wazuh:wazuh -X POST "https://10.10.10.20:55000/security/user/authenticate" | jq -r .data.token) $ curl -sk -H "Authorization: Bearer $TOKEN" "https://10.10.10.20:55000/agents?select=id,name,status" | jq

Where to look in the dashboard

Wazuh dashboard ▸ Server management ▸ Endpoints Summary ▸ Deploy new agent
🔌

07 · Core Configuration — Endpoints & IDS

Phase 7 / 11

A SIEM with no data is a login page. This phase wires up the telemetry that makes the lab worth having: the Wazuh agent plus Sysmon on Windows, a Linux agent on the Ubuntu box, and Suricata generating network alerts.

7.1Enrol the Windows EndpointAgent

Install the Wazuh agent MSI on the Windows 11 VM, pointing it at the manager. The dashboard's "Deploy new agent" wizard generates this exact command with a group and enrollment key.

Windows PowerShell (Administrator)
PS> Invoke-WebRequest -Uri https://packages.wazuh.com/4.x/windows/wazuh-agent-4.14.7-1.msi -OutFile $env:tmp\wazuh-agent.msi PS> msiexec.exe /i $env:tmp\wazuh-agent.msi /q WAZUH_MANAGER="10.10.10.20" WAZUH_AGENT_NAME="win11-victim" WAZUH_REGISTRATION_SERVER="10.10.10.20" PS> NET START WazuhSvc PS> Get-Service WazuhSvc # Status: Running

Within a minute the agent appears in Endpoints Summary as Active.

7.2Install Sysmon with a Curated ConfigTelemetry

Sysmon is what turns bland Windows logs into attacker-grade telemetry: process creation with command lines and hashes, network connections, DNS queries and image loads. Use a community config — SwiftOnSecurity for a clean baseline, or Olaf Hartong's Sysmon Modular for ATT&CK-tagged events.

PS> Invoke-WebRequest https://download.sysinternals.com/files/Sysmon.zip -OutFile Sysmon.zip PS> Expand-Archive Sysmon.zip -DestinationPath C:\Sysmon # Grab a battle-tested config PS> Invoke-WebRequest https://raw.githubusercontent.com/SwiftOnSecurity/sysmon-config/master/sysmonconfig-export.xml -OutFile C:\Sysmon\config.xml # Install as a service with that config PS> C:\Sysmon\Sysmon64.exe -accepteula -i C:\Sysmon\config.xml

Now tell the Wazuh agent to forward the Sysmon channel. Edit C:\Program Files (x86)\ossec-agent\ossec.conf and add a localfile block:

ossec.conf — Windows agent
<localfile> <location>Microsoft-Windows-Sysmon/Operational</location> <log_format>eventchannel</log_format> </localfile> PS> Restart-Service WazuhSvc

Sysmon's default (no config) logs almost nothing useful and floods you with noise on the wrong things. Never run it bare — always deploy a curated config and review it against your detection goals.

7.3Enrol the Linux Box & Install SuricataIDS

The Ubuntu VM plays two roles: a monitored Linux endpoint and the network IDS. Install the Wazuh agent, then Suricata, then update its rules.

Ubuntu IDS VM (10.10.10.40)
# Wazuh agent $ curl -sO https://packages.wazuh.com/4.x/apt/pool/main/w/wazuh-agent/wazuh-agent_4.14.7-1_amd64.deb $ sudo WAZUH_MANAGER='10.10.10.20' WAZUH_AGENT_NAME='ubuntu-ids' dpkg -i ./wazuh-agent_4.14.7-1_amd64.deb $ sudo systemctl enable --now wazuh-agent # Suricata IDS $ sudo apt install -y suricata jq $ sudo suricata-update # pull ET Open ruleset $ sudo suricata-update list-sources

Point Suricata at the lab interface and enable EVE JSON output, which Wazuh reads natively.

# Set HOME_NET and the monitored interface in /etc/suricata/suricata.yaml $ sudo sed -i 's#HOME_NET:.*#HOME_NET: "[10.10.10.0/24]"#' /etc/suricata/suricata.yaml $ sudo suricata -T -c /etc/suricata/suricata.yaml -v # config test $ sudo systemctl restart suricata
🔗

08 · Integration & Network Design

Phase 8 / 11

Now connect the pieces so telemetry lands in one place and the attacker can safely reach the victims. This is where the collection of VMs becomes an actual SOC.

8.1Feed Suricata Alerts into WazuhPipeline

Add a localfile block to the Ubuntu agent's ossec.conf so the manager ingests Suricata's EVE log. Wazuh's built-in Suricata decoder parses it automatically.

/var/ossec/etc/ossec.conf — Ubuntu agent
<localfile> <log_format>json</log_format> <location>/var/log/suricata/eve.json</location> </localfile> $ sudo systemctl restart wazuh-agent

Verify the pipeline end-to-end before moving on: curl http://testmynids.org/uid/index.html from a victim triggers the ET rule "GPL ATTACK_RESPONSE id check returned root", which should surface in Wazuh within seconds. If it doesn't, the break is between Suricata and the agent — check EVE output is enabled.

8.2Network Segmentation & Firewall PostureDesign

Keep the lab off your production LAN. On the zero-dollar VirtualBox build, host-only already isolates it. For a mini-PC build, add pfSense or OPNsense as a router VM if you want inter-VLAN rules and a place to practise firewall log analysis.

SegmentSubnetHostsRule
SIEM10.10.10.20WazuhAccept agent traffic (1514/1515/55000)
Victims10.10.10.30–40Win11, UbuntuReachable from attacker; egress denied
Attacker10.10.10.50KaliReach victims; no internet during attacks

Never bridge the attacker VM to your real network. Atomic Red Team runs genuine offensive techniques; a misconfigured bridge means you are scanning and potentially exploiting hosts you don't own. Host-only or an internal bridge, always.

8.3Stand Up the Kali AttackerRed

Import the official Kali VirtualBox/VMware image or install from ISO, attach it to the lab network only, and confirm it can reach the victims.

$ sudo ip addr add 10.10.10.50/24 dev eth0 $ ping -c2 10.10.10.30 # reach the Windows victim $ nmap -sV -T4 10.10.10.30 # first noise — watch Wazuh light up

That nmap scan is your first real detection test. Move to the dashboard and look for the connection spike; if Suricata has scan rules enabled you'll see a port-scan alert too.

🎯

09 · Advanced — Attack, Detect & Tune

Phase 9 / 11

This is the phase you actually built the lab for. Fire a known ATT&CK technique with Atomic Red Team, confirm the detection, and when it's missing, write the rule that catches it. Repeat forever — that repetition is detection engineering.

9.1Install Atomic Red Team on the VictimSimulate

Atomic Red Team is a library of small, precise tests mapped to MITRE ATT&CK. Install the PowerShell module on the Windows victim (not the attacker — the tests run locally to generate the telemetry you want to detect).

PS> IEX (IWR 'https://raw.githubusercontent.com/redcanaryco/invoke-atomicredteam/master/install-atomicredteam.ps1' -UseBasicParsing) PS> Install-AtomicRedTeam -getAtomics -Force PS> Import-Module invoke-atomicredteam

Run Atomic Red Team only on a snapshot you can revert, and disable/exclude Defender for the test window if it quarantines the atomics before Sysmon logs them. Revert the snapshot when finished — some tests deliberately leave persistence behind.

9.2Fire a Technique & Watch the SIEMDetect

Start with T1059.001 (PowerShell) and T1003.001 (LSASS memory access) — both produce clear Sysmon telemetry and map to rules Wazuh already ships.

# Preview what a test does before running it PS> Invoke-AtomicTest T1059.001 -ShowDetailsBrief # Run a specific atomic PS> Invoke-AtomicTest T1059.001 -TestNumbers 1 # Credential access — LSASS access via comsvcs PS> Invoke-AtomicTest T1003.001 -TestNumbers 1 # Clean up afterwards PS> Invoke-AtomicTest T1059.001 -Cleanup
ATT&CK IDTechniqueSysmon EventExpect in Wazuh
T1059.001PowerShell executionEvent 1 (process create)Rule 92052 / PowerShell alerts
T1003.001LSASS memory dumpEvent 10 (process access)Credential-access alert
T1053.005Scheduled taskEvent 1 + 4698Persistence alert
T1547.001Registry Run keyEvent 13 (reg set)Autostart alert
9.3Search the Telemetry — Wazuh & SplunkHunt

Once events land, practise pivoting. In the Wazuh dashboard's Discover view you filter with a simple query; if you also run Splunk in your lab, the equivalent SPL is below. Every hunt starts with a hypothesis you can express as a query.

Wazuh dashboard — Discover filter (find the PowerShell atomic)
rule.groups: "sysmon_event1" and data.win.eventdata.image: *powershell.exe and data.win.eventdata.commandLine: (*-enc* or *DownloadString* or *IEX*)
Splunk SPL — same intent, if you forward Sysmon there too
index=sysmon EventCode=1 Image="*\\powershell.exe" | where match(CommandLine, "(?i)(-enc|DownloadString|IEX|FromBase64String)") | table _time, host, User, ParentImage, CommandLine
Wazuh — LSASS access hunt (T1003.001)
rule.groups: "sysmon_event_10" and data.win.eventdata.targetImage: *lsass.exe and not data.win.eventdata.sourceImage: (*wazuh* or *MsMpEng.exe*)
9.4Write a Custom Detection RuleEngineer

When a technique fires with no alert, that's a detection gap — the whole reason to have a lab. Add a custom rule to local_rules.xml on the manager, restart, and re-run the atomic to confirm it triggers.

/var/ossec/etc/rules/local_rules.xml — flag encoded PowerShell
<group name="local,sysmon,attack,"> <rule id="100210" level="12"> <if_group>sysmon_event1</if_group> <field name="win.eventdata.image">powershell\.exe>
lt;/field> <field name="win.eventdata.commandLine">-enc|-encodedcommand</field> <description>Encoded PowerShell command line (T1059.001)</description> <mitre><id>T1059.001</id></mitre> </rule> </group> $ sudo /var/ossec/bin/wazuh-control restart # Re-fire the atomic; the level-12 alert should now appear

Test rule syntax offline before restarting the whole manager: echo 'sample log line' | sudo /var/ossec/bin/wazuh-logtest shows exactly which rule and decoder match, so you tune in seconds instead of restart cycles.

9.5Build a Dashboard & Tune False PositivesTune

A detection you can't see is useless, and one that cries wolf gets ignored. Pin a MITRE ATT&CK dashboard and start suppressing the benign noise your own admin activity generates.

Dashboard path: Wazuh ▸ Threat Hunting ▸ MITRE ATT&CK ▸ Framework Filter by: agent.name, rule.mitre.id, rule.level >= 10

To silence a known-good source, raise or drop the rule with an override rather than deleting the base rule:

<rule id="100211" level="0"> <if_sid>100210</if_sid> <field name="win.eventdata.parentImage">\\\\Sure-Backup-Agent\.exe>
lt;/field> <description>Ignore encoded PS from the backup agent (tuned FP)</description> </rule>
Attack-and-detect loop complete when
  • An Atomic Red Team test produces a Wazuh alert at the expected level
  • You can pivot from the alert to the raw Sysmon event and the parent process
  • A gap you found now has a custom rule that fires reliably
  • Benign admin activity no longer generates the same alert
🩺

10 · Monitoring, Maintenance & Troubleshooting

Phase 10 / 11

A lab that fills its disk or drifts out of date stops teaching you anything. A few habits keep it healthy, and the table below covers the errors every home-lab builder hits.

10.1Disk, Retention & Health ChecksOps

The indexer is what fills disks. Watch usage and set an index-retention policy so old alerts roll off instead of wedging the stack. Wazuh estimates roughly 6 GB per 90 days for a ~100-endpoint enterprise; a four-VM lab is tiny by comparison, but snapshots and Sysmon volume add up.

$ df -h /var/lib/wazuh-indexer # watch the SIEM disk $ sudo /var/ossec/bin/agent_control -l # list agents + status $ curl -sk -u admin:PASS "https://10.10.10.20:9200/_cat/indices/wazuh-alerts-*?v&h=index,store.size,docs.count"
Delete indices older than a threshold (lab housekeeping)
$ curl -sk -u admin:PASS -XDELETE "https://10.10.10.20:9200/wazuh-alerts-4.x-2026.08.*"
10.2Updating the StackOps

Snapshot first, then update. Docker makes version bumps trivial; bare-metal follows the official upgrade guide.

Docker single-node
$ git -C wazuh-docker fetch --tags && git -C wazuh-docker checkout v4.14.7 $ cd wazuh-docker/single-node $ docker compose pull && docker compose up -d
Agents (Ubuntu)
$ sudo apt update && sudo apt install --only-upgrade wazuh-agent $ sudo systemctl restart wazuh-agent

Keep agent and manager on the same minor version. A manager on 4.14 with agents on 4.9 will mostly work but you'll hit missing decoders and odd rule behaviour — exactly the kind of confusion that wastes a lab session.

10.3Common Errors & FixesTroubleshoot

If something's broken, it's almost certainly in this table. Work top to bottom.

SymptomLikely CauseFix
Indexer container exits / crash-loopsvm.max_map_count too lowsudo sysctl -w vm.max_map_count=262144 and persist it
Dashboard 502 / "not ready yet"Indexer still initialisingWait 2–3 min; check docker compose logs wazuh.indexer
Agent stuck "Never connected"Port 1514/1515 blocked or wrong manager IPVerify firewall + WAZUH_MANAGER; re-enrol
Agent "Disconnected" after rebootTime skew between agent and managerEnable NTP / sync clocks on all VMs
No Sysmon events in WazuhMissing localfile eventchannel blockAdd block to ossec.conf, restart agent
Suricata alerts absentWrong HOME_NET / interface, or EVE offFix suricata.yaml; run suricata -T
Self-signed cert warning in browserExpected for a labAccept the exception, or import the CA cert

Before you burn an hour debugging, run sudo /var/ossec/bin/wazuh-control status on the manager and agent_control -l. Nine times out of ten the answer — dead service, disconnected agent, clock skew — is right there.

📚

11 · Sources & References

Phase 11 / 11

Primary documentation and community projects referenced in this guide. Always verify version numbers and hardware requirements against the current official docs before you build.

Wazuh — Official Installation Guide Wazuh — Docker Deployment (single-node) GitHub — wazuh/wazuh-docker (Compose files & cert generator) Wazuh — Upgrade Guide Suricata — Quickstart & Configuration Microsoft Sysinternals — Sysmon GitHub — SwiftOnSecurity/sysmon-config GitHub — olafhartong/sysmon-modular (ATT&CK-tagged config) GitHub — Red Canary Atomic Red Team MITRE ATT&CK — Enterprise Matrix Proxmox VE — Administration Guide Oracle VirtualBox — User Manual

Lab built — now put it to work.

Pair this lab with CyberHawk's SOPs to practise structured incident response against your own attack simulations, or run the alerts you generate through the CyberHawk IOC Scanner to enrich them with live threat intelligence. Detection engineering is a habit, not a project — fire a new ATT&CK technique every week and close the gap it reveals.

▸ Browse CyberHawk SOPs  ·  ▸ IOC Scanner  ·  ▸ More Tutorials

◈ Stay Connected

Follow CyberHawk Threat Intel for threat intelligence, deployment guides and hands-on SOC tooling content.

🌐 Website ▶️ YouTube ▶️ YouTube (2) 𝕏 Twitter / X ♪ TikTok ✈️ Telegram
🔍 IOC Scanner 🛠️ Live Tools 📚 Courses 🚨 Threat Intel 📝 Blog 📋 SOPs

"They can't exploit you if you are the Exploit."