Architecture: What I Actually Run
Three physical hosts, one router, one LAN, and a clear split of roles so that services stay manageable.
Physical layout
- Router: MikroTik hEX. Single wired router: firewall, DHCP server, gateway. No VLANs; one flat subnet. Wi‑Fi is handled by APs, not the hEX.
- Switch: One unmanaged PoE switch in the network closet between the router and the rest (powers the APs; connects all hosts).
- Wi‑Fi: Four MikroTik hAP ac² access points, managed centrally via CAPsMAN on the hEX. Each AP has a built-in 5-port switch — one port provides wired backhaul to the primary PoE switch; remaining ports connect local devices. Two SSIDs (2.4 GHz and 5 GHz names); same security for seamless roaming. Per-AP fixed channels on 5 GHz (and tuned 2.4 / TX power) so neighbors on wired backhaul do not stomp the same spectrum. Same LAN as everything else.
- Desktop Host (daily driver + hypervisor): Windows PC, Intel i7-11700K, 128 GB RAM, NVIDIA RTX 3070. My main desktop and the Hyper-V host. Plex Media Server and Ollama (local LLM inference on the GPU) run on the Windows host directly; media libraries live on the NAS Host over SMB. Four VMs: Docker host (Ubuntu), nginx proxy + keepalived BACKUP (Ubuntu), dedicated Minecraft server (Ubuntu), and Stoat Chat (Ubuntu). The Docker VM runs Vaultwarden, Mealie, Paperless-ngx, ConvertX, IT-Tools, Donetick, Homepage, OpenWebUI, Uptime Kuma, Pi-hole, Loki, Prometheus, Grafana, and more.
- NAS Host (storage + Pi-hole): Ubuntu LTS + ZFS, AMD Ryzen 5 2600, 48 GB RAM, 4×8 TB in RAIDZ1. SMB shares for the Desktop Host and Plex media libraries. All backups land here. One Pi-hole instance runs as a Docker container. Also runs Grafana Alloy for metrics and log shipping.
- Proxy Host (bare-metal, network closet): GMKtec NucBox G11, AMD Ryzen Embedded R2514 (8 cores), 16 GB RAM, 512 GB NVMe — provisioned 2026-07-01. Primary nginx (keepalived MASTER, holds VIP), Pi-hole 3 (Docker), and Docker Engine. Located in the network closet on a UPS (shared with ONT, router, and switch); wired directly to the switch. Runs certbot, DDNS (via keepalived notify when it holds the VIP), fail2ban, and UFW.
So: one Windows Hyper-V host (Desktop Host) with four VMs, one Ubuntu NAS, and one bare-metal Ubuntu host (Proxy Host); nginx and Pi-hole spread across all three active hosts.
Why this split?
- Daily driver on the Desktop Host — I use that machine every day. The important VMs (Docker, nginx proxy, Pi-hole) keep running when I’m not at the desk.
- Plex on the Desktop Host — Plex runs on the Windows install (same machine as Hyper-V and Ollama). Libraries stay on the NAS Host via SMB; the RTX 3070 handles hardware transcoding.
plex.detellem.comhits nginx on the VIP, then the Plex port on the Desktop Host. - Pi-holes — Three active instances (Docker container on the Docker VM, Docker container on the NAS Host, and Docker container on the Proxy Host). All run with
network_mode: host. Clients receive all three Pi-holes plus a Google DNS fallback via DHCP. If one fails, clients use the next. Nebula Sync keeps blocklists and settings synchronized from the primary every 15 minutes. - nginx HA pair — The internet hits the router on 80/443; it forwards to a virtual IP (VIP) held by keepalived. The Proxy Host is the preferred MASTER; the nginx VM on the Desktop Host is BACKUP. If the MASTER’s nginx fails a health check, the VIP moves to the BACKUP automatically. Config and cert sync from the config primary (nginx VM) to the Proxy Host are active.
- Proxy Host in the network closet — Co-located with the ONT, router, and switch on a shared UPS. This means the primary nginx node stays up during brief power outages even if the Desktop Host and NAS Host lose power. It’s also wired directly to the switch for maximum reliability.
Diagram (conceptual)
Internet
│
▼
┌─────────────────────────────────────┐
│ Network Closet (on UPS) │
│ │
│ ISP ONT → MikroTik hEX (router) │
│ DHCP, firewall, NAT │
│ │ │
│ PoE Switch ───────┴──── Proxy Host │
│ │ │ │ │ (nginx, │
│ │ │ │ │ Pi-hole 3, │
│ │ │ │ │ keepalived)│
└───┼──┼──┼──┼─────────────────────────┘
│ │ │ │
┌──────┘ │ │ └──────┐
│ │ │ │
┌────▼────┐ ┌──▼──▼──┐ ┌────▼────┐
│ AP 1 │ │ AP 3/4 │ │ AP 2 │
│(5-port) │ │ (Wi-Fi │ │(5-port) │
│ + Wi-Fi │ │ only) │ │ + Wi-Fi │
└────┬────┘ └─────────┘ └────┬────┘
│ wired │ wired
▼ ▼
┌─────────────────────────┐ ┌─────────────────────────┐
│ Desktop Host │ │ NAS Host │
│ Win + Hyper-V │ │ Ubuntu + ZFS │
│─────────────────────────│ │─────────────────────────│
│ Windows: │ │ 4×8 TB RAIDZ1 │
│ Plex, Ollama (RTX 3070)│ │ SMB shares (media, │
│ │ │ backups, documents) │
│ VMs: │ │ Pi-hole 2 (Docker) │
│ • Docker VM │ │ Backup target (all hosts)│
│ Vaultwarden, Mealie, │ │ Grafana Alloy agent │
│ Paperless, ConvertX, │ └─────────────────────────┘
│ IT-Tools, Donetick, │
│ Homepage, OpenWebUI, │
│ Uptime Kuma, Pi-hole 1│
│ Loki, Prometheus, │
│ Grafana │
│ • nginx VM (BACKUP) │
│ • Minecraft VM │
│ • Stoat Chat VM │
└─────────────────────────┘
Each AP has a built-in 5-port switch. One port per AP provides 1 Gbps wired backhaul to the primary PoE switch; the remaining ports connect local devices. The Desktop Host and NAS Host are each wired to an AP’s switch port — not wireless, but routed through the AP’s backhaul to the main switch. The Proxy Host is the only infrastructure box wired directly to the primary PoE switch (co-located in the network closet).
Tech choices in one sentence
- Hyper-V — I’m on Windows anyway; VMs are isolated and easy to snapshot. No Proxmox/KVM here.
- Ubuntu + ZFS — ZFS, SMB, and Docker (like Pi-hole) on one box. Media and backups live here; Plex and the rest mount it.
- MikroTik — Router and CAPsMAN in one place; CLI and Winbox; cheap and flexible. DHCP reservations live on the hEX.
- nginx + keepalived — One reverse proxy in front of everything; two nodes and a floating VIP so I only forward one address from the router. The Proxy Host holds the VIP under normal operation (UPS-protected, directly wired); certbot and config authoring run on the nginx VM, with sync to the Proxy Host.
- UPS strategy — The network closet (ONT, router, switch, Proxy Host) is on a single UPS so the primary nginx and internet connectivity survive brief power interruptions. The Desktop Host and NAS Host are not UPS-protected — if they go down, services degrade but DNS and the reverse proxy stay up.
If you want to go deeper on any of these, the links in the next sections point to official docs.