KVM bridge networking
A Linux bridge connects KVM instances to your provider’s network. Create the bridge on each hypervisor first, then enter its name in the VirtConsole subnet. This guide covers an ordinary Ethernet network with a gateway on the same subnet, including an untagged switch port or a provider VLAN.
VirtConsole attaches instance interfaces to an existing host bridge. Adding a Bridged subnet in the panel does not configure the host’s physical interface, IP address or default route.
Check that bridged networking fits your provider
Section titled “Check that bridged networking fits your provider”| What your provider supplies | Use |
|---|---|
| Addresses on the same Ethernet network as an upstream gateway, with guest MAC addresses allowed | A Linux bridge, as described here. |
| A tagged VLAN carrying that network | A VLAN interface connected to a bridge. See Tagged VLANs. |
| Additional IPs tied to provider-issued virtual MAC addresses | The provider’s MAC for each guest IP. See Hetzner or OVH. |
| A subnet routed to the host’s main IP, with no direct guest access to the upstream gateway | A routed configuration. See Networking modes and the provider’s routing instructions. |
A bridge exposes guest MAC addresses to the upstream switch. A provider that permits only the host MAC must explicitly support additional virtual MACs, or you need a routed design. Giving the bridge the host’s MAC does not make guest traffic use that MAC.
The examples below are for KVM hosts running the VirtConsole agent. Manage a Proxmox node’s bridges through Proxmox networking, not these agent-host instructions.
How the interfaces fit together
Section titled “How the interfaces fit together”Provider switch and gateway | eno1 Physical uplink; no host IP after conversion | br0 Linux bridge; carries the host IP and default route / \ guest NIC guest NIC Each instance has its own IP and MACFor a shared management and guest uplink, move the host’s addresses, routes and DNS configuration from the physical interface to the bridge. The physical interface becomes a bridge port. Do not leave the same address or default route configured on both.
If guests use a separate uplink or VLAN, leave management networking in place. The guest bridge can have no host IP address and no default route; guests still use the provider’s gateway. Do not move management onto a guest-only bridge.
Before changing the host network
Section titled “Before changing the host network”Run configuration commands as root on the hypervisor. Start by recording the current setup:
ip -br linkip -br addressip -4 route showip -6 route showbridge link showcat /etc/resolv.confRecord the uplink name, host IPv4 and IPv6 addresses with prefixes, gateways, DNS resolvers, MAC address and MTU. With several default routes, identify the actual management uplink rather than taking the first line. Check the provider’s network allocation as well as the running configuration.
Use the network manager already controlling the interface:
| Existing configuration | Section |
|---|---|
Debian with /etc/network/interfaces and ifupdown |
Debian |
Ubuntu with /etc/netplan/*.yaml |
Ubuntu |
| RHEL, Rocky or AlmaLinux with NetworkManager profiles | RHEL |
An OS name alone does not identify the network manager. If the host uses native systemd-networkd, a bond, policy routing or another custom setup, adapt that existing configuration instead of enabling a second manager. If cloud-init or your provider rewrites networking at boot, update its authoritative configuration or follow its documented procedure to take over network management.
Example values
Section titled “Example values”All IP addresses below are documentation examples. Replace them with your allocation before applying anything.
| Setting | Example |
|---|---|
| Physical uplink | eno1 |
| New bridge | br0 |
| Host IPv4 | 203.0.113.10/24 |
| Upstream IPv4 gateway | 203.0.113.1 |
| Host MAC | 02:00:00:00:00:10 |
| DNS | 1.1.1.1, 9.9.9.9, or your existing resolvers |
| Optional host IPv6 | 2001:db8:100::10/64 |
| Optional upstream IPv6 gateway | 2001:db8:100::1 |
Keep your real prefix length; do not change it to /24 just to match the example. Gateways outside the assigned prefix, /32 host addresses and provider-specific IPv6 routing need explicit routes; use the relevant provider guide. Do not invent a gateway.
Choose an unused bridge name. virbr0 is commonly used by libvirt’s default NAT network; that network is not your provider-facing bridge. An existing working bridge can be reused after checking its uplink and addressing.
Debian with ifupdown
Section titled “Debian with ifupdown”This example uses the bridge extensions provided by bridge-utils. It does not replace an existing ifupdown2 or systemd-networkd setup.
Back up the configuration and make sure the bridge support is installed:
cp -a /etc/network /root/network-before-br0apt-get install bridge-utilsEdit the existing uplink configuration in /etc/network/interfaces or its included file. Remove the old uplink’s static or DHCP stanza and replace it with the bridge configuration below. The bridge scripts bring up eno1; do not retain a separate address-bearing stanza for that port. Preserve the loopback definition, includes and unrelated interfaces, checking that an included file does not still configure the old uplink.
auto loiface lo inet loopback
auto br0iface br0 inet static address 203.0.113.10/24 gateway 203.0.113.1 bridge_ports eno1 bridge_hw eno1 bridge_stp off bridge_fd 0 dns-nameservers 1.1.1.1 9.9.9.9bridge_hw eno1 keeps the host-facing bridge MAC equal to the uplink MAC. STP is disabled for this single-uplink topology. Do not add a second physical uplink unless you have designed the bonding or loop-prevention arrangement.
The dns-nameservers option requires resolver integration such as resolvconf. Preserve the host’s existing resolver configuration if it is managed separately; verify name resolution after the change.
For an existing static IPv6 allocation, add this stanza and remove the corresponding address and gateway from the physical port’s old configuration:
iface br0 inet6 static address 2001:db8:100::10/64 gateway 2001:db8:100::1Review the saved file with ifquery br0. Apply the change from the console during the maintenance window by rebooting the host, then perform the verification checks. A planned reboot avoids leaving addresses from the old live configuration on the physical port. Do not use a reboot as a substitute for checking the saved configuration first.
Rollback: from the console, restore the original interface files from /root/network-before-br0, remove only the new bridge stanza or file you added, and reboot into the original configuration. Do not delete unrelated interface files.
Ubuntu with Netplan
Section titled “Ubuntu with Netplan”Back up the directory before editing:
cp -a /etc/netplan /root/netplan-before-br0Edit the YAML file that already defines the uplink. Netplan merges its configuration files, so adding a new file does not automatically remove an address or DHCP setting from an older one. Preserve unrelated interfaces and routes.
The following example uses systemd-networkd and static IPv4. It disables automatic host IPv6 configuration; if the host uses static IPv6, DHCPv6 or router advertisements, carry that configuration over to br0 before applying it.
network: version: 2 renderer: networkd ethernets: eno1: dhcp4: false dhcp6: false accept-ra: false bridges: br0: interfaces: [eno1] macaddress: 02:00:00:00:00:10 dhcp4: false dhcp6: false accept-ra: false addresses: - 203.0.113.10/24 routes: - to: default via: 203.0.113.1 nameservers: addresses: [1.1.1.1, 9.9.9.9] parameters: stp: false forward-delay: 0Replace macaddress with the actual uplink MAC from ip link show eno1. For static IPv6, add 2001:db8:100::10/64 to the bridge’s addresses list and a second default route with via: 2001:db8:100::1. Use your actual IPv6 gateway; a link-local gateway is scoped to br0. If the provider supplies the host address through DHCP or SLAAC, configure those methods on the bridge instead of copying this static example. Preserve any DHCP client-ID requirements.
Validate and try the configuration:
netplan generatenetplan try --timeout 120During the trial, verify host connectivity and open a second SSH connection. Confirm the trial only when those checks pass. A confirmed trial applies the configuration; it is already saved for boot.
Rollback: use the console to restore the original YAML files from /root/netplan-before-br0 and remove only new files introduced for this change. Run netplan generate, then netplan apply. Recheck addressing and routes. If an unused bridge remains, verify that the original management network is restored and the saved configuration is correct before rebooting.
RHEL, Rocky and AlmaLinux with NetworkManager
Section titled “RHEL, Rocky and AlmaLinux with NetworkManager”Use NetworkManager profiles for RHEL 9 and 10. Do not add legacy network-scripts files alongside them. Record the connection profile name, which can differ from the device name:
nmcli -f NAME,UUID,TYPE,DEVICE connection show --activenmcli connection show "CURRENT_UPLINK_PROFILE"cp -a /etc/NetworkManager/system-connections /root/nm-connections-before-br0Replace CURRENT_UPLINK_PROFILE below with that exact profile name. Keep the original profile as a rollback option. Create the bridge and port without activating them:
nmcli connection add type bridge con-name br0 ifname br0 connection.autoconnect nonmcli connection modify br0 \ ipv4.method manual ipv4.addresses 203.0.113.10/24 \ ipv4.gateway 203.0.113.1 ipv4.dns "1.1.1.1 9.9.9.9" \ ipv6.method disabled \ bridge.mac-address 02:00:00:00:00:10 bridge.stp nonmcli connection add type ethernet con-name br0-port ifname eno1 \ port-type bridge controller br0 connection.autoconnect nonmcli connection modify br0 connection.autoconnect-ports 1The port-type, controller and connection.autoconnect-ports names require RHEL 9.4 or later. On older RHEL 9 installations, use slave-type, master and connection.autoconnect-slaves, respectively.
This example disables host IPv6 on the bridge. If the host currently has static IPv6, configure it before activation:
nmcli connection modify br0 \ ipv6.method manual ipv6.addresses "2001:db8:100::10/64" \ ipv6.gateway "2001:db8:100::1"For DHCPv6 or SLAAC, retain the existing host’s IPv6 method and DNS settings on the bridge instead. Carry over additional routes, MTU and any interface-based firewall-zone assignment deliberately; a newly created profile does not inherit them.
From the console, disable automatic activation of the original profile and activate the bridge port. Activating the port also activates its bridge:
nmcli connection modify "CURRENT_UPLINK_PROFILE" connection.autoconnect nonmcli connection up br0-portThis replaces the old active uplink profile and can interrupt SSH. After the verification checks pass, enable the new profiles at boot:
nmcli connection modify br0 connection.autoconnect yesnmcli connection modify br0-port connection.autoconnect yesRollback: from the console, bring down br0-port and br0, disable their autoconnect, restore autoconnect on CURRENT_UPLINK_PROFILE, and activate the original profile. Keep the backup until a planned reboot has verified persistence.
Tagged VLANs
Section titled “Tagged VLANs”An untagged access port needs no VLAN interface on the host. If the provider explicitly delivers a tagged VLAN, put its VLAN interface into the bridge, not the raw uplink. For VLAN 100:
Provider trunk -- eno1 -- eno1.100 -- br100 -- instance interfacesFor example, add this to an existing Netplan configuration for a guest-only VLAN. Keep all existing management settings under eno1 unchanged. The bridge has no host address and creates no additional default route:
network: version: 2 renderer: networkd # Retain the existing ethernets: eno1: management configuration here. vlans: eno1.100: id: 100 link: eno1 dhcp4: false dhcp6: false accept-ra: false bridges: br100: interfaces: [eno1.100] dhcp4: false dhcp6: false accept-ra: false parameters: stp: false forward-delay: 0This is a fragment to merge into the existing configuration, not a replacement file: eno1 must already be defined. Use the same validation and console-backed trial as above. With ifupdown or NetworkManager, create the equivalent persistent VLAN device and make it the bridge port. Do not enslave the raw trunk to this guest-only bridge or tag traffic twice. Check the VLAN ID and permitted MTU with the provider.
Instances attached to br100 see an ordinary untagged network; the host VLAN interface adds and removes the tag. Enter br100 as the subnet’s bridge in VirtConsole. If management also uses this VLAN, move that VLAN’s host addressing onto the bridge using the shared-uplink pattern instead.
Add the subnet in VirtConsole
Section titled “Add the subnet in VirtConsole”After the host bridge works, go to Networking > Subnets > Add subnet. See Subnets and IP addresses for the full form.
| Field | For the untagged example |
|---|---|
| Networking Mode | Bridged |
| Bridge | br0, exactly as it exists on the host |
| Protocol | IPv4; add IPv6 as a separate subnet if supplied |
| Netmask | The guest allocation’s mask, for example 255.255.255.0 |
| Gateway | The provider’s gateway for that guest allocation, for example 203.0.113.1 |
| DNS Resolver 1 / 2 | Resolvers reachable from the instances |
| Hypervisors | Only hosts where this bridge exists and reaches this allocation |
Use the provider’s guest allocation, which may differ from the management subnet. Do not use the host IP as the guest gateway unless you are deliberately configuring a routed network.
Generate only addresses assigned to you. Exclude the host address, gateway and any reserved addresses; exclude network and broadcast addresses for an ordinary IPv4 subnet. If the provider requires a virtual MAC, enter it on each corresponding IP. Do not assign every guest the physical host MAC.
On multiple hypervisors, the same bridge name is not enough: each bridge must reach the correct upstream network or VLAN. Prepare it on every selected host before enabling placement there.
Verify the host and a test instance
Section titled “Verify the host and a test instance”Check the host before deploying a guest:
ip -br addressip -4 route showip -6 route showip link show master br0bridge link showping -c 3 203.0.113.1getent hosts docs.virtconsole.comSubstitute the real bridge and gateway. Confirm that:
- The host address and intended default route use
br0, with no duplicate address or default route left oneno1. eno1is a port ofbr0and has carrier. For a tagged VLAN, the port is the VLAN interface.- DNS works, a new SSH connection works, and the management server can still reach the agent on port 2443.
- The host’s IPv6 address and default route are present if IPv6 was configured. An ICMP-blocking gateway may not answer ping, so also test actual permitted traffic.
Deploy one test instance from the new subnet. Confirm its assigned IP, prefix, gateway and MAC inside the guest; test its gateway, DNS and outbound connectivity, then inbound connectivity from another machine. Inbound tests must match the instance’s security-group rules.
For an instance already running, virsh domiflist INSTANCE_DOMAIN shows the host bridge used by its NIC. virsh net-list lists libvirt-managed networks, not every Linux bridge, so an empty network list does not mean br0 is missing.
At the end of the maintenance window, verify the saved configuration survives a planned host reboot before putting production instances on it.
Troubleshooting
Section titled “Troubleshooting”| Symptom | Check |
|---|---|
| Host becomes unreachable | Console first: wrong prefix/gateway, duplicate configuration, changed host MAC, wrong uplink, or missing management VLAN. Restore the saved configuration if necessary. |
| Host works but guests cannot reach the gateway | Provider MAC restrictions, guest IP/MAC pairing, upstream VLAN, bridge port membership and guest prefix/gateway. |
| Bridge exists but an instance cannot start | Exact bridge name in the VirtConsole subnet, selected hypervisor, link state and the agent’s error message. |
| IPv4 works but IPv6 fails | IPv6 address and route moved to the bridge, correct gateway scope, provider routing/MAC requirements, and neighbour-discovery filtering. IPv4 success does not validate IPv6. |
| Small packets work but larger transfers stall | MTU across guest, bridge, VLAN/bond and upstream path; check firewall handling of path-MTU discovery. |
| Configuration breaks after reboot | Duplicate network-manager definitions, cloud-init regeneration, old NetworkManager autoconnect profiles, or a bridge-helper service recreating the same bridge. |
Do not flush the host firewall or disable instance security groups to make a bridge work. Inspect the applicable forwarding and filtering rules. See CSF firewall and Security groups.
Existing bridge-helper installations
Section titled “Existing bridge-helper installations”Older versions of this guide used hypervisor:bridge with a vbridge-*.service unit. Do not run that helper or its stop action against a bridge now managed by the OS network configuration. The stop action tears the bridge down.
When converting an existing helper installation, schedule a console-backed maintenance window, record the service and live network state, and prepare the persistent OS configuration first. Disable the old unit for the next boot without stopping the live bridge, then activate the new configuration during that window. Keep a console rollback plan. One bridge should have one configuration owner.

