Linux server connected through Ethernet cables to a network switch in a lab
Networking Tutorials
William  

Build a Linux Bridge Safely With Ip or NetworkManager

Create a Linux network bridge with ip when you need precise, temporary kernel state. Use NetworkManager when it owns the host's persistent configuration. In both cases, the bridge gets the IP address, default gateway, and DNS settings. The physical interface becomes a bridge port, and you must verify each state change before risking a remote connection.

A bridge joins Layer 2 networks. The host's Layer 3 settings belong on that bridge, not on the physical port beneath it. Put another way, the port carries frames; the bridge owns the host's identity.

What is the correct Linux bridge design before you change anything?

Server network interfaces converging into one transparent logical bridge connection

Build the topology around one bridge device and one or more ports.

host IP, routes, DNS
 |
 br0 Layer 2 bridge
 / \
 enp1s0 tap0 physical or virtual ports

The physical interface, such as enp1s0, becomes a port of br0. It should not keep the host's IP address, default route, or DNS configuration. If it does, the host may appear to work while traffic takes an inconsistent path.

That mistake is common because people treat the bridge like an extra interface. It is not. The bridge is the interface your host uses, while the enslaved device is only a path into the Layer 2 network.

A virtual machine or container can also attach to the bridge. For KVM, the guest's virtual Ethernet device becomes another bridge port. The guest then gets its own address through the same network, unless you deliberately add routing or filtering.

DeviceJobHost IP and routes
br0Layer 2 bridge and host interfaceYes
enp1s0Physical bridge portNo
tap0 or vnet0Virtual bridge portNo
Guest interfaceGuest's own Layer 3 endpointConfigured inside the guest

A bridge does not create a new subnet. It extends an existing Layer 2 segment. If you need separate networks, use routing or VLANs instead. The network segmentation guide covers that design.

How do you identify the real interface names and existing connections?

Run inspection commands before changing anything. Do not assume the uplink is called eth0.

ip -br link
ip -br addr
ip route
ip -br neigh
resolvectl status
nmcli device status
nmcli connection show

Here is what each command tells you:

  • ip -br link shows short interface names and their link state.
  • ip -br addr shows addresses already assigned to each interface.
  • ip route shows the default route and connected networks.
  • ip -br neigh shows known Layer 2 neighbors.
  • resolvectl status shows which resolver is active, if systemd-resolved is running.
  • nmcli device status shows which devices NetworkManager controls.
  • nmcli connection show lists saved NetworkManager profiles.

Record the current address, gateway, DNS servers, and profile name before you touch the port.

ip addr show dev <physical-interface>
ip route show
nmcli -f NAME,UUID,TYPE,DEVICE connection show
nmcli -f connection.id,connection.interface-name,connection.master,connection.slave-type connection show

The interface name may be enp1s0, ens18, eno1, or something else. Predictable names are based on hardware details, not on what a tutorial happened to use. Check the output and use the name that exists on your machine.

You also need to know who controls networking. If NetworkManager owns the interface, changing it with ip changes the live kernel state but not necessarily the saved profile. NetworkManager may restore the old state during a reconnect or reboot.

nmcli -f GENERAL.STATE,GENERAL.CONNECTION device show <physical-interface>
systemctl is-active NetworkManager
systemctl is-active systemd-resolved
readlink -f /etc/resolv.conf

If the physical device already belongs to a bridge, bond, team, or virtual switch, stop here and map that topology first. Adding another owner produces the sort of configuration that looks reasonable until the next link flap.

How do you create a Linux network bridge with ip and NetworkManager?

Administrator configuring a Linux server network bridge beside connected Ethernet hardware

Choose one owner for the configuration. Use the iproute2 workflow for immediate kernel changes. Use NetworkManager for a saved profile that should return after reboot.

Do not mix both workflows casually. NetworkManager can remove or replace state that you created by hand.

Create the bridge with iproute2

The following sequence creates a live bridge. Replace the placeholders with values from your inspection.

IFACE=<physical-interface>

sudo ip link add name br0 type bridge
sudo ip link set dev "$IFACE" master br0
sudo ip link set dev "$IFACE" up
sudo ip link set dev br0 up

ip -br link
bridge link show

ip link add creates the kernel bridge. ip link set ... master br0 attaches the physical interface as a port. The final two commands bring both devices up.

Check the result before assigning the host address.

ip link show dev br0
ip link show dev "$IFACE"
bridge link show dev "$IFACE"

You should see br0 in the master field for the physical device. If the physical interface still owns the host address, move it before testing connectivity.

