Why this matters beyond the homelab: VLAN segmentation, inter-zone firewall policy, and managed switching are the same skills behind enterprise network engineering, Azure Virtual Network design (subnets, NSGs, hub-spoke topology), and compliance-driven infrastructure (PCI-DSS, HIPAA, SOC 2). The threat model driving each boundary here is identical to the one behind a production landing zone.
The Rack
Everything runs inside a Rackpi T1, a 10-inch form factor rack. Compact, wall-mountable, and purpose-built for small-footprint homelabs. The three Proxmox nodes, the UniFi switch, and the gateway all live here.
10-inch form factor matters for the hardware decisions downstream. Standard 19-inch rack equipment does not fit. Every piece of network hardware in the fleet was selected with that constraint in mind.
Network Hardware
| Device | Model | Role |
|---|---|---|
| Gateway | UniFi Dream Machine | Routing, inter-VLAN firewall, VLAN management, threat management |
| Switch | UniFi US-8-150W | PoE managed switch, VLAN trunking to all nodes |
| WiFi | UniFi Beacon HD | Wireless connectivity across all VLANs |
The entire stack is UniFi. That is intentional. A unified controller means VLAN policy, firewall rules, and wireless configuration are all managed in one place. No cross-platform policy drift, no separate firewall and switch rule sets to keep synchronized.
Why the UniFi Dream Machine, Not OPNsense
The fleet originally ran OPNsense as a dedicated firewall. The reasoning was sound: more granular firewall API access, better automated threat response integration, and a clear separation between routing and security enforcement.
The problem was the ISP modem. Running OPNsense as a second gateway behind the ISP modem created a dual-gateway topology that caused persistent IP release failures. The ISP modem would not reliably hand off the WAN IP under load, which introduced intermittent internet drops that were difficult to diagnose and impossible to fully resolve without replacing the ISP hardware.
The decision was to consolidate to the UniFi Dream Machine as the single gateway and firewall. The tradeoff is less granular firewall API access. The automated IP blocking that previously ran via the OPNsense API is being rebuilt for the UniFi platform. Detection and alerting through Wazuh and n8n remain fully operational in the meantime.
Reliability over capability. A firewall that drops connections is worse than a less capable firewall that stays up.
UCG-Fiber: The Upgrade Target
The UDM handles the current traffic load without issue. The upgrade target is the UCG-Fiber, which adds 10GbE uplink capacity and a more capable firewall engine. The primary driver is the nightly backup pipeline: vzdump snapshots moving from all three nodes to Node-B over the local network saturate the current 1GbE uplink during the 3AM window.
The VLAN structure, IP addressing, and firewall policy all carry over. The UCG-Fiber is a hardware swap, not a network redesign. The UniFi Network application also runs natively on the UCG-Fiber, which eliminates the need for a separate Cloud Key or controller VM.
VLAN Structure
Five active VLANs, each named after a Star Wars planet. The naming convention mirrors the rest of the fleet.
╔══════════════════════════════════════════════════════════════════════════╗
║ VLAN TOPOLOGY ║
╠══════════════════════════════════════════════════════════════════════════╣
║ ║
║ VLAN 10 - MANAGEMENT / TATOOINE (192.168.1.0/24) ║
║ ├─ 192.168.1.1 UniFi Dream Machine (Gateway/Firewall) ║
║ ├─ 192.168.1.2 UniFi US-8-150W (Switch) ║
║ ├─ 192.168.1.10 Node-A (Millennium Falcon) ║
║ ├─ 192.168.1.11 Node-B (CR90 Corvette) ║
║ ├─ 192.168.1.12 Node-C (Gozanti Cruiser) ║
║ ├─ 192.168.1.50 ALLIANCE-DC01 (Windows Server 2022) ║
║ └─ No DHCP, static assignments only ║
║ ║
║ VLAN 20 - SERVICES / NABOO (192.168.20.0/24) ║
║ ├─ 192.168.20.10 Authentik SSO ║
║ ├─ 192.168.20.20 Tantive-III (Ollama, OpenWebUI, ComfyUI) ║
║ ├─ 192.168.20.30 Wazuh SIEM ║
║ ├─ 192.168.20.40 Grafana ║
║ ├─ 192.168.20.41 InfluxDB ║
║ ├─ 192.168.20.50 n8n Automation ║
║ ├─ 192.168.20.51 Vaultwarden ║
║ ├─ 192.168.20.86 Canto-Bight (Windows 11 Pro, AD test workstation) ║
║ └─ DHCP .100-.200 for future services ║
║ ║
║ VLAN 30 - IoT / MUSTAFAR (192.168.30.0/24) ║
║ ├─ 192.168.30.10 Home Assistant ║
║ ├─ Smart home devices ║
║ └─ Isolated, cannot initiate to Management or Services ║
║ ║
║ VLAN 40 - DMZ / SCARIF (192.168.40.0/24) ║
║ ├─ 192.168.40.10 Nginx Proxy Manager (TLS termination, rate limiting) ║
║ ├─ Public-facing ingress only ║
║ └─ No DHCP, static assignments only ║
║ ║
║ VLAN 50 - BOT-NET / SECURITY SANDBOX (192.168.50.0/28) ║
║ ├─ 192.168.50.10 Fulcrum VM204 (K-2SO) ║
║ ├─ Triple isolation: no LAN, no internet, Discord webhooks only ║
║ └─ No DHCP, static assignments only ║
║ ║
╚══════════════════════════════════════════════════════════════════════════╝
| VLAN | Planet | Name | Subnet | DHCP | Purpose |
|---|---|---|---|---|---|
| 10 | Tatooine | Management | 192.168.1.0/24 | Disabled | Hypervisors, network hardware |
| 20 | Naboo | Services | 192.168.20.0/24 | .100-.200 | All production workloads |
| 30 | Mustafar | IoT | 192.168.30.0/24 | .100-.200 | Smart home, fully isolated |
| 40 | Scarif | DMZ | 192.168.40.0/24 | Disabled | NPM, public-facing ingress |
| 50 | Bot-Net | Security Sandbox | 192.168.50.0/28 | Disabled | K-2SO triple isolation |
Why Each Boundary Exists
VLAN 10: Tatooine (Management)
Proxmox nodes, the UDM, and the switch live here. Nothing else does. DHCP is disabled. Every host is statically assigned.
Management traffic is the highest-value target on any network. A compromised VM on VLAN 20 should not have a direct path to probe the hypervisor it is running on. Keeping management isolated enforces that boundary at the network layer, not just the application layer. This mirrors Azure’s dedicated management subnets and just-in-time VM access patterns.
ALLIANCE-DC01 also lives here. The domain controller sits on the management VLAN because it is infrastructure, not a workload. Placing it on VLAN 20 with application services would mean a compromised service has a path to Active Directory. That is not an acceptable blast radius.
VLAN 20: Naboo (Services)
Every production workload lives here. Authentik, Wazuh, NPM on the services side, Grafana, InfluxDB, n8n, Vaultwarden, Canto-Bight. This is the largest and most active segment.
Intra-VLAN communication is permitted because most services need to reach each other: Grafana queries InfluxDB, n8n calls Authentik for OAuth, NPM proxies to everything. Authentik enforces application-layer access control on top of the network-layer permissiveness.
DHCP is enabled here with a range reserved for future services. New workloads come up on VLAN 20 by default and get statically assigned IPs after they prove stable.
VLAN 30: Mustafar (IoT)
Home Assistant and all smart devices. Isolated because IoT firmware quality is historically poor and update cycles are slow. Consumer IoT devices are an accepted permanent vulnerability. The mitigation is containment.
VLAN 30 can reach the internet. It cannot initiate connections to Management or Services. Home Assistant has a specific firewall rule allowing it to reach InfluxDB on VLAN 20 for telemetry. That is the only permitted cross-VLAN path from VLAN 30. Everything else from Mustafar is dropped at the UDM.
VLAN 40: Scarif (DMZ)
Nginx Proxy Manager lives here. This is the only surface that accepts inbound traffic from the internet, and only through Cloudflare proxy. NPM handles TLS termination and rate limiting before any request reaches VLAN 20.
DHCP is disabled. The DMZ is a controlled ingress point. Unauthorized hosts on Scarif represent a direct attack surface against production services.
The traffic flow for any external request:
Internet
└─ UniFi Dream Machine (firewall, threat management)
└─ VLAN 40 / Scarif: NPM (TLS termination, rate limiting)
└─ VLAN 20 / Naboo: Authentik (SSO, MFA evaluation)
└─ VLAN 20 / Naboo: Backend service
VLAN 50: Bot-Net (Security Sandbox)
K-2SO lives here in triple isolation: no LAN access, no internet access, Discord webhooks only. The /28 subnet (192.168.50.0/28) is intentionally small. This VLAN is not designed to grow. It exists for one workload.
The isolation exists because K-2SO is an automation bot with elevated Discord permissions and access to infrastructure observability data. Bots that make external API calls and run automation logic are a lateral movement risk if compromised. The correct mitigation is to give them the minimum viable network path: Discord webhooks out, nothing else.
DHCP is disabled. Static assignments only.
Enforcement Layer: UniFi
All inter-VLAN routing and firewall policy is enforced at the UDM. The rule logic follows a default-deny posture between VLANs with explicit allow rules for required cross-segment traffic:
- VLAN 30 to VLAN 20: allow InfluxDB port only (Home Assistant telemetry)
- VLAN 40 to VLAN 20: allow NPM proxy ports (controlled ingress)
- VLAN 50 to internet: allow Discord webhook endpoints only
- Management to all: allow (required for Proxmox node management)
- All to Management: deny
- IoT to Management or Services: deny
- Bot-Net to LAN: deny
Everything not explicitly permitted is dropped.
One known workaround: the Bot-Net to NPM firewall rule currently has no port specifier due to a conflict with UniFi Direct Remote Connection on port 443. Tailscale handles all remote access so Direct Remote Connection is not needed. The rule will be tightened to port 443 only once that decision is confirmed.
Remote Access: Tailscale
No ports are exposed to the internet. Remote access to every service in the fleet runs exclusively through Tailscale. Node-C advertises the management subnet to authorized Tailscale clients.
┌─────────────────────────────────────────────────────────────┐
│ TAILSCALE OVERLAY │
├─────────────────────────────────────────────────────────────┤
│ 100.x.x.10 --> Node-A (Millennium Falcon) │
│ 100.x.x.11 --> Node-B (CR90 Corvette) │
│ 100.x.x.12 --> Node-C (Gozanti Cruiser) <- Subnet Router │
│ 100.x.x.20 --> Selected VMs/Containers │
└─────────────────────────────────────────────────────────────┘
The practical result: the UDM firewall ruleset only handles inter-VLAN policy. It does not manage inbound internet traffic, NAT rules, or VPN termination. Tailscale handles all of that at the identity layer. The firewall stays simple. Simple firewall rules are auditable firewall rules.
DNS as a Security Layer
AdGuard Home on VLAN 20 serves as the DNS resolver for all VLANs. Internal service resolution uses split DNS: *.fleet.local resolves to internal IPs, external queries forward upstream with filtering applied.
DNS resolution and network access are separate enforcement points. A device on VLAN 30 can resolve a VLAN 20 hostname. The UDM firewall will still drop the connection if no inter-VLAN rule permits it. DNS alone is not a firewall, and the architecture does not treat it as one.
Related Posts
- The Architecture: Measure Twice, Cut Once
- Node-C: The Gozanti Cruiser, Security Sentinel
- Tailscale Split DNS and AdGuard: Remote Access Without Opening a Single Port
- NPM and UniFi Firewall Rule Ordering: The Silent Traffic Drop
- Deploying Authentik SSO Across 15+ Services: The Full Integration Playbook