Network Segmentation Using VLANs in Your Homelab
We earn commissions when you shop through the links on this page, at no additional cost to you.
When I first started running a homelab, everything lived on one flat network. My Raspberry Pi file server, Docker host, smart home devices, guest laptops—all on the same subnet, all able to talk to each other. Then one day a guest's compromised laptop started scanning my network, and I realized I needed better isolation. VLANs were the answer.
Virtual Local Area Networks aren't magic, but they're incredibly powerful for homelabs. They let you carve a single physical network into multiple logical ones, so IoT devices can't reach your Nextcloud server, guests get their own sandbox, and your Kubernetes cluster stays isolated from everything else. Today I'm walking you through exactly how I set this up.
Why VLANs Matter for Homelab Security
A flat network is convenient until it isn't. Here's what I've learned from experience:
- Lateral movement stops: Even if an IoT device gets compromised, it can't automatically pivot to your NAS or self-hosted Nextcloud instance. The switch enforces isolation at layer 2.
- Guest traffic is contained: When friends visit and connect their laptops, they're in their own VLAN. They can't accidentally (or intentionally) browse your services.
- Resource contention is clearer: When you isolate workloads, network saturation becomes easier to diagnose. Is my media server slow because of guest traffic or because of backup traffic? VLANs help you answer that.
- You can enforce different firewall rules: Your production VLAN gets strict ingress rules. Your IoT VLAN only needs outbound HTTPS. Your guest VLAN gets minimal privileges.
The catch? VLANs require a managed switch (starting around $100–150 for a gigabit 24-port), and your router needs to support VLAN trunking. If you're running consumer gear, you might hit limitations. I use an UniFi Dream Machine (around $300) paired with UniFi switches—the interface makes VLAN management painless, though you can do this with Mikrotik, Ubiquiti EdgeRouter, or even a Linux box running with VLANs on a basic switch if you're patient.
My VLAN Layout for a Typical Homelab
Here's what I actually run at home:
| VLAN Name | ID | Subnet | Purpose |
|---|---|---|---|
| Management | 10 | 192.168.10.0/24 | Router, APs, switches, admin tools |
| Production | 20 | 192.168.20.0/24 | Docker hosts, Nextcloud, Vaultwarden, databases |
| IoT | 30 | 192.168.30.0/24 | Smart home devices, cameras, sensors |
| Guest | 40 | 192.168.40.0/24 | Guest wireless, visitor devices |
| Lab/Experimental | 50 | 192.168.50.0/24 | Kubernetes, test containers, breaking things |
I keep management traffic separate because if something on your production VLAN goes haywire, you still want to SSH into your firewall. The lab VLAN lets me experiment without worrying about stability—if I accidentally flood the network with bad containers, it stays isolated.
Step-by-Step: Configuring VLANs on UniFi
If you're using Ubiquiti UniFi (my go-to for homelabs), here's exactly what I do:
1. Create the VLANs in the Controller
Log into your UniFi controller (usually at unifi.ui.com or your local IP), go to Settings → Networks → Create New Network.
For each VLAN, set:
- Name: "Production" (something descriptive)
- Purpose: Corporate (or Guest for guest VLAN)
- VLAN ID: 20 (your ID number)
- IPv4 Address: 192.168.20.1
- Subnet Mask: 255.255.255.0
- DHCP Mode: DHCP Server
- DHCP Range: 192.168.20.100 – 192.168.20.200
Repeat for each VLAN. The controller handles the routing between them automatically.
2. Configure Your Access Points
For wireless traffic, go to Settings → Wireless Networks → Create New Network.
Create a separate SSID for each VLAN (or use one SSID with guest isolation). For example:
- SSID: "HomeLab" → VLAN 20 (Production)
- SSID: "Guest" → VLAN 40 (Guest)
- SSID: "IoT" → VLAN 30 (IoT)
When a device connects to "Guest", it automatically lands on VLAN 40.
3. Tag Switch Ports
This is critical. In the UniFi controller, go to Devices → [Your Switch] → Ports.
For each physical port, decide whether it's:
- Untagged (access port): Device connects and automatically gets that VLAN. Use this for dumb devices like cameras or the VPS I order from RackNerd (around $40/year for a public VPS) that sits on the edge of my network.
- Tagged (trunk port): Port carries multiple VLANs. Use this for links between switches, or for a Proxmox host running multiple VMs on different VLANs.
Example port configuration:
- Port 1 (Proxmox Host): Tagged, allow all VLANs
- Port 2 (Docker Host): Untagged, VLAN 20 (Production)
- Port 5 (Aqara Hub): Untagged, VLAN 30 (IoT)
- Port 24 (Upstream to Main Switch): Tagged, all VLANs
Firewall Rules: Isolating Traffic Between VLANs
VLANs alone don't block traffic between subnets—routing does that. By default, your router will route between VLANs. You need firewall rules to deny what shouldn't cross.
In UniFi, go to Settings → Firewall & Security → Firewall Rules. Here's my ruleset:
# Allow Production to reach IoT (for home automation orchestration)
# Direction: Production → IoT
# Action: Accept
# Protocol: TCP/UDP
# Port: 8123 (Home Assistant)
# Block IoT from reaching Production
# Direction: IoT → Production
# Action: Drop
# Protocol: Any
# Block Guest from reaching Production
# Direction: Guest → Production
# Action: Drop
# Protocol: Any
# Block Guest from reaching IoT
# Direction: Guest → IoT
# Action: Drop
# Protocol: Any
# Allow all internal to reach Management (for DNS, NTP)
# Direction: Any → Management
# Protocol: UDP
# Port: 53, 123
# Action: Accept
# Allow Production and Management to reach Guest (for monitoring guest AP)
# Direction: Production/Management → Guest
# Action: Accept (specific management traffic only)
In practice, my UniFi controller translates this into a visual ruleset. The syntax varies by device, but the principle is: explicit allow, implicit deny. Every rule has a source VLAN, destination VLAN, protocol, port, and action.
Docker and VLANs on Your Host
If your Docker host is on VLAN 20 (Production), containers inherit that by default. But what if you want a container to live on a different VLAN? You'll need 802.1Q trunk tagging.
Here's a Docker Compose example where one service sits on the Production VLAN and another on the IoT VLAN:
version: '3.8'
services:
nextcloud:
image: nextcloud:latest
container_name: nextcloud
networks:
- prod_net
ports:
- "8080:80"
environment:
- MYSQL_HOST=db
- MYSQL_USER=nextcloud
- MYSQL_PASSWORD=secure_password
- MYSQL_DATABASE=nextcloud
db:
image: mariadb:latest
container_name: nextcloud_db
networks:
- prod_net
environment:
- MYSQL_ROOT_PASSWORD=root_password
- MYSQL_DATABASE=nextcloud
- MYSQL_USER=nextcloud
- MYSQL_PASSWORD=secure_password
influxdb:
image: influxdb:latest
container_name: influxdb_iot
networks:
- iot_net
environment:
- INFLUXDB_DB=iot_metrics
- INFLUXDB_ADMIN_USER=admin
- INFLUXDB_ADMIN_PASSWORD=admin_password
ports:
- "8086:8086"
networks:
prod_net:
driver: bridge
ipam:
config:
- subnet: 192.168.20.0/25
iot_net:
driver: bridge
ipam:
config:
- subnet: 192.168.30.0/25
This creates two isolated bridge networks within Docker. Nextcloud and its database talk to each other on prod_net, while InfluxDB (for IoT metrics collection) runs on iot_net. They don't cross unless you explicitly link them.
However, this is Docker-level isolation, not true VLAN separation. If you want real 802.1Q trunk tagging (so containers actually appear on different physical VLANs), you need to configure VLAN subinterfaces on your host OS and use macvlan or ipvlan drivers—that's a deeper dive beyond this article, but it's possible on Linux.
Testing Your VLAN Setup
Once configured, validate that isolation is working:
# From a Production