sudo ip addr flush dev "$IFACE"
sudo ip addr add <host-cidr> dev br0
sudo ip route replace default via <gateway-ip> dev br0

ip -br addr show dev br0
ip route show

ip addr flush removes every address from the physical port. That includes IPv4 and IPv6 addresses, so do not run it blindly on a remote server. If IPv6 is in use, move the required IPv6 address and route to the bridge instead of deleting them.

The bridge now has the host's Layer 3 configuration. The physical interface carries frames but has no host identity.

The kernel bridge created this way is temporary. It disappears after a reboot unless another manager recreates it. That is useful for testing and inconvenient for production, which is why persistent hosts usually need NetworkManager or another service.

Create the bridge with NetworkManager

NetworkManager stores the bridge and port as connection profiles. This is the right choice when NetworkManager already controls the host.

First identify the old profile and the physical device.

nmcli device status
nmcli connection show

Then create a bridge profile with the host's IPv4 settings.

IFACE=<physical-interface>
HOST_CIDR=<host-cidr>
GATEWAY=<gateway-ip>
DNS=<dns-ip>

sudo nmcli connection add type bridge \
 ifname br0 \
 con-name br0 \
 ipv4.method manual \
 ipv4.addresses "$HOST_CIDR" \
 ipv4.gateway "$GATEWAY" \
 ipv4.dns "$DNS" \
 ipv6.method auto

This creates the bridge profile. NetworkManager owns the address, gateway, and DNS settings because they are attached to br0.

Now add the physical port profile.

sudo nmcli connection add type ethernet \
 ifname "$IFACE" \
 con-name br0-port \
 master br0 \
 slave-type bridge \
 ipv4.method disabled \
 ipv6.method disabled

The port profile has no host address or route. If the host needs IPv6, configure it on br0 instead of disabling it here.

Activate the bridge and inspect the result.

sudo nmcli connection up br0
sudo nmcli connection up br0-port

nmcli device status
nmcli connection show --active
ip -br addr
ip route
bridge link show

NetworkManager may activate the port as part of activating the bridge. Running both commands makes the intended order clear and gives you an error at the point where activation fails.

Read that error. Do not keep repeating nmcli connection up while ignoring it. A profile conflict, unmanaged device, missing address, or failed carrier state needs a different fix.

NetworkManager's connection and device settings document the profile properties used here.

How do you assign an IP address, gateway, and DNS to an iproute2 bridge?

Assign the host address and default route to br0.

sudo ip addr add <host-cidr> dev br0
sudo ip route replace default via <gateway-ip> dev br0

ip -br addr show dev br0
ip route get <gateway-ip>
ip route show default

The address uses CIDR notation, such as the value you recorded from the old interface. Do not invent a new subnet because the bridge was created. A bridge normally belongs to the same network as the physical interface it replaced.

The route lookup shows which device the kernel will use for the gateway. It must resolve through br0, not the enslaved interface.

DNS is separate from the bridge itself. ip can assign addresses and routes, but it does not manage resolver configuration.

If systemd-resolved is active, assign DNS to the bridge for the running system.

sudo resolvectl dns br0 <dns-ip>
sudo resolvectl domain br0 ~.
resolvectl status br0

The ~. route tells the resolver to use this link for general DNS queries. Whether that setting survives a restart depends on how your system manages resolver state. A command that works until the next reboot is not persistent configuration.

Check /etc/resolv.conf before editing it.

readlink -f /etc/resolv.conf
cat /etc/resolv.conf

If it points to a resolver-managed file, do not overwrite it with a hand-written file. Configure the service that owns it. If NetworkManager owns DNS, use ipv4.dns and the related settings on the bridge profile instead.

How do you move an existing NetworkManager connection onto the bridge safely?

Ethernet cable being carefully moved between server interface ports and network switch

Do not create a second profile while the old profile still owns the physical interface's address and gateway. First identify the current profile.

nmcli -f NAME,UUID,TYPE,DEVICE connection show
nmcli -f ipv4.method,ipv4.addresses,ipv4.gateway,ipv4.dns,ipv6.method connection show "<old-profile>"

You have two choices. Convert the existing profile into a bridge port, or create a new port profile and disable the old one. Converting the existing profile usually leaves fewer competing profiles behind.

sudo nmcli connection modify "<old-profile>" \
 connection.master br0 \
 connection.slave-type bridge \
 ipv4.method disabled \
 ipv4.addresses "" \
 ipv4.gateway "" \
 ipv4.dns "" \
 ipv4.dns-search ""

That removes the old IPv4 address, gateway, and DNS settings from the physical connection. Keep IPv6 settings only if you have deliberately moved the IPv6 configuration to br0; otherwise, the old profile can still claim Layer 3 ownership.

