A network bridge is a Layer 2 virtual switch that allows virtual machines and containers to share a physical network interface and appear as first-class devices on the local network. On RHEL 9, NetworkManager is the authoritative tool for creating and managing bridges, replacing the deprecated brctl-only workflows of older distributions. Bridges are essential for KVM/QEMU virtual machines that need external network access, and are also used by LXC containers, Open vSwitch integrations, and some Docker configurations. This tutorial walks through creating a production-ready bridge (br0) on RHEL 9 using nmcli.
Prerequisites
- RHEL 9 system with at least one physical (or bonded) Ethernet interface (e.g.,
ens3) - Root or
sudoaccess NetworkManagerrunning (systemctl status NetworkManager)bridge-utilsinstalled for verification (dnf install -y bridge-utils)- Console or out-of-band access recommended — adding a physical NIC to a bridge will briefly drop connectivity
Step 1 — Create the Bridge Interface
Use nmcli to create a new connection of type bridge. This creates a logical bridge device named br0 without yet connecting it to any physical interface.
# Create the bridge connection
sudo nmcli con add type bridge con-name br0 ifname br0
# Disable Spanning Tree Protocol (STP) for simple single-bridge setups
sudo nmcli con mod br0 bridge.stp no
# Verify the connection profile was created
nmcli con show br0
Step 2 — Assign a Static IP Address to the Bridge
Configure the bridge with a static IP so that the host remains reachable after the physical interface is enslaved to the bridge and loses its own IP.
# Set static IP, gateway, and DNS
sudo nmcli con mod br0
ipv4.method manual
ipv4.addresses "192.168.1.50/24"
ipv4.gateway "192.168.1.1"
ipv4.dns "8.8.8.8,8.8.4.4"
ipv6.method ignore
# Confirm the settings
nmcli -f ipv4.addresses,ipv4.gateway,ipv4.dns con show br0
Step 3 — Add a Physical Interface as a Bridge Slave
Attach the physical Ethernet interface (ens3) to the bridge as a slave port. The physical interface will no longer hold an IP address — the bridge will own it.
# First, bring down and delete any existing connection on ens3
sudo nmcli con down ens3
sudo nmcli con del ens3
# Create the slave (port) connection
sudo nmcli con add
type ethernet
slave-type bridge
con-name br0-slave
ifname ens3
master br0
# List all connections to confirm both br0 and br0-slave exist
nmcli con show
Step 4 — Bring Up the Bridge
Activate the bridge connection. NetworkManager will automatically bring up the slave connection as well.
# Bring up the bridge (this may momentarily drop SSH if connected over ens3)
sudo nmcli con up br0
# Confirm the bridge is up and has the expected IP
ip addr show br0
# Example expected output:
# br0:
# inet 192.168.1.50/24 brd 192.168.1.255 scope global br0
Step 5 — Verify the Bridge Configuration
Use ip link and brctl to confirm bridge membership and forwarding state.
# Show all interfaces and their states
ip link show
# Show bridge details and connected ports
brctl show
# Example brctl output:
# bridge name bridge id STP interfaces
# br0 8000.52540012ab34 no ens3
# Show the bridge forwarding table (MAC address table)
brctl showmacs br0
# Test connectivity from the host
ping -c 4 192.168.1.1
Step 6 — Connect a KVM Virtual Machine to the Bridge
When creating a KVM VM with virt-install, specify the bridge as the network source so the VM receives an IP on the same subnet as physical hosts.
# Install libvirt and KVM tools if not already present
sudo dnf install -y qemu-kvm libvirt virt-install
sudo systemctl enable --now libvirtd
# Create a VM attached to br0
sudo virt-install
--name testvm
--ram 2048
--vcpus 2
--disk size=20
--os-variant rhel9.0
--network bridge=br0
--cdrom /path/to/rhel9.iso
# For Docker, note that Docker creates its own docker0 bridge by default.
# To connect Docker containers to br0 instead, use a macvlan network:
# docker network create -d macvlan
# --subnet=192.168.1.0/24
# --gateway=192.168.1.1
# -o parent=br0 macvlan_br0
Conclusion
You have created a fully functional NetworkManager-managed bridge (br0) on RHEL 9, assigned it a static IP, enslaved a physical interface, verified the configuration with brctl and ip link, and connected a KVM virtual machine to it. Bridges created with nmcli are persistent across reboots and fully managed by NetworkManager, making them more reliable than manually editing ifcfg files or calling brctl directly. For Docker workloads that need direct Layer 2 access to the physical network, macvlan networks over br0 are the recommended approach.
Next steps: How to Set Up a DHCP Server with ISC DHCP on RHEL 9, How to Configure Bond and Team Interfaces on RHEL 9, and How to Configure DRBD for High-Availability Storage on RHEL 9.