Skip to main content

Proxmox VE 9.0 - Optimizing Network Interfaces Configuration

Introduction

After going through what is described on the previous pages, I have the following network interfaces configuration at Proxmox:

image.png

That said, seeing all this mess is what they call "bridge explosion." I have a mix of traditional Linux bridges, host-level VLAN subinterfaces, and a legacy naming convention that doesn't scale well.

We can absolutely streamline this layout, reduce the host-level configuration footprint, and make the whole environment much more elegant by migrating to a VLAN-Aware Bridge model.


The Cheat Sheet: Virtual to Physical Terms

Virtual networking can be a total brain-melter because you can't physically trace where the copper cables are going. 

To map this to real-world hardware, let's pretend the Proxmox miniPC is a literal server rack, and inside it, we are installing physical switches, crimping patch cables, and plugging things into ports:

  • Linux Bridge (vmbr / trunk / wan): This is a Physical Switch inside the server. If you have three bridges, you have three separate hardware switch boxes sitting in your rack.

    • VLAN-Aware Bridge: A Managed Switch. It is smart. It understands 802.1Q VLAN tags (10, 3020) and can pass multiple VLANs down a single wire or isolate them on specific ports.

      • Subinterface (enp1s0.20 or vmbr0.10): An Access Port on a switch that is hard-coded to strip the tag off a specific VLAN and hand you clean, untagged traffic.
    • Standard Bridge (Non-VLAN-Aware): A Dumb / Unmanaged Switch. It doesn't understand tags. If tagged traffic enters it, it either drops it or treats it like generic background noise.


The Current Pain Points

The Subinterface & Bridge Cascading: Right now, every time I want to introduce a new VLAN to the virtual environment, I am forced to create a host-level Linux VLAN interface (like trunk.30) and then stack a completely separate Linux Bridge on top of it (like win2k8). This creates an unnecessary layer of clutter.

The Legacy Naming Quirk: The bridge for the 10.0.30.0/24 server network is named win2k8. This should be changed ASAP... running modern Linux containers like Technitium, Uptime Kuma, and Nginx Proxy Manager on a bridge called win2k8 creates unnecessary cognitive load when troubleshooting.


The "Before" Setup: The Dumb Switch Chaos

In the current configuration, the miniPC is running a mountain of separate, cheap unmanaged switches stacked on top of each other, held together by a mess of virtual patch cables.

  1. The WAN Switch (wan): A dedicated unmanaged switch. I ran a cable from the Digi ONT into a special adapter that stripped away everything except VLAN 20 (enp1s0.20), then plugged that clean wire into this switch. The OPNsense WAN port plugged in here.

  2. The Core Switch (trunk): Another separate unmanaged switch. I ran a physical network cable from enp4s0 straight to the TP-Link switch.

  3. The Looping Splitters (trunk.10 and trunk.30): Because the trunk switch was dumb, it couldn't split VLANs natively. So, I virtually plugged two "VLAN splitter boxes" into it.

  4. The Management Switch (proxmox): A fourth physical switch box. I ran a patch cable from the VLAN 10 splitter (trunk.10) into this switch just so the Proxmox host could have its 10.0.10.10 management IP.

  5. The Server Switch (win2k8): A fifth physical switch box. I ran a patch cable from the VLAN 30 splitter (trunk.30) into this switch. Every single one of the containers (Technitium, Uptime Kuma, etc.) and the Windows Server had to plug their cables into this specific box.

Why it was risky: If any of those cascading virtual cables or subinterfaces glitched, the whole stack collapsed.


The Solution: A Single VLAN-Aware Bridge

Instead of creating distinct bridges for every single broadcast domain, we can leverage Proxmox native VLAN Aware feature. This allows a single Linux Bridge to handle all tagging natively, mimicking how a physical managed switch behaves.

Here is how we can refactor the infrastructure into two clean blocks: a dedicated WAN Bridge and a single VLAN-Aware LAN Bridge.

Current Interface / Bridge New Optimized Component Role / Function
enp1s0.20 + wan vmbr1 (Traditional Bridge) WAN: Slaved directly to enp1s0.20. OPNsense net0 stays here to swallow the raw ISP internet feed.
enp4s0 + trunk vmbr0 (VLAN Aware: Yes) LAN Trunk: Slaved directly to enp4s0. Connects to Port 6 of the physical TP-Link switch.
trunk.10 + proxmox vmbr0.10 (VLAN Interface) Host Management: Gets Proxmox host IP (10.0.10.10/24) and gateway (10.0.10.1).
trunk.30 + win2k8 Deleted No longer needed.

The resulting /etc/network/interfaces file (before / after):

