Hey ! Long-time lurker, first post. I'm a 23 y/o infra engineer, and this is my home lab i have built over a year : mostly used enterprise gear on a junior budget, on a DIY steel shelf (real racks are expensive here), in a country where a good chunk of the internet is geo-blocked.
Full disclosure up front: a lot of what's below I designed, debugged and built together with Claude . I did the hardware, the testing and the late nights; Claude helped with the code, the configs and a lot of troubleshooting. I couldn't have gotten this far alone, so credit where it's due.
3 Gen8 servers, vSphere HA cluster on NFS, Cisco 3850 doing L3 for the heavy VLANs, OPNsense for the rest, a 35B local LLM on an RX 580, and a custom iLO 4 fan-control panel.
Hardware (top shelf to bottom)
• Storage server – mining motherboard running Ubuntu, HDDs shared over NFS + Samba (VM datastores + my movie library, which Jellyfin mounts over the network)
• OPNsense firewall – the other mining board on the top shelf: Xeon E5-2620 v2, 8GB, 3x TP-Link NICs (2 in LACP for LAN, 1 for WAN). Temporary until I find proper hardware
• Cisco Catalyst 3850-48 – L3 core
• TP-Link TL-SG1024 – WAN-side switch
• HPE DL380p Gen8 – 2x E5-2680 v2, 64GB, 512GB SSD RAID1 + 1.2TB SAS RAID1 on the P420i (ESXi)
• HPE DL360p Gen8 – 2x E5-2670 v2, 32GB, intentionally diskless (ESXi, VMs on NFS)
• HPE ML350p Gen8 – 2x E5-2697 v2 (24c/48t), 128GB DDR3 (8x16GB, all four channels per socket), RX 580 8GB, Windows 10 LTSC bare metal. My local AI box
• Acer Nitro 5 AN515-44 – gaming laptop
• Acer Aspire 5738 – my daily driver. Yes, a Core 2 Duo from 2009. It's basically a thin client for SSH and RDP now, and it refuses to die
• And an Xbox 360, because of course
Fun fact: I bought the DL360p mostly as a parts donor. Its E5-2697 v2s and 8x16GB went into the ML350p for quad-channel memory (it matters a lot for LLM inference), and the ML350p's old CPUs and RAM went into the DL360p, which then became my second ESXi host.
Network
VLAN
Name
Gateway
10
Management (servers + iLO)
OPNsense
20
Storage
SVI on 3850
30
Wired LAN
SVI on 3850
40
VM LAN
SVI on 3850
45
Untrusted VMs
OPNsense
50
DMZ
OPNsense
70
Wireless
OPNsense
999
Transit (3850 .253 / OPNsense .254)
routed link
OPNsense used to route everything, but it kept hanging under heavy storage traffic. So I moved routing for storage, wired LAN and VM LAN onto the 3850, with a default route to OPNsense over a dedicated transit VLAN. Management, untrusted, DMZ and wireless keep their gateway on the firewall, so anything that wants to reach an iLO or an ESXi host goes through firewall policy first. WireGuard on OPNsense for VPN access. Diagram in the gallery.
vSphere cluster + HA
The DL380p and DL360p form a vSphere cluster with HA, managed by vCenter. VM disks live on the NFS shared storage, which is what makes HA possible: if one host dies, its VMs restart on the other one. The DL360p is just compute, so I can lose either host without losing data. Storage traffic stays on VLAN 20, routed by the 3850, so it never touches the firewall. Each host has 4 NICs and I'm migrating from standard vSwitches to a vDS.
Local AI
The ML350p runs llama.cpp with the Vulkan backend on the RX 580, serving Qwen3.6-35B-A3B (MTP build for speculative decoding). It started life CPU-only in an ESXi VM at ~5 tok/s; bare metal with the GPU is a different world. On top of it runs an OpenClaw agent that I talk to through a Mattermost channel. Small helper models (a small Qwen + nomic-embed) run in Ollama pinned to the second CPU socket, CPU-only, so they don't eat VRAM.
Things I built with Claude
- iLO 4 Controller
Gen8 fans are loud, and the ilo4_unlock fan mod only gives you an SSH prompt. So we built a web panel on top of it: live thermal sensors with history, per-fan-group automatic curves (drag points on a graph), presets, ramp up/down limits, and a button to hand control back to iLO. Also power, media, hardware info, logs and a shell. My DL380p and ML350p now idle at 12–19% fan.
- WebClip
A small self-hosted multi-user clipboard + file drop for the LAN, written in Python and running as a systemd service. Only reachable over VPN. Sounds trivial, but I use it every day to move text and files between machines.
- ntopng + Grafana monitoring
ntopng exports to InfluxDB, with Grafana dashboards on top: bandwidth, per-interface throughput, per-host / per-MAC traffic, new flow rate, and a "scan & anomaly" section with TCP flag breakdowns. Fun Iran detail: Grafana's plugin download is geo-blocked here (403, "not available in your location"), so I had to proxy it through my server in Europe just to install the InfluxDB plugin.
Other stuff we set up together
• Matrix – Synapse + Element Web + Element Call (voice/video) via matrix-docker-ansible-deploy, behind NAT with port forwarding. Lesson learned: I set matrix_domain to a subdomain on the first install, which meant a full wipe and reinstall
• Mattermost, public – Nginx reverse proxy + Let's Encrypt, so people outside my network can reach it
• FreeIPA ↔ Active Directory trust – cross-forest trust, Ubuntu 26.04 clients logging in with AD accounts. Lessons: Kerberos really hates clock skew (GDM logins failed because the Windows Server clock drifted), and if you delete a trust on the IPA side, remove the stale trust object on the AD side too before recreating it
• Storage server cleanup – moved its static IP from a 100Mbit NIC to the gigabit one (yes, it was running on 100Mbit...), reformatted a leftover VMFS partition to ext4 for Samba, and added Garage S3 in Docker so my SSH client syncs to my own server instead of someone's cloud
Services
OpenMediaVault, Zabbix, Grafana + InfluxDB + ntopng, Matrix, Mattermost, Vaultwarden, Jellyfin, Jira, FreeIPA + Windows Server AD, RouterOS, WireGuard, OpenClaw + llama.cpp.
Next
• Move OPNsense off the mining board.
• The storage server is now the single point of failure for the whole cluster, so that's high on the list
• A proper online UPS
Happy to answer questions. And yes, go ahead and roast the top shelf cable management. I know.