Network segmentation with Ubiquiti — why your homelab needs VLANs
I found out my Xiaomi security cameras were making DNS requests to servers in mainland China. That’s not unusual for IoT devices, and it’s probably harmless telemetry. But those cameras were on the same network as my Synology NAS, my K3s cluster, and every other device in my home.
That’s how I learned about VLANs. Not from a networking textbook, but from the realization that a compromised smart device could reach everything I cared about.
Why a flat network is a problem
Most home networks run everything on a single subnet. Your laptop, your phone, your smart plugs, your NAS, your printers, all on 192.168.1.0/24. They can all talk to each other freely.
This works fine until you think about what IoT devices actually are: small computers running firmware you can’t audit, often with poor update histories, talking to cloud services you don’t control. A compromised smart plug on your flat network can scan your NAS, attempt to reach your Kubernetes API, or sniff traffic from other devices.
Network segmentation puts boundaries between these groups. IoT devices get their own isolated network. Your lab infrastructure gets another. Management interfaces get a third. Each group can only talk to the others through firewall rules you explicitly define.
It’s the same principle used in enterprise networks, just scaled down to a home setup.
My VLAN design
I settled on four VLANs after some experimentation:
VLAN 10 (Management, 10.0.10.0/24): Switch management interfaces, Ubiquiti controller, IPMI-style access. Only my workstation can reach this VLAN. Nothing else needs to manage network infrastructure.
VLAN 20 (Lab/K3s, 10.0.20.0/24): All Raspberry Pi nodes, the K3s cluster, and services exposed through MetalLB. This is where the actual workloads live. It can reach the NAS for storage (specific ports only) but is otherwise isolated.
VLAN 30 (IoT, 10.0.30.0/24): Cameras, smart plugs, robot vacuum, anything with firmware I don’t control. This VLAN can reach the internet (so devices can phone home to their cloud services) but cannot initiate connections to any other VLAN.
VLAN 40 (Guest, 10.0.40.0/24): Guest Wi-Fi. Internet access only. No access to any internal network. I hand out the password without worrying about what devices guests bring.
Each VLAN has its own DHCP scope and DNS configuration. The Ubiquiti gateway handles routing between VLANs, with firewall rules controlling what’s allowed.
Ubiquiti setup
I run a UniFi Gateway (UDM-SE) and a USW-Lite-8-PoE switch. The UniFi controller manages everything from a single interface.
Creating VLANs is done in the Networks section. Each network gets a VLAN ID, a subnet, and a DHCP range. About two minutes per VLAN.
Port profiles determine which VLAN a physical port belongs to. My Raspberry Pi ports are assigned to the Lab profile (VLAN 20, untagged). The Synology NAS port is a trunk port carrying both VLAN 10 and VLAN 20 tagged, because the NAS needs to be reachable for both management and lab storage.
Firewall rules are the core of segmentation. I use a “deny by default” approach between VLANs and then add specific allows:
- Lab (VLAN 20) can reach NAS (VLAN 10) on Samba (445) and NFS (2049) ports only.
- IoT (VLAN 30) can reach the internet but nothing internal. Drop all inter-VLAN traffic from IoT.
- Management (VLAN 10) can reach everything, because that’s where I administer from.
- Guest (VLAN 40) gets internet only. No inter-VLAN traffic allowed.
- All VLANs can reach the gateway for DNS and DHCP.
Setting up these rules took about 30 minutes. Testing them took longer because I kept finding edge cases.
K3s-specific considerations
Running Kubernetes on a segmented network complicates things. The K3s nodes live on VLAN 20, but the pod network (flannel’s default VXLAN overlay, 10.42.0.0/16) and the service network (10.43.0.0/16) are internal to the cluster. Traffic from pods to external resources exits through the node’s VLAN 20 IP.
MetalLB assigns LoadBalancer IPs from a pool I defined on VLAN 20 (10.0.20.200-10.0.20.250). Services like Paperless-ngx, Grafana, and my ingress controller get IPs from this pool. My workstation on VLAN 10 can reach these services because the management-to-lab firewall rule allows it.
One thing to watch: if you use a CNI that does source NAT (and flannel does by default), your firewall rules see the node IP as the source, not the pod IP. This simplifies the firewall rules but means you can’t do per-pod firewall rules at the network level. For finer-grained control within the cluster, you’d use Kubernetes NetworkPolicies.
Common mistakes I made
I forgot to set DNS servers for some VLANs. Each VLAN has its own DHCP scope, and without a DNS server configured, devices got an IP but couldn’t resolve anything. The fix is simple: point all VLANs to the gateway as DNS, or run a dedicated DNS server (I use the gateway’s built-in DNS).
mDNS doesn’t cross VLANs. This caught me off guard. My AirPlay devices on the IoT network couldn’t be discovered from the main network. mDNS (Bonjour/Avahi) uses multicast, which doesn’t route between VLANs by default. The solution is an mDNS reflector. The UDM-SE has a built-in option for this under the network settings. Enable it for the VLANs that need device discovery.
I confused tagged and untagged ports for longer than I’d like to admit. A port can carry one untagged VLAN (the native VLAN) and multiple tagged VLANs. If you’re plugging in a device that doesn’t understand VLAN tags (like a Raspberry Pi with default configuration), the port should be set to the target VLAN as untagged. My NAS, which is VLAN-aware, gets a trunk port with tagged VLANs. I mixed these up and spent an evening wondering why my Pi nodes couldn’t get a DHCP lease.
I also assumed my firewall rules were correct because things worked. But “things work” and “things are isolated” aren’t the same statement. I spent an afternoon running nmap from each VLAN scanning the others to verify that blocked traffic was actually blocked. Found two rules that were too permissive. Worth the hour.
Was it worth it?
VLANs added maybe 30 minutes of initial setup and a few hours of debugging edge cases. In return, I know exactly what can talk to what on my network. My IoT cameras can phone home to their cloud service but can’t touch my NAS. A guest device can browse the internet but can’t discover my lab services.
It’s the kind of setup where you do the work once and then don’t think about it. Until something changes, like adding a new device or a new service, and you update a firewall rule. The peace of mind that comes from proper segmentation is hard to quantify, but after running a flat network for years, I can’t imagine going back.
If you’re running a homelab with any kind of IoT devices, VLANs aren’t optional. They’re the baseline.