auto lo
iface lo inet loopback

auto enp2s0
iface enp2s0 inet manual
#ETH1

auto enp1s0
iface enp1s0 inet manual
#ETH0

auto enp3s0
iface enp3s0 inet manual
#ETH2

auto enp4s0
iface enp4s0 inet manual
#ETH3

auto enp1s0.20
iface enp1s0.20 inet manual
#ETH0.20

auto trunk
iface trunk inet manual
        bridge-ports enp4s0
        bridge-stp off
        bridge-fd 0
#ETH3

auto wan
iface wan inet manual
        bridge-ports enp1s0.20
        bridge-stp off
        bridge-fd 0
#ETH0.20

auto proxmox
iface proxmox inet static
        address 10.0.10.10/24
        gateway 10.0.10.1
        bridge-ports trunk.10
        bridge-stp off
        bridge-fd 0

auto trunk.10
iface trunk.10 inet manual

auto trunk.30
iface trunk.30 inet manual

auto win2k8
iface win2k8 inet manual
        bridge-ports trunk.30
        bridge-stp off
        bridge-fd 0
#SERVERS

source /etc/network/interfaces.d/*

auto lo
iface lo inet loopback

auto enp1s0
iface enp1s0 inet manual
# ETH0 - Connected to Huawei ONT (DIGI)

iface enp2s0 inet manual
# ETH1 - Unused Lab Port

iface enp3s0 inet manual
# ETH2 - Unused Lab Port

auto enp4s0
iface enp4s0 inet manual
# ETH3 - Trunk to TP-Link Switch

auto enp1s0.20
iface enp1s0.20 inet manual
# ETH0.20

auto vmbr1
iface vmbr1 inet manual
        bridge-ports enp1s0.20
        bridge-stp off
        bridge-fd 0
# WAN - DIGI Fiber

auto vmbr0
iface vmbr0 inet manual
        bridge-ports enp4s0
        bridge-stp off
        bridge-fd 0
        bridge-vlan-aware yes
        bridge-vids 2-4094
# LAN Trunk to Switch

auto vmbr0.10
iface vmbr0.10 inet static
        address 10.0.10.10/24
        gateway 10.0.10.1
# PVE Management Interface (VLAN 10)

source /etc/network/interfaces.d/*


The "After" Setup: The Enterprise Clean-up

We went into the virtual server rack, threw all those tiny, unmanaged desktop switches into the trash, and replaced them with exactly two clean pieces of hardware.

      [ DIGI Fiber ONT ]
               │ (VLAN 20)
       ┌───────▼───────────────────────────────────┐
       │  vmbr1 (Dedicated WAN Switch)             │
       └───────┬───────────────────────────────────┘
               │ (Clean WAN Traffic)
       ┌───────▼───────────────────────────────────┐
       │  OPNsense VM (Router / Firewall)          │
       └───────┬───────────────────────────────────┘
               │ (All LAN Trunk Traffic)
┌──────────────▼────────────────────────────────────────────────────────┐
│ vmbr0 (The Big Smart Managed Switch - VLAN Aware)                     │
├──────────────┬──────────────────┬──────────────────┬──────────────────┤
│ Access Port  │ Access Port      │ Access Port      │ Trunk Port       │
│  (VLAN 10)   │  (VLAN 30)       │  (VLAN 30)       │ (VLANs 2-4094)   │
└──────┬───────┴──────┬───────────┴──────┬───────────┴──────┬───────────┘
       │              │                  │                  │
 [Proxmox Host]   [Win2K8 VM]     [Linux Containers]   [Real-World Switch]
 (10.0.10.10)
1. Switch A (vmbr1 - The Internet Box)

This is a tiny, isolated 2-port unmanaged switch.

  • Port 1: Wired directly to Digi Fiber ONT line (enp1s0.20).

  • Port 2: Wired directly to OPNsense VM's WAN port.

  • Result: Completely isolated internet traffic. Nothing else in the lab can touch this switch.

2. Switch B (vmbr0 - The Enterprise Managed Switch)

This is the game-changer. It is one big, high-end, VLAN-aware managed switch. It natively understands tags, so we don't need separate hardware boxes for different networks anymore. Everything connects directly to this one switch:

    • The Trunk Uplink: We assigned the physical network port enp4s0 to this switch. It acts as a massive trunk pipe, carrying all the VLANs directly down to the real, physical TP-Link switch.

    • The Proxmox Host Management (vmbr0.10): Instead of giving Proxmox a separate switch, we told the host to take its management leg and plug it directly into a virtual port on Switch B pre-configured for VLAN 10.

    • The Servers & Containers (Win2K8, Technitium, etc.): Instead of plugging into a separate win2k8 bridge box, they now plug their virtual cables straight into Switch B. In their settings, we simply set their virtual switch port to VLAN Tag: 30. Switch B handles the isolation internally.

image.png

image.png

image.png

image.png


The OPNsense Case

image.png

image.png

Because we left the VLAN tags completely blank in the Proxmox settings for the OPNsense VM, Proxmox treats both of those network adapters (net0 and net1) as raw, transparent physical wires.

Inside OPNsense, those wires show up as vtnet0 and vtnet1. Because Proxmox isn't touching or restricting the packets, OPNsense can handle them exactly like a physical corporate router would.

Here is exactly how those two adapters are acting:

Adapter 1 (vtnet0) — The Dedicated Internet Pipe

In Proxmox, net0 is plugged directly into the isolated internet switch, Switch A (vmbr1).

  • The Physical Mapping: vmbr1 is tied to enp1s0.20. This means the Proxmox host handles stripping the DIGI VLAN 20 tag off the incoming fiber line before it passes it along.

  • What OPNsense Sees: By the time the internet traffic travels down the virtual wire to vtnet0, it is completely untagged, clean ISP traffic.

  • The Config: Because it's a flat, clean wire, OPNsense doesn't need to build any VLAN subinterfaces on it. It just logs directly into the parent interface using your DIGI credentials via PPPoE (pppoe0 (vtnet0)).

image.png

image.png

Adapter 2 (vtnet1) — The Smart Inside Trunk

This is where the magic happens. In Proxmox, net1 is plugged into the big, smart, VLAN-aware switch, Switch B (vmbr0) with the tag left blank.

  • What OPNsense Sees: vtnet1 is acting as a Physical Trunk Port. Every single packet passing through Home 2 with a VLAN tag (10203040) flows down this single virtual wire completely untouched.

  • The Inside Config: Instead of just assigning an IP to vtnet1, I told the OPNsense operating system to slice that single wire into four virtual interfaces:

    • vtnet1_vlan10 for your Management network.

    • vtnet1_vlan20 for your Access Points.

    • vtnet1_vlan30 for your Server network.

    • vtnet1_vlan40 for your Users.

image.png

image.png


The WLC 9800 Case

The reason there is no VLAN tag on the Cisco 9800-CL inside Proxmox is because the 9800-CL is an enterprise Cisco device that handles the VLAN tagging entirely by itself. To map this to physical gear, let's look at the difference between how Proxmox treats a Blank VLAN box versus a Numbered VLAN box:

When you connect a VM or Container to a VLAN-aware bridge (vmbr0), Proxmox looks at that VLAN Tag field to decide what kind of physical switch port it should mimic:

1. Typing a Number (e.g., Tag: 30) = An "Access Port"

This tells Proxmox: "The virtual machine inside here is a regular device (like a Windows desktop or a lightweight Linux container). It has no idea what a VLAN is." * What Proxmox does: Proxmox acts as the smart switch. When traffic leaves that VM, Proxmox slaps a VLAN 30 sticker on it. When traffic comes back from the network with a VLAN 30 sticker, Proxmox rips the sticker off before handing the clean, untagged packet to the VM.

  • The  Setup: This is how our containers (Technitium, Uptime Kuma) work. They just see a regular flat network, while Proxmox does the tagging behind their backs.

2. Leaving it BLANK = A "Trunk Port"

This tells Proxmox: "The machine inside here is a highly intelligent network device (like a router or a switch). Stand back and get out of its way."

  • What Proxmox does: Proxmox stops touching the packets. It acts as a pure, transparent physical wire. It passes all tags (10203040, etc.) straight through into the VM completely untouched, with their original 802.1Q headers intact.

image.png

Looking at the Cisco WLC screenshot, because the Cisco software is configured as a trunk, it is actively listening for multiple streams of data wrapped in different VLAN stickers. It wants to receive VLAN 10 for management, VLAN 20 for one SSID, and VLAN 40 for another SSID.

If I were to go into Proxmox and force a VLAN Tag: 10 on the 9800-CL's hardware settings, Proxmox would strip away all other VLANs and only deliver untagged VLAN 10 traffic to the Cisco VM. The Cisco 9800-CL would instantly drop the packets because it expects a tagged trunk link, not an access link.

By leaving it blank in Proxmox, I am running a virtual trunk cable from the Proxmox Switch B straight into the Cisco virtual switch interface. The two systems speak the exact same 802.1Q trunk language, allowing the 9800-CL to sort out the VLANs internally just like a physical Catalyst switch would on a real server rack.