If you need to preserve IPv6, modify the port without disabling it, then configure the equivalent IPv6 settings on the bridge profile. Do not use a blanket disable command when the host depends on IPv6.

Now put the host settings on the bridge.

sudo nmcli connection modify br0 \
 ipv4.method manual \
 ipv4.addresses "<host-cidr>" \
 ipv4.gateway "<gateway-ip>" \
 ipv4.dns "<dns-ip>"

Activate the profiles in a controlled batch.

sudo nmcli connection down "<old-profile>"
sudo nmcli connection up br0
sudo nmcli connection up "<old-profile>"

nmcli device status
nmcli connection show --active
ip -br addr
ip route

The old profile is now a port profile under br0. If it still shows an address on the physical interface, the migration is incomplete. Check the profile again rather than guessing which setting survived.

Should spanning tree be enabled or disabled on the bridge?

Enable Spanning Tree Protocol (STP) when the bridge can reach the same Layer 2 network through more than one path. That includes redundant physical links, another switch path, or a virtual topology that can loop back into the bridge.

A simple host bridge with one physical uplink and no alternate Layer 2 path can usually run with STP disabled. If you are not certain that the topology has one path, enable it. A broadcast loop can take down more than the machine you are configuring.

With iproute2, enable STP like this:

sudo ip link set dev br0 type bridge stp_state 1
ip -d link show dev br0

The detailed output shows bridge attributes, including STP state. Disable it only after you have confirmed that no alternate path can form.

sudo ip link set dev br0 type bridge stp_state 0
ip -d link show dev br0

With NetworkManager, set the bridge property in the profile.

sudo nmcli connection modify br0 bridge.stp yes
sudo nmcli connection down br0
sudo nmcli connection up br0

nmcli -f bridge.stp connection show br0
ip -d link show dev br0

STP can delay forwarding while the topology settles. That delay is preferable to a loop that floods the network. If you disable STP because a guest appears slow to start, diagnose the topology and bridge settings first. Turning off loop protection is not a performance fix.

How do you avoid losing a remote server connection during the migration?

Use a local console, serial console, hypervisor console, or out-of-band management before moving the address. SSH is a poor safety net while you are replacing the interface that carries SSH.

The safest migration has a rollback plan:

  1. Save the current address, route, DNS, and NetworkManager profile names.
  2. Open a console session that does not depend on the network.
  3. Prepare the bridge and port profiles before activating them.
  4. Schedule a rollback that restores the old profile after a short delay.
  5. Apply one disruptive change.
  6. Verify the bridge, address, route, and gateway.
  7. Cancel the rollback only after a new remote session works.

A rollback command might look like this when the old profile is still valid:

echo 'nmcli connection up "<old-profile>"' | at now + <short-delay>

Use your system's available scheduler and replace the placeholder with a short delay appropriate for your access method. If at is not installed or does not run on the host, use the console or a systemd timer instead.

Apply small batches, not a long script that destroys the old state before checking anything.

sudo nmcli connection up br0
ip -br addr show dev br0
ip route show default
ping -c 1 <gateway-ip>

If the gateway responds, test the resolver and a known external address.

resolvectl query <known-hostname>
ping -c 1 <known-ip>

The ping to an IP tests routing and basic reachability. The name lookup tests the resolver on top of that. Keep the layers separate, as explained in how I troubleshoot Linux networking.

Do not cancel the rollback because nmcli reported activated. A profile can be active while the host has the wrong route or no usable neighbor entry. Confirm the path from a second session first.

How do you verify that the bridge and its ports actually work?

Linux bridge hardware showing active Ethernet links across server and switch connections

An interface showing UP proves very little. Verify kernel state, address ownership, routes, bridge membership, VLAN state, and actual traffic.

ip -br link
ip -br addr
ip route
ip rule
bridge link show
bridge fdb show br br0
bridge vlan show

Use these checks to answer specific questions:

  • Is br0 up?
  • Is the physical interface listed as a port of br0?
  • Does only br0 have the host address?
  • Does the default route use br0?
  • Is the bridge forwarding frames?
  • Is VLAN filtering enabled, and do the expected VLAN entries exist?

If you use NetworkManager, check its view too.

nmcli general status
nmcli device status
nmcli connection show --active
nmcli -f GENERAL,IP4,IP6 device show br0

Then test each layer.

ping -c 1 <gateway-ip>
resolvectl query <known-hostname>
ping -c 1 <known-hostname>
ip neigh show dev br0

