Guest VLAN - tagged on the trunk port

Segmenting Your Proxmox Homelab: Practical VLAN Configuration and Firewall Rules

Proxmox Pulse Proxmox Pulse
9 min read
Colored ribbons flowing through transparent channels representing tagged network traffic on trunk ports

Segmenting Your Proxmox Homelab: Practical VLAN Configuration and Firewall Rules

If your homelab runs everything on a single flat network, the solution is usually straightforward—break traffic into separate broadcast domains using Linux bridges with trunk ports for LXC containers (tagged) or KVM VMs doing their own tagging internally. When combined with per-VLAN firewall rules in Proxmox's built-in nftables-based system and SSH hardening tuned to your new topology, you get real network isolation without needing extra appliances. This post walks through the exact configuration steps I use on production homelabs running 10-25 VMs across four VLANs for guest traffic, management services like Home Assistant and Docker workloads, storage replication between nodes via Automated Backups with Proxmox Backup Server, and a dedicated K3s cluster for Kubernetes development.

Key Takeaways

  • Tagged Traffic — LXC containers need tag=10 in their config file to send tagged frames on the physical interface; KVM VMs tag internally so they can use untagged traffic with an external VLAN-aware bridge
  • Per-VLAN Firewall Rules — Proxmox's built-in firewall evaluates nftables rules per network, letting you isolate guest and management subnets without extra software like CrowdSec on Proxmox at the hypervisor level
  • SSH Hardening + VLAN Segmentation — Restricting SSH to a single management VLAN while running services across others cuts your attack surface more than either measure alone
  • Trunk vs Access Ports — One trunk port per host is simpler and scales well; multiple access ports distribute NIC load but complicate cabling

How Do VLANs Actually Work on Proxmox?

The term "VLAN" gets thrown around loosely, so let's pin it down in the context of Proxmox VE. A virtual LAN creates a separate Layer 2 broadcast domain within your existing physical network infrastructure—typically carried over an Ethernet trunk port that carries multiple tagged frames to and from different VLANs on the same cable.

Proxmox handles this through Linux bridges, which are kernel objects created by ip link add or managed via the GUI's Network tab. You create a base bridge (usually named vmbr0) with your IP address for management traffic, then optionally define additional sub-interfaces:

auto vmbr1
iface vmbr1 inet manual
    vlan-id 20
    bridge_ports eth0
    bridge_stp off
    bridge_fd 0

The key insight is that vlan_id on the interface tells Linux to strip and reapply tags for traffic flowing through that specific VLAN. When you attach a container or VM to vmbr1, it communicates with other devices tagged as VLAN 20—including your router—without needing any extra configuration in guest OSes (for LXC at least).

This is different from Configuring VLANs on Proxmox with Linux Bridges which covers the basics more broadly. Here I'm focusing specifically on a practical homelab setup where you're running mixed workloads and need to keep them separated without buying an extra switch or rewiring everything.

Setting Up Your Trunk Port for LXC Containers

The most common configuration is using your primary bridge as a trunk port that carries untagged management traffic plus tagged VLAN frames out the physical NIC (usually eth0). Here's what my typical vmbr0 looks like:

auto eth0
iface eth0 inet manual

auto vmbr0
    iface vmbr0 inet static
        address 192.168.1.5/24
        gateway 192.168.1.1
        bridge-ports eth0
        bridge-stp off
        bridge-fd 0

# Guest VLAN - tagged on the trunk port
auto vmbr1
    iface vmbr1 inet manual
        address 172.16.10.5/24
        vlan-id 30
        bridge-ports eth0

Note that vmbr1 has no gateway—it's a pure Layer 2 interface on the trunk. Guest containers attached to vmbr1 see their traffic tagged as VLAN 30 when it leaves the host and untagged inside the container itself (assuming you set up tagging in the LXC config). The router handles inter-VLAN routing, so your guest services can reach both subnets transparently.

For a homelab with four or more VLANs—say one for guests, one for management/monitoring tools like Cockpit on Proxmox and Prometheus, one dedicated to Docker workloads running in LXC containers (see also Docker Inside LXC on Proxmox: A Practical Guide), and a fifth for storage replication—this single-trunk approach scales cleanly. Each VLAN gets its own bridge sub-interface without needing additional physical NICs or complex bonding setups.

KVM VM Tagging vs LXC Containers

Here's where the distinction matters: KVM VMs tag their traffic internally using virtio-net, so they can connect to a plain (untagged) vmbr0 and still communicate with tagged VLAN devices. The hypervisor handles the tagging transparently through QEMU. This means your Windows or Linux KVM guest doesn't need any special configuration—it just sees eth0 as an ordinary network adapter connected to vmbr0.

LXC containers, on the other hand, use veth pairs and pass-through networking by default (since Proxmox 8). A container attached directly to vmbr1 with VLAN tagging enabled receives tagged frames. If you want that traffic untagged inside the LXC—so your services see eth0 as an ordinary interface—you set up a "VLAN-aware" bridge:

auto vmbr2
    iface vmbr2 inet manual
        address 172.16.20.5/24
        vlan-id 40
        bridge-ports eth0
        bridge-vlan-aware yes

The bridge-vlan-aware option tells Linux to maintain a VLAN database on the interface and strip tags for attached containers while reapplying them when traffic leaves the host. This is particularly useful if you're running Docker in Proxmox LXC workloads that expect standard Ethernet frames, or your container OS has limited VLAN support (Debian-based LXCs handle tagged bridges fine; Alpine and older Ubuntu versions can be picky).

