Configure systemd-networkd
Learn how to configure systemd-networkd with .network unit files for static IPs, DHCP, bonding, bridges, and VLANs on modern Linux servers.
Before you start
- ▸Root or sudo access on the target system
- ▸systemd version 245 or newer (check with systemctl --version)
- ▸Physical or SSH console access in case network connectivity is interrupted during the switch
- ▸Knowledge of your interface names (use 'ip link show' to list them)
systemd-networkd is a lean, dependency-light network daemon that ships with systemd. It excels in server, container, and headless environments where NetworkManager's GUI-centric feature set is unnecessary overhead. This guide shows you how to switch to networkd, write .network unit files, and set up production-ready configurations including bonding, bridges, and VLANs.
NetworkManager vs systemd-networkd
Both daemons configure network interfaces, but they target different use cases:
- NetworkManager: Designed for desktops and laptops. Handles Wi-Fi roaming, VPN plugins, per-user profiles, and integrates with GNOME/KDE network applets. It is the correct default on Wayland desktops.
- systemd-networkd: Designed for servers and containers. Static configuration files, no D-Bus GUI dependency, deterministic behaviour on boot, native VLAN/bridge/bond support. Works well alongside
systemd-resolvedfor DNS.
Do not run both daemons managing the same interface simultaneously — pick one per interface, or disable NetworkManager entirely on servers.
Prerequisites
Ensure you have a recent systemd (v245+ covers everything in this guide). Check your version:
systemctl --version
All configuration files go in /etc/systemd/network/. Files in this directory override any matching files in /lib/systemd/network/. Naming convention matters: networkd processes files in lexicographic order, so prefix filenames with two-digit numbers (10-, 20-) to control precedence.
Step 1: Disable NetworkManager, Enable networkd
On Debian/Ubuntu:
sudo systemctl disable --now NetworkManager
sudo systemctl enable --now systemd-networkd
sudo systemctl enable --now systemd-resolved
On Fedora/RHEL/Rocky:
sudo systemctl disable --now NetworkManager
sudo systemctl enable --now systemd-networkd
sudo systemctl enable --now systemd-resolved
On Arch:
sudo systemctl disable --now NetworkManager
sudo systemctl enable --now systemd-networkd systemd-resolved
Point /etc/resolv.conf to the resolved stub resolver (recommended on all distros):
sudo ln -sf /run/systemd/resolve/stub-resolv.conf /etc/resolv.conf
Step 2: Basic Static and DHCP .network Files
Each .network file has at minimum a [Match] section (which interface to configure) and a [Network] section (what to apply). A .netdev file creates virtual devices (bonds, bridges, VLANs); a .network file then configures them.
DHCP on a single interface
sudo tee /etc/systemd/network/10-eth0.network <<'EOF'
[Match]
Name=eth0
[Network]
DHCP=yes
EOF
Static IP address
sudo tee /etc/systemd/network/10-eth0.network <<'EOF'
[Match]
Name=eth0
[Network]
Address=192.168.1.50/24
Gateway=192.168.1.1
DNS=1.1.1.1 9.9.9.9
EOF
Match by MAC address instead of interface name when interface names are unpredictable:
sudo tee /etc/systemd/network/10-server.network <<'EOF'
[Match]
MACAddress=52:54:00:ab:cd:ef
[Network]
Address=10.0.0.10/24
Gateway=10.0.0.1
DNS=10.0.0.1
EOF
Step 3: Network Bonding
Bonding aggregates multiple physical interfaces for redundancy or throughput. You need a .netdev file to create the bond device, then two .network files — one to attach the physical ports as bond members, and one to configure the bond itself.
Create the bond virtual device
sudo tee /etc/systemd/network/20-bond0.netdev <<'EOF'
[NetDev]
Name=bond0
Kind=bond
[Bond]
Mode=active-backup
MIIMonitorSec=100ms
EOF
Common Mode values: active-backup (failover), balance-rr (round-robin), 802.3ad (LACP — requires switch support).
Enslave the physical interfaces
sudo tee /etc/systemd/network/21-bond0-slave.network <<'EOF'
[Match]
Name=eth0 eth1
[Network]
Bond=bond0
EOF
Configure the bond interface
sudo tee /etc/systemd/network/22-bond0.network <<'EOF'
[Match]
Name=bond0
[Network]
Address=192.168.1.50/24
Gateway=192.168.1.1
DNS=1.1.1.1
EOF
Step 4: Network Bridges
Bridges are essential for KVM/QEMU virtual machines that need layer-2 connectivity to the host network. The pattern is identical to bonding: create the bridge device, attach a port, configure the bridge.
Create the bridge device
sudo tee /etc/systemd/network/30-br0.netdev <<'EOF'
[NetDev]
Name=br0
Kind=bridge
EOF
Attach the physical port
sudo tee /etc/systemd/network/31-br0-port.network <<'EOF'
[Match]
Name=eth0
[Network]
Bridge=br0
EOF
Configure the bridge
sudo tee /etc/systemd/network/32-br0.network <<'EOF'
[Match]
Name=br0
[Network]
Address=192.168.1.50/24
Gateway=192.168.1.1
DNS=1.1.1.1
EOF
VMs configured with br0 as their bridge will appear directly on the 192.168.1.0/24 network.
Step 5: VLANs
VLANs require a .netdev to create the VLAN interface, a reference in the parent interface's .network file, and a separate .network file for the VLAN interface itself.
Create the VLAN device
sudo tee /etc/systemd/network/40-vlan100.netdev <<'EOF'
[NetDev]
Name=vlan100
Kind=vlan
[VLAN]
Id=100
EOF
Reference the VLAN in the parent interface
sudo tee /etc/systemd/network/10-eth0.network <<'EOF'
[Match]
Name=eth0
[Network]
VLAN=vlan100
EOF
Configure the VLAN interface
sudo tee /etc/systemd/network/41-vlan100.network <<'EOF'
[Match]
Name=vlan100
[Network]
Address=10.100.0.5/24
Gateway=10.100.0.1
EOF
You can stack VLANs on a bonded or bridged interface by referencing the bond/bridge name in the parent [Match] section instead of a physical interface.
Apply and Verify
Reload networkd after any configuration change:
sudo networkctl reload
Check the status of all managed links:
networkctl status
Inspect a specific interface:
networkctl status eth0
Confirm addresses are applied:
ip addr show
ip route show
For bonding, check which slave is active:
cat /proc/net/bonding/bond0
Troubleshooting
- Interface shows "unmanaged": networkd only manages interfaces with a matching
.networkfile. Double-check the[Match]section name or MAC. Runnetworkctl listto see all detected interfaces and their state. - "configuring" state that never resolves: Often caused by a missing route or gateway. Check
journalctl -u systemd-networkd -ffor specific errors. - DNS not working after switching: Confirm
/etc/resolv.confis the symlink to the stub resolver, not a plain file left by NetworkManager. Runresolvectl statusto verify per-interface DNS assignments. - Bond stuck in degraded state: The
MIIMonitorSecvalue controls how fast failures are detected. Also verify both NICs are visible withip link showbefore networkd starts. - VLAN traffic not passing: Confirm the upstream switch port is configured as a trunk and the correct VLAN IDs are allowed. networkd configures the host correctly; misconfigured switch ports are the most common failure point.
Frequently asked questions
- Can I run systemd-networkd and NetworkManager on the same machine?
- Yes, but not on the same interface simultaneously. It is safest to disable NetworkManager entirely on servers. On desktops with both wired and wireless interfaces, you could configure one with networkd and let NM handle Wi-Fi, but this adds complexity and is generally not recommended.
- Do I need to reboot after changing .network files?
- No. Run 'sudo networkctl reload' to pick up changes immediately. For .netdev changes (new virtual devices), you may need to run 'sudo systemctl restart systemd-networkd' since virtual devices must be created before they can be configured.
- How do I match an interface when its name changes between reboots?
- Use MACAddress= in the [Match] section instead of Name=. Alternatively, create a persistent interface name via a systemd .link file in /etc/systemd/network/ using the [Link] Name= key to rename the interface to something stable.
- What is the difference between a .network, .netdev, and .link file?
- A .link file configures low-level interface properties (renaming, MTU, offloading) and is processed by udev. A .netdev file creates virtual network devices like bonds, bridges, and VLANs. A .network file assigns addressing and routing to any interface, physical or virtual.
- How do I configure LACP (802.3ad) bonding instead of active-backup?
- In the [Bond] section of your .netdev file, set Mode=802.3ad and optionally set LACPTransmitRate=fast. Your switch ports must also be configured for LACP/port-channel aggregation, or the bond will not come up correctly.
Related guides
Build a Mesh VPN with Nebula
Build a fully self-hosted mesh VPN with Nebula: create a CA, sign node certs, configure lighthouses, enforce group-based firewall rules, and run as a systemd service.
Common Linux Network Ports Reference
Learn Linux port ranges, read /etc/services, find what's listening with ss and nmap, and apply solid firewall rules to expose or block the right ports.
How to Configure a Static IP on Linux
Configure a static IP on Linux using Netplan, NetworkManager (nmcli), or systemd-networkd across Ubuntu, Fedora, Debian, and Arch with verified steps.
Expose a Service with Cloudflare Tunnel
Expose local services to the internet without port-forwarding using Cloudflare Tunnel. Install cloudflared, create a named tunnel, configure ingress rules, and run as a systemd service.