While Network Manager is the default networking stack on most desktop and server distributions, there are situations where systemd-networkd is the better choice for a KVM hypervisor. If you are running a headless server, want minimal overhead, or prefer declarative configuration files over a daemon-heavy approach, systemd-networkd delivers exactly that. This guide covers how to configure bridge networking on a KVM host using systemd-networkd on Ubuntu 24.04 Server and RHEL 10.
When to Use systemd-networkd Over Network Manager
Network Manager is built for flexibility – it handles Wi-Fi, VPNs, mobile broadband, and dynamic network changes gracefully. That flexibility comes with overhead that a dedicated KVM server does not need. Here is when systemd-networkd makes more sense:
- Headless servers with static network configurations that rarely change
- Minimal installations where you want fewer running services
- Container hosts and hypervisors where predictable, fast boot-time networking matters
- Environments where you want plain-text configuration files version-controlled in git
- Systems already using systemd for everything else and you want consistency
The configuration uses .netdev files to define virtual devices (like bridges) and .network files to configure addressing and link membership. Both go in /etc/systemd/network/ and are processed in lexical order by filename.
Prerequisites
- A KVM host running Ubuntu 24.04 Server or RHEL 10
- Root or sudo access
- Knowledge of your physical interface name (check with
ip link show) - Console access recommended when changing network configuration remotely
Step 1 – Disable Network Manager (If Active)
On systems where Network Manager is running, you need to disable it before switching to systemd-networkd. Running both at the same time causes conflicts.
sudo systemctl stop NetworkManager
sudo systemctl disable NetworkManager
sudo systemctl mask NetworkManager
On Ubuntu 24.04 Server with Netplan, also stop the Netplan backend if present.
sudo systemctl stop systemd-networkd
sudo rm -f /etc/netplan/*.yaml
Verify Network Manager is no longer active.
systemctl status NetworkManager
Step 2 – Enable systemd-networkd and systemd-resolved
Enable both systemd-networkd for network configuration and systemd-resolved for DNS resolution.
sudo systemctl enable systemd-networkd
sudo systemctl enable systemd-resolved
sudo systemctl start systemd-resolved
Link the resolved stub to /etc/resolv.conf so applications use systemd-resolved for DNS.
sudo ln -sf /run/systemd/resolve/stub-resolv.conf /etc/resolv.conf
Step 3 – Create the Bridge Device
Create a .netdev file that defines the bridge interface. The filename prefix (e.g., 10-) controls processing order – lower numbers are processed first.
sudo tee /etc/systemd/network/10-br0.netdev <<EOF
[NetDev]
Name=br0
Kind=bridge
EOF
This tells systemd-networkd to create a bridge device named br0 at boot time.
Step 4 – Bind the Physical Interface to the Bridge
Create a .network file for your physical Ethernet interface that assigns it as a member of the bridge. Replace enp3s0 with your actual interface name.
sudo tee /etc/systemd/network/20-enp3s0.network <<EOF
[Match]
Name=enp3s0
[Network]
Bridge=br0
EOF
This file matches the physical interface by name and adds it to the br0 bridge. Notice there is no IP configuration here – the physical interface should not have an IP address when it is a bridge member.
Step 5 – Configure the Bridge with a Static IP
Create the .network file for the bridge itself. This is where you assign the IP address, gateway, and DNS settings.
sudo tee /etc/systemd/network/30-br0.network <<EOF
[Match]
Name=br0
[Network]
Address=192.168.1.100/24
Gateway=192.168.1.1
DNS=8.8.8.8
DNS=8.8.4.4
Domains=example.com
[Link]
RequiredForOnline=carrier
EOF
The [Link] section with RequiredForOnline=carrier prevents systemd from waiting for a full online state before considering the network ready, which speeds up boot time.
Alternative – DHCP Configuration
If you prefer DHCP on the bridge (common in lab environments), replace the bridge network file with this.
sudo tee /etc/systemd/network/30-br0.network <<EOF
[Match]
Name=br0
[Network]
DHCP=ipv4
[DHCP]
UseDNS=true
UseDomains=true
[Link]
RequiredForOnline=carrier
EOF
Step 6 – Restart systemd-networkd
Apply the new configuration by restarting the service. If you are connected over SSH, you may lose your session briefly.
sudo systemctl restart systemd-networkd
If you want to apply changes without a full restart, use networkctl reload (available in systemd 249+).
sudo networkctl reload
Step 7 – Verify the Configuration
Run through a series of checks to confirm everything is working.
Check the overall network status.
networkctl status
Check the bridge specifically.
networkctl status br0
Expected output should show the bridge with your static IP, the linked physical interface, and an “online” or “routable” state.
Verify the IP address assignment.
ip addr show br0
Confirm the physical interface is a bridge member.
bridge link show
Test DNS resolution.
resolvectl status
ping -c 3 google.com
List all managed links and their states.
networkctl list
Step 8 – Use the Bridge with KVM Virtual Machines
With the bridge active, attach VMs to it during creation.
virt-install \
--name myvm \
--ram 2048 \
--vcpus 2 \
--disk size=20 \
--os-variant ubuntu24.04 \
--network bridge=br0 \
--cdrom /var/lib/libvirt/images/ubuntu-24.04.iso
For existing VMs, edit the domain XML with virsh edit vmname and set the interface section to use the bridge.
<interface type='bridge'>
<source bridge='br0'/>
<model type='virtio'/>
</interface>
File Summary
Here is a recap of the three configuration files and their purpose.
| File | Purpose |
|---|---|
/etc/systemd/network/10-br0.netdev | Defines the br0 bridge device |
/etc/systemd/network/20-enp3s0.network | Binds the physical interface to the bridge |
/etc/systemd/network/30-br0.network | Assigns IP, gateway, DNS to the bridge |
Troubleshooting
If the bridge does not come up, check the journal for errors.
journalctl -u systemd-networkd -b --no-pager
Common issues include typos in interface names in the [Match] section, missing .netdev files, or leftover Network Manager configurations. Verify that no other service is managing the same interfaces.
systemctl list-units --type=service | grep -i network
Only systemd-networkd.service and systemd-resolved.service should be active for network management.
Summary
Using systemd-networkd for KVM host networking gives you a lightweight, file-based configuration that is easy to understand, version control, and deploy across multiple hypervisors. The approach is simple – define the bridge device in a .netdev file, bind the physical interface to it with a .network file, and configure addressing on the bridge with another .network file. Once active, VMs attached to the bridge get direct Layer 2 access to your physical network, exactly like they would with Network Manager but with less overhead.































































