This is an old revision of the document!
classic-bridging
This tutorial is for Debian users who want to create network bridges, or virtual switches, on production hosts. By production hosts, I mean something that’s designed to run virtual appliances (VMs, containers, etc.).
This tutorial assumes you have access to PTR records and/or have a block of external IPs.
In this tutorial, I’ll break down two differing setups I use. To be clear, the tutorial is about much more than bridging — it’s just that the bridges are the most important part because they route incoming traffic to the appliances.
The first setup is at Brown Rice (co-located server). The second setup is at Pebble Host (dedicated host — actual hardware provisioned on your behalf).
Here are the technical specifications for each host:
I prefer to use virsh + qemu/kvm on the physical (bare metal) host.
For my machine in Taos, I run the Debian host OS on a separate SSD on a dedicated SATA port that’s not part of the SAS back-plane. At Pebble, I don’t have this luxury; everything runs on the boot volume. This limitation fits the use-case, however, as I only have Pebble setup to run 5-7 virtual appliances, while the server co-located at Brown Rice has upwards of 30 virtual appliances.
Each location has a different set of requirements due to how they broadcast IP/prefixes, whether they filter traffic or not, and how they allocate IPs.
Brown Rice treats the prefixes/blocks they provide as public and, according to that logic, everything is open and exposed. The onus of responsibility rests exclusively on the client.
Pebble Host, on the other hand, serves over 50K clients. MAC address filtering becomes practically necessary due to potential conflicts within vendor OUIs (especially virsh). Filtering is also done for security, compliance, accountability, etc.
The SuperMicro has a built-in 10Gbps NIC, with 4 ports and 1 IPMI port.
Before we start tinkering with the operating system on the host, we need to establish A, AAAA, SPF, DMARC, and PTR records for the host. After that, we will setup IPMI access in the SuperMicro’s BIOS.
At Brown Rice, my machine has four cables plugged in, allocated as follows:
To setup IPMI, boot the production host and enter the BIOS (American Megatrends on this vintage SuperMicro). Configure:
After configuring the network interface and hardening (disable ssh, iKVM, Virtual Media, SNMP unless needed), add source IP whitelist rules (DROP everything else at the end).
Use a small VPS + SOCKS proxy (e.g. ssh -D 8080 to VPS + FoxyProxy) to appear from an approved IP when accessing the firewalled IPMI panel.
NOTE: Self-signed TLS certificate is acceptable given the source IP restrictions and hardening.
Your primary DNS records (A/AAAA/SPF/DMARC) and PTR (IPv4 via panel, IPv6 via email request) should already be set up.
Now install Debian without NetworkManager (core utilities only). Remove it if already present:
sudo apt remove --purge NetworkManager
Configure primary interface in /etc/network/interfaces:
auto enp1s0f0
iface enp1s0f0 inet static
address 8.28.86.100
netmask 255.255.255.0
gateway 8.28.86.1
nameservers 8.8.8.8
sudo systemctl restart networking ping4 google.com
Raise dedicated bridge interfaces (no address):
# bridge ipv4 auto enp1s0f1 iface enp1s0f1 inet manual # bridge ipv6 auto enp2s0f0 iface enp2s0f0 inet6 manual
Install bridge-utils and create bridge:
sudo apt install bridge-utils brctl addbr br0
Configure bridge (IPv6 only on bridge, since IPv4 host address already exists on primary interface):
auto br0
iface br0 inet6 static
address 2602:fb41:0:11::2/64
gateway 2602:fb41:0:11::1
bridge_ports enp1s0f1 enp2s0f0
accept_ra 2
bridge_stp off
bridge_fd 0
sudo systemctl restart networking ping6 google.com ping4 google.com # double-check IPv4 still works
(Continue with UFW firewall setup, virt-install / preseed for VMs, connecting them to br0, etc. — as described in the original article.)
(One NIC — enp4s0 — handles both IPv4 and IPv6.)
Pebble requires VMAC (specific virtual MAC addresses) for VMs to pass their traffic filtering.
Create bridge with same MAC as physical interface:
auto br0
iface br0 inet static
address 45.143.197.68
netmask 255.255.255.192
gateway 45.143.197.65
bridge_ports enp4s0
bridge_stp off
bridge_fd 0
hwaddress ether xx:xx:xx:xx:xx:xx # <-- same MAC as enp4s0
iface br0 inet6 static
address 2a10:e780:11:15::4/64
gateway 2a10:e780:11:15::1
Additional static routes may be needed for routed blocks.
VMs connected to br0 must use an approved VMAC in their config (virt-install / libvirt XML).
Both setups rely on classic /etc/network/interfaces + bridge-utils (not NetworkManager, not systemd-networkd bridges in this case).
Bridges act as virtual switches, passing traffic directly to VMs with public IPs.
Security differs greatly: open exposure at Brown Rice vs. MAC filtering + restrictions at Pebble.
Use preseed + virt-install scripts for fast, repeatable VM deployment.
If you run into issues or want to discuss variations, feel free to reach out on Matrix:
— oemb1905 2025/11/09 03:07