A quick gotcha: if you're migrating an existing homelab from bare metal to Proxmox VE on a converted old laptop with only one NIC, make sure your upstream switch port is configured as a trunk. A misconfigured access-port-only uplink will silently drop all tagged traffic and leave you wondering why containers can't reach the router despite having correct IP addresses.

Per-VLAN Firewall Rules in Proxmox VE

Proxmox's built-in firewall (enabled globally via pve-firewall start) uses nftables under the hood, making it fast enough for homelab use without adding another daemon like CrowdSec or a full iptables setup. The key advantage: rules are evaluated per network interface and can be scoped to specific VLANs using zone-based policies.

To apply firewall rules to vmbr1 (your guest VLAN):

# Enable firewall on the bridge
pct set <CTID> --firewall 0        # Disable for containers that need full access
iptables -I INPUT -i eth0 -m conntrack \
    --ctstate NEW,ESTABLISHED -j ACCEPT

# Add rule to allow guest traffic only within VLAN and management subnet
nft add rule inet fw4 input iifname "vmbr1" ip saddr 172.16.10.0/24 accept

For a more structured approach using the Proxmox API or CLI:

# Create a new firewall zone for guest VLAN
pve-firewall add rule --net vmbr1 \
    --action ACCEPT \
    --source 172.16.10.0/24 \
    --destination any

# Block all other traffic on this bridge by default (if using the "default deny" mode)
pve-firewall set net/vmbr1 --policy_in DROP --policy_out ACCEPT

The practical benefit here is that you can isolate your guest workloads from management services without additional hardware. If a container in vmbr2 gets compromised, it still has outbound access but can't reach 192.168.1.x (your host and router) unless explicitly allowed by rules on the bridge's input chain.

SSH Hardening Tied to VLAN Segmentation

Network segmentation alone doesn't stop brute-force attacks—it just limits where they come from. Pairing it with SSH hardening gives you defense in depth: fail2ban blocks repeated authentication failures, while firewall rules restrict which VLANs can even reach port 22 on the host's management IP (192.168.1.5).

# Install and configure fail2ban for SSH with a tighter threshold
apt install -y fail2ban

cat > /etc/fail2ban/jail.local << 'EOF'
[sshd]
enabled = true
port    = ssh
filter  = sshd-agent
logpath = /var/log/auth.log
maxretry = 3
findtime = 600
bantime  = -1

# Whitelist management VLAN so your host stays reachable from within the lab
ignoreip = 127.0.0.1/8 ::1 192.168.1.0/24 172.16.0.0/16
EOF

systemctl restart fail2ban

The bantime = -1 setting keeps offending IPs banned permanently until you manually remove them—useful in a homelab where the same device might retry SSH after being temporarily locked out. The whitelist ensures your management VLAN (including any host running Ansible playbooks or backup agents) stays reachable even if fail2ban catches legitimate-but-rapid connections from a script.

For extra protection against external threats, you can combine this with Cloudflare Tunnel on Proxmox for zero-trust access to your management services without opening additional ports:

# If using Cloudflared as a tunnel agent alongside local SSH hardening
systemctl enable cloudflared.service --now
cloudflared service install

Single Trunk vs Multiple Bridges — Which Scales Better?

For homelabs with 10-25 VMs, the single-trunk approach works well. But if you're running Docker in LXC heavily or have a lot of inter-container traffic (like services communicating via internal DNS), there's an honest tradeoff to consider:

Approach Pros Cons
Single trunk port, multiple VLANs on one bridge sub-interface Simple cabling; fewer physical ports used; easy to add new VLANs without adding NICs or bridges Higher CPU overhead for packet tagging/untagging on older hardware (ARM Pis struggle around 8+ active VLANs); single point of failure if the trunk link drops
Multiple access ports, one bridge per VLAN Lower per-interface CPU cost; each port handles only untagged traffic so there's no virtualization penalty in Linux; easier to migrate a specific VM or container between physical NICs during maintenance windows More cabling and switch-port usage; harder to add new services without adding another interface (e.g., if you're building your software-defined datacenter incrementally)

My rule of thumb: stick with a single trunk port unless your homelab has specific performance requirements—like running GPU-accelerated workloads that push 1+ Gbps through the storage VLAN, or if you're using Proxmox VE on ARM where every CPU cycle counts for interrupt processing.

Conclusion

Segmenting your Proxmox homelab with Linux bridges and trunk ports gives real network isolation without requiring extra hardware—LXC containers handle tagged traffic natively, KVM VMs do it internally through virtio-net, and the built-in firewall evaluates rules per-VLAN using fast nftables chains. Pair this with fail2ban for SSH hardening tuned to your VLAN whitelist, and you've got a solid defense against both lateral movement within the lab and brute-force attacks from outside.

The next step is usually setting up Automate Proxmox VE: Essential Scripts for Homelab Backups to monitor your VLAN health—check that tagged frames are flowing correctly, verify fail2ban isn't over-banning legitimate hosts, and track which containers have been assigned to the right bridge interfaces. From there you're ready for more advanced setups like Cluster-Wide Brute-Force Defense or a full K3s cluster on dedicated VLAN-backed VMs without worrying about noise from guest services bleeding into your management plane.

Share
Proxmox Pulse

Written by

Proxmox Pulse

Sysadmin-driven guides for getting the most out of Proxmox VE in production and homelab environments.

Related Articles

View all →