How to Configure a Network Bridge on Fedora

A network bridge on Fedora lets you connect virtual machines or containers to your physical network as if they were directly attached, configured through NetworkManager.

You just finished setting up a KVM virtual machine and realized it is stuck in an isolated NAT network. You want the VM to appear as a regular device on your local LAN, complete with its own IP address from your router. You need a network bridge to stitch your physical Ethernet cable to the virtual machine interface.

What a network bridge actually does

A network bridge operates at Layer 2 of the OSI model. It forwards Ethernet frames between interfaces without routing them. Think of it as a transparent patch cable that splits one physical port into multiple virtual ports. Your physical interface stops handling IP traffic directly. The bridge interface takes over the IP address. Every packet that enters the bridge gets flooded to all attached ports until the switch learns which MAC address lives where.

NetworkManager handles the bookkeeping so you do not have to manage raw ip link commands manually. Fedora ships with NetworkManager configured to manage bridges out of the box. You create connection profiles, not persistent kernel objects. When the system boots, NetworkManager reads the profiles and builds the bridge in the correct order. This approach survives reboots, interface renames, and kernel updates without breaking.

Run nmcli connection show before you start. You need to know your current wired connection name and your physical interface name. NetworkManager tracks connections by profile name, not by hardware address. Keep that distinction clear.

Building the bridge with NetworkManager

Here is how to create the bridge device and assign it a persistent connection name.

# Create the bridge device and assign it a persistent connection name
sudo nmcli connection add type bridge ifname br0 con-name br0
# Set the bridge to start automatically on boot
sudo nmcli connection modify br0 connection.autoconnect yes
# Assign a static IP address to the bridge instead of the physical cable
sudo nmcli connection modify br0 ipv4.method manual ipv4.addresses 192.168.1.50/24 ipv4.gateway 192.168.1.1 ipv4.dns 1.1.1.1

NetworkManager stores these profiles in /etc/NetworkManager/system-connections/. You never edit those files directly. Use nmcli or nmtui to modify them. Manual edits drift and break on package updates.

Here is how to attach your physical interface as a bridge slave.

# Replace enp3s0 with your actual interface name from ip link
sudo nmcli connection add type bridge-slave ifname enp3s0 master br0
# Tell NetworkManager to bring the slave up automatically
sudo nmcli connection modify enp3s0 connection.autoconnect yes
# Disable DHCP on the slave since the bridge now handles IP assignment
sudo nmcli connection modify enp3s0 ipv4.method disabled ipv6.method disabled

Here is how to bring the bridge online and detach the old wired profile.

# Deactivate the original wired connection to prevent IP conflicts
sudo nmcli connection down "Wired connection 1"
# Activate the bridge profile, which also brings up the slave
sudo nmcli connection up br0

NetworkManager will print Connection successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/2). If it hangs or prints an error, check the next section. Bring the bridge up before you attach VMs. Half the time the symptom is gone after a clean activation cycle.

Verify the bridge is forwarding

Here is how to confirm the kernel sees the bridge and the slave interface.

# Check the bridge state and attached ports
ip link show br0
# List all bridge members and their forwarding state
bridge link show
# Verify the bridge has the IP address you assigned
ip addr show br0

You should see state UP on br0 and state UP on the slave. The bridge link show output will list the slave with state forwarding. If the slave shows state blocking, Spanning Tree Protocol is still calculating the topology. Wait ten seconds and run the command again.

Here is how to check that NetworkManager recognizes the bridge as the active connection.

# Show the active connection profile and its device mapping
nmcli connection show --active
# Verify the bridge is handling DHCP or static routing correctly
ip route show dev br0

Run journalctl -xeu NetworkManager if the activation failed. Read the actual error before guessing. NetworkManager logs are verbose and usually point directly to a missing dependency or a conflicting profile.

Common pitfalls and what the error looks like

The nmcli connection up br0 command will refuse to proceed and print Error: Connection activation failed: Device not managed by NetworkManager. This happens when NetworkManager.conf contains unmanaged-devices=interface-name:br0. Remove the bridge from the unmanaged list or delete the line entirely. NetworkManager must own the device to configure it.

If you see [FAILED] Failed to start NetworkManager.service during boot, your network configuration probably references a missing interface name. Fedora renames interfaces on hardware changes. Check /var/log/messages for the new name and update the slave profile.

Firewall denials are the most common post-bridge issue. firewalld assigns zones to interfaces, not to bridges by default. If you do not assign a zone, the bridge inherits the default zone, which often drops forwarded traffic. You will see dropped packets in journalctl -t firewalld with REJECT or DROP markers.

Here is how to assign the bridge to a trusted zone and reload the firewall.

# Permanently assign the bridge to the trusted zone
sudo firewall-cmd --permanent --zone=trusted --add-interface=br0
# Apply the change to the running firewall immediately
sudo firewall-cmd --reload

Always run firewall-cmd --reload after every rule change. Otherwise the runtime config and the persistent config diverge. Future debugging sessions become impossible.

Kernel netfilter hooks sometimes fail to inspect bridged traffic. Fedora loads bridge and br_netfilter automatically in most cases. If you run custom iptables or nftables rules and they silently ignore bridged packets, the br_netfilter module is not loaded. You will see no error, just missing traffic.

Here is how to load the module and persist it across reboots.

# Load the bridge netfilter module into the running kernel
sudo modprobe br_netfilter
# Create a drop-in file so systemd loads it on every boot
echo 'br_netfilter' | sudo tee /etc/modules-load.d/br_netfilter.conf

SELinux denials occasionally block libvirt from attaching to the bridge. Check journalctl -t setroubleshoot for a one-line summary. Do not disable SELinux. Fix the context or add a policy module. Trust the package manager. Manual file edits drift, snapshots stay.

When to use a bridge versus alternatives

Use a network bridge when you want virtual machines to appear as independent devices on your physical LAN. Use NAT networking when you only need outbound internet access for VMs and do not care about inbound routing. Use macvlan when you want to assign multiple MAC addresses to a single physical interface without a bridge overhead. Use a routed setup when you are separating VM traffic into a completely different subnet with explicit firewall rules. Stay on the default NAT if you are running a single development VM and only need to reach the internet.

Where to go next