A failed gateway ping points to link, port membership, VLAN handling, or neighbor discovery. A successful IP ping with failed name lookup points to DNS. A resolved name with failed ping points to routing, filtering, or the remote host.

For a virtual machine bridge, check the guest-facing port as well.

bridge link show
ip link show type tuntap
ip link show type veth

The exact virtual interface depends on the hypervisor or container runtime. The principle does not change: the guest port must be attached to the same bridge, and the bridge must have a path to the correct VLAN or physical network.

How do you diagnose a bridge that looks up but does not pass traffic?

Start with kernel state, not another configuration command. A bridge can be administratively up while its port has no carrier, its VLAN is wrong, or its forwarding database has learned nothing.

Watch link, address, and route changes while reproducing the failure.

sudo ip monitor link addr route

In another terminal, inspect the port and bridge details.

ip -d link show dev br0
ip -d link show dev <physical-interface>
bridge link show
bridge vlan show
bridge fdb show br br0

If NetworkManager manages the bridge, read its logs during the failure.

journalctl -u NetworkManager -b
journalctl -u NetworkManager -b -f
nmcli general logging

The log should show profile activation, port attachment, carrier changes, and DHCP or address errors. If it says the device is unmanaged, stop changing bridge settings and fix ownership first.

Check the route and neighbor table separately.

ip route get <remote-ip>
ip neigh show dev br0
ip route show table all

A neighbor entry stuck in INCOMPLETE or FAILED means the host cannot resolve the next Layer 2 hop. That usually points to the wrong port, VLAN, switch configuration, or a missing physical link. It is not fixed by adding another default route.

Capture traffic on both sides of the bridge.

sudo tcpdump -eni br0
sudo tcpdump -eni <physical-interface>

If packets appear on br0 but not on the physical interface, inspect port state, VLAN filtering, and bridge forwarding. If packets leave the physical port but no replies return, check the upstream switch, VLAN, gateway, and remote host.

You can also trace NetworkManager's system calls when profile behavior is unclear.

sudo strace -f -e trace=network,ioctl \
 nmcli connection up br0

That is not a first-line bridge test. Use it when the visible NetworkManager error does not explain what changed. The useful evidence is still the same: which device was modified, which profile was activated, and what the kernel reported afterward.

For packet filtering, inspect the host firewall and bridge netfilter settings. A bridge may forward Ethernet frames while the host firewall drops traffic that crosses the bridge or reaches a local service.

sudo nft list ruleset
sysctl net.bridge.bridge-nf-call-iptables
sysctl net.bridge.bridge-nf-call-ip6tables

Do not change firewall policy until a packet capture shows where the packet stops. Otherwise you are changing security rules to compensate for a bad port or route.

Which bridge method should you use for a server or home lab?

Use iproute2 when you are proving a topology or debugging kernel behavior. The commands expose each state change, and the configuration disappears on reboot unless you save it elsewhere.

Use NetworkManager when the bridge is part of the machine's normal network configuration. Profiles survive reboot, integrate with DNS handling, and give you one service responsible for activation.

For a KVM host, NetworkManager is usually the practical persistent choice. Attach the physical uplink and guest virtual interfaces to the bridge, then keep the host's address on br0. For a lab where you are testing bridge flags, VLAN filtering, or forwarding behavior, build it with ip first and inspect the kernel state before making it permanent.

Do not let two managers fight over the same interface. That is how a working bridge becomes a boot race with a different answer after every restart.

FAQ

Can I keep the host IP address on the physical interface?

No. Move the host's address, default route, and DNS settings to the bridge. The physical interface should act as a Layer 2 port, or another manager may install conflicting routes and neighbor state.

Does a Linux bridge replace a router?

No. A bridge forwards Ethernet frames inside a Layer 2 segment. It does not create separate networks or route between subnets. Use a router, firewall, or VLAN-aware design when traffic must cross Layer 3 boundaries.

Why does the bridge work until NetworkManager restarts?

The live kernel state and the saved NetworkManager profile are different things. If you created br0 with ip, NetworkManager may not know that it should recreate or preserve it. Either make NetworkManager the owner or disable its control of that interface and manage persistence elsewhere.

Do I need a physical interface to create a bridge?

No. A bridge can connect virtual interfaces only. That is useful for isolated test networks, containers, and virtual machines. Without a port connected to an external network, though, the bridge will not provide outside connectivity.

Why does disabling STP sometimes appear to fix the bridge?

STP can delay forwarding while it checks the topology. Disabling it may remove that delay, but it also removes loop protection. If traffic improves only after STP is disabled, inspect the topology and forwarding state before keeping that change.

Related on this blog