Network Segmentation Using VLANs in Your Homelab

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:

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:

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:

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:

Example port configuration:

Watch out: If you tag all ports by mistake, your unmanaged devices (printers, cameras without VLAN support) will lose connectivity. Start conservative—tag only what needs it, and add more as you go.

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.

Tip: Start with a deny-all rule between VLANs, then add allow rules as you discover what needs to communicate. It's easier to add access than to realize you've blocked something critical.

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