Multi-VLAN Home Network
Overview
Four VLANs on a UniFi UCG Express, each named after one of Gandalf’s names from Tolkien, with ProtonVPN WireGuard routing on one segment and strict firewall rules between the rest. All public subdomains go through Cloudflare Zero Trust before any traffic reaches home.
Why I Built It
I had everything on a flat network for a long time. Servers, NAS, IoT devices, personal machines — all one subnet, nothing between them. That’s fine until you actually think about what it means, and then it feels bad.
What I really wanted was per-VLAN VPN routing without running WireGuard on every individual machine. The UCG Express does policy-based routing at the gateway level, so you put a device on the right VLAN and it routes through the VPN transparently. That’s the whole idea.
How It Works
| VLAN | Name | Subnet | Role |
|---|---|---|---|
| 1 | Gandalf | 192.168.1.x | Server network — Proxmox nodes, NAS, all services. No VPN. |
| 2 | Mithrandir | 192.168.2.x | Client/AI devices. All traffic through ProtonVPN WireGuard. |
| 3 | Tharkûn | 192.168.3.x | DMZ. Tharkûn → internal blocked. IoT and untrusted devices. |
| 4 | Rivendell | 192.168.4.x | Unused. Reserved. |
Olorín (the UCG Express, 192.168.1.1) is the gateway. It handles VLAN routing, firewall rules, DHCP reservations, and the WireGuard client. A Netgear MS308E managed switch sits downstream with a trunk port for all VLANs and access ports to devices.
Every homelab VM and service is on Gandalf — Proxmox, the Synology, n8n, Prometheus, everything. Importantly, DHCP reservations live in the UniFi controller rather than as static IPs on each host. That matters more than it sounds — I had a port forward break because a machine renewed its lease and changed IPs before I got this right.
ProtonVPN runs as a WireGuard client on the UCG Express itself. All Mithrandir traffic routes through it, and the kill switch is enabled: if the tunnel drops, Mithrandir devices lose internet entirely rather than falling back to unencrypted routing. That’s the correct behavior, even if it means a brief outage when the VPN hiccups.
Tharkûn is a practical DMZ. Devices there can reach the internet but can’t initiate connections into Gandalf or Mithrandir. Good enough for IoT devices that need to phone home but have no business talking to anything inside.
Public subdomains go through Cloudflare Zero Trust with GitHub IdP and MFA. Anything hitting proxmox.nbkelley.com or synology.nbkelley.com requires authentication first. Cloudflare tunnels handle ingress so the origin servers never see unprotected traffic directly.
Challenges
- The PBR incident. ProtonVPN’s WireGuard config went stale and the tunnel dropped. Everything on Mithrandir lost internet. This was the kill switch working correctly, but policy-based routing failures don’t advertise themselves clearly and it took a few minutes to sort out.
- DHCP vs. static IPs. Should have used reservations from day one. A port forward broke when a lease renewed and the IP changed — not obvious why until I looked at the right thing.
- UCG Express documentation. Some of the kill switch and routing configuration required more digging than expected. The UniFi docs for the OS version I was running were scattered and occasionally wrong.
- 2.5GbE link between UCG and switch. Took some fiddling with port settings on the Netgear side to get it working reliably.
Result
Stable. Haven’t had to touch the VLAN config in months. The VPN routing works, the DMZ segmentation works, and everything on Gandalf reaches what it needs to.
The kill switch has caught a couple of VPN drops that would have otherwise sent Mithrandir traffic out unencrypted. Worth the occasional brief outage.