DEV Community

Makita Tunsill
Makita Tunsill

Posted on

Building a Real SIEM Lab on a Mac Mini Fleet — What Actually Broke, and What I Learned Fixing It

Most "I built a home SOC" posts show you the pretty dashboard and stop there. This one is about what happened after the dashboard loaded — because that's where the real learning was.

🖥️ The setup

Three Mac Minis, one control machine, all Ubuntu. Mac Mini 1 runs the Wazuh manager, indexer, and dashboard — the security monitoring core. Mac Mini 2 handles AWS IAM permission scanning (Cloudsplaining, ScoutSuite). Mac Mini 3 is a documentation hub plus a custom vulnerability-intelligence pipeline pulling from the NVD API and NIST's CPRT compliance framework data. A fourth machine, my daily driver, orchestrates all three over SSH.

Today's goal: get every machine reporting into Wazuh, so I'd have real, fleet-wide visibility — not just a single monitored box.

🐛 Bug #1: the silent feed stall

After installing the Wazuh agent on Mac Mini 3, vulnerability scanning just... sat there. The log showed Initiating update feed process and then nothing. No error, no timeout, no progress.

I ruled things out methodically: DNS resolved fine, curl could reach Wazuh's CTI feed endpoint and complete a full TLS handshake, disk space was nowhere close to full, and there were no stale lock files sitting around. Every individual piece of the pipeline worked in isolation — but the feed download itself never completed.

The actual fix: upgrade Wazuh from 4.14.5 to 4.14.6. A newer point release fixed whatever was silently stalling the content-updater module. Once upgraded, the feed downloaded, decompressed, and the scanner came alive within minutes. Lesson: when every individual network/system check passes but a specific module still won't progress, check for a version-specific bug before going deeper down the debugging rabbit hole.

🔒 Bug #2: locking myself out with fail2ban

Mid-troubleshooting, my control machine's SSH connection to Mac Mini 3 started getting flatly refused — no prompt, no error, just Connection refused. Ping worked fine. Every other port responded. Just port 22, silently dead.

fail2ban was doing exactly its job: several failed login attempts (from me, testing wrong credentials at the LUKS pre-boot stage) had gotten my own control machine's IP banned. The fix was trivial once identified — fail2ban-client set sshd unbanip from another machine that still had access — but diagnosing it took a full port-by-port nc scan to notice that literally everything except SSH was reachable, which is the signature of an IP-level ban rather than a service failure.

💥 Bug #3: the one that actually hurt

Mac Mini 1's built-in local agent (ID 000, the manager monitoring itself) had a real limitation: its package/vulnerability data collected locally but never synced to the indexer, unlike genuine remote agents. I tried the obvious fix — install a standard wazuh-agent package alongside the existing wazuh-manager on the same box, pointed at 127.0.0.1.

That was a mistake. Both packages fight over the same /var/ossec directory. Installing the agent triggered a dependency conflict that silently uninstalled the manager entirely — service gone, core directories (bin, logs, queue) wiped.

Recovery: a database backup taken automatically just hours earlier (Wazuh's password-reset tooling creates one on every run, as a side effect) let me restore agent registrations without re-enrolling everything from scratch. Reinstalling wazuh-manager rebuilt the directory structure; restoring global.db from backup brought agent records back exactly as they were. Total data loss: about two hours of granular scan history that regenerates on its own.

The actual lesson isn't "don't make mistakes." It's: before touching a production monitoring stack, know where your backups live and confirm they're recent — because you may need them sooner than you think, for reasons you didn't predict.

🔑 Bug #4: two credential gaps that had been there since day one

Once the manager was back up, the dashboard's built-in API health check started throwing errors — first a rate-limit lockout (a different protection layer than fail2ban, this one built into the Wazuh API itself), then, once that cleared, a flat authentication failure.

Digging into it, I found the dashboard's config file was pointing at a wazuh-wui service account whose password had never actually been synced past its installer placeholder value. Deeper still: the account didn't even exist in the indexer's internal user database at all — a gap from the original install, invisible until the dashboard actually needed to authenticate through it.

Creating it properly meant generating a bcrypt hash with Wazuh's bundled JDK (the standalone hash.sh tool needs OPENSEARCH_JAVA_HOME set explicitly — it won't find Java on its own), manually appending the user to internal_users.yml, and pushing the change with securityadmin.sh authenticated via the actual admin certificate (not the node certificate — an easy mix-up, since both live in the same folder).

While in there, I also found the Wazuh API's own admin account was still sitting on its default factory password. Fixed that too, same session.

✅ What I'd tell someone starting this today

Version-pin your Wazuh components across the whole fleet, and check for point releases before assuming a stuck process is an environment problem.
Never install wazuh-agent and wazuh-manager side-by-side on the same host natively — if you need the manager to monitor itself as a full remote-style agent, containerize the agent instead.
Know exactly where your automatic backups land, before you need them.
Audit default credentials as a standing checklist item, not a reactive one — I only found the factory-password API account because a different bug forced me to test it.

🎯 Fleet-wide monitoring is live now, all four machines reporting, all default credentials closed out. It took longer than the tutorial version of this story would suggest — and that's exactly the part worth writing down.

Building this as part of First Step Technology's internal security lab — cybersecurity and technology risk advisory, Jacksonville, FL. 🛡️

Top comments (0)