The 2 AM Wake-Up Call # I woke up to find my CI/CD platform had been down for 8 hours. Semaphore, the Ansible automation engine that manages my entire homelab, was stuck in a crash loop:
1 2 3 /usr/local/bin/server-wrapper: line 295: syntax error: unexpected "&&" /usr/local/bin/server-wrapper: line 295: syntax error: unexpected "&&" /usr/local/bin/server-wrapper: line 295: syntax error: unexpected "&&" The same error, repeating every few seconds. The container would start, hit the broken entrypoint script, crash, and restart. Endlessly.
The Goal # Add all 4 Proxmox VE cluster nodes (pve-mini2, pve-mini3, pve-mini5, pve-mini6) to the existing Prometheus/Grafana stack on LXC 30194. The monitoring stack already covered Graylog, Windows desktop, and PAN-OS firewall metrics – Proxmox was the last major gap.
Approach: pve-exporter vs node_exporter # I evaluated two options:
Overview # Migrated the Prometheus + Grafana monitoring stack from a shared Docker VM to a dedicated LXC container. The shared VM hosted multiple stacks (pgAdmin, Portainer, monitoring) which created resource contention and made lifecycle management messy. Moving monitoring to its own LXC follows the homelab pattern of one service per container for cleaner isolation, backups, and management.
Why an XDR in a Homelab? # When I first started building out my homelab infrastructure, I fell into the same trap that catches most homelab enthusiasts: I assumed that being behind a firewall made me safe. After all, I wasn’t running a Fortune 500 network. I had VLANs, I had a next-generation firewall doing deep packet inspection, and I kept my systems patched. What more did I need?
The Problem # Watchtower had been my go-to for automatic Docker container updates across 8+ services. It worked… mostly. But I kept running into issues:
Opt-out model is dangerous - Watchtower watches ALL containers by default. I had to remember to add com.centurylinklabs.watchtower.enable=false to containers I didn’t want updated. Forgetting meant surprise updates.
No visibility - Updates happened silently at 4 AM. I only knew something updated when it broke. No dashboard, no easy way to see pending updates.
The Challenge # I needed a unified security monitoring solution that could:
Provide endpoint detection and response (XDR) capabilities Integrate with my existing Graylog centralized logging infrastructure Scale from a single-node deployment to multi-node if needed Work with my existing OpenClaw threat intelligence feeds The Solution # Wazuh Single-Node Stack # Deployed Wazuh as a Docker-based single-node stack. The single-node architecture includes:
The Problem # I noticed my Graylog VM was consuming more memory than expected. The VM has 4GB RAM allocated, but both Graylog and OpenSearch were competing for memory, leaving little headroom for the operating system’s filesystem cache.
What I Tried # First, I checked memory usage on the Graylog VM:
What Changed # Pinned Graylog’s JVM heap to 1GB by adding explicit GRAYLOG_SERVER_JAVA_OPTS to docker-compose.yml:
1 GRAYLOG_SERVER_JAVA_OPTS: "-Xms1g -Xmx1g -XX:NewRatio=1 -server -XX:+UseG1GC" Why # Noticed high memory usage on the Graylog VM. JVM ergonomics was auto-allocating ~2GB for Graylog, leaving insufficient RAM for OS filesystem cache. OpenSearch query performance suffers without cache headroom.
What Changed # Upgraded Watchtower notifications from plain text to Discord embeds using Shoutrrr URL parameters:
Added colored sidebar (green for updates) Suppressed noisy startup messages Cleaner, more readable notifications Why # Plain text Watchtower notifications were hard to scan in busy Discord channels. Embeds provide visual structure and color-coding.