If you administer Linux across more than one distro in 2026, you maintain the mental model of four different network stacks: netplan (Ubuntu’s declarative front-end), ifupdown (Debian’s classic /etc/network/interfaces), NetworkManager (the RHEL family default, also a popular choice on Arch), and systemd-networkd (the minimalist option, default on Arch when nothing else is installed). openSUSE Leap adds a fifth: wicked. Each of these does the same job — bring a network interface up with the right IP, gateway, DNS — and each picks a fundamentally different abstraction. This article compares them across the seven distros covered in our Distro Reference, shows the static-IP recipe in each, and gives you a decision tree for greenfield deployments and migrations.
Contents
The four (five) stacks in one paragraph each
netplan is a YAML front-end Ubuntu adopted in 18.04 LTS. You write declarative YAML in /etc/netplan/*.yaml and netplan generates the configuration for the actual backend (either systemd-networkd or NetworkManager). The advantage is the configuration is human-readable, version-controllable, and stable across Ubuntu releases. The drawback is the indirection: when something breaks, you have to mentally translate netplan YAML into the backend’s mental model to debug. Default on Ubuntu Server since 18.04 and Ubuntu Desktop since 22.04.
ifupdown is the original Debian way: edit /etc/network/interfaces with stanzas (auto eth0 / iface eth0 inet static), then ifup eth0 or restart the networking service. Conservative, well-documented, no surprises. Still the Debian server default in 2026. Limited expressiveness compared to YAML or keyfiles but exactly what you want for a small, stable installation.
NetworkManager is the GNOME-era state daemon. Connections are stored as keyfiles in /etc/NetworkManager/system-connections/*.nmconnection and managed via nmcli (CLI), nmtui (curses TUI) or a GUI. It handles transitions automatically — Wi-Fi reconnection, VPN startup, captive portal detection. Default on RHEL 9 family (including Rocky and Alma), Fedora, and increasingly other distros that want desktop-style network handling.
systemd-networkd is the systemd team’s minimalist offering. Configuration in /etc/systemd/network/*.network, no daemon state to speak of, integrates with systemd-resolved for DNS. Lightweight, predictable, popular on Arch and container hosts. Does less than NetworkManager but does it with fewer moving parts.
wicked is openSUSE’s stack. Compatible-ish syntax with the old Red Hat /etc/sysconfig/network-scripts but with its own daemon. Still the openSUSE Leap default in 2026. Tumbleweed (the rolling sibling) has switched to NetworkManager.
Per-distro defaults in 2026
The table below summarises which stack ships as default on each distro covered in the Distro Reference.
| Distro | Default stack | Backend behind it |
|---|---|---|
| Ubuntu 24.04 LTS Server | netplan | systemd-networkd |
| Ubuntu 24.04 LTS Desktop | netplan | NetworkManager |
| Debian 12 Bookworm | ifupdown | (itself) |
| Fedora 40 | NetworkManager | (itself) |
| Rocky 9 / Alma 9 / RHEL 9 | NetworkManager | (itself) |
| Arch Linux (minimal install) | none | you pick one |
| openSUSE Leap 15.5 | wicked | (itself) |
| Alpine Linux 3.19 | ifupdown (busybox) | (itself) |
Two non-obvious entries deserve a word. Ubuntu Server vs Desktop: both use netplan as the user-facing config, but the backend is different. On Server, netplan generates systemd-networkd configuration. On Desktop, netplan generates NetworkManager configuration so the GUI works. You write the same YAML; netplan picks the right backend at install time. Arch minimal install: the base install ships nothing for routing. You must install one of: systemd-networkd (included with the systemd package and already disabled), networkmanager, dhcpcd, or connman. Most Arch users on a server pick systemd-networkd; on a laptop, NetworkManager.
The static-IP recipe per stack
The same task — give eth0 the static IP 192.168.1.10/24 with gateway 192.168.1.1 and DNS 1.1.1.1 — expressed in each stack.
netplan
# /etc/netplan/01-static.yaml
network:
version: 2
ethernets:
eth0:
addresses: [192.168.1.10/24]
routes:
- to: default
via: 192.168.1.1
nameservers:
addresses: [1.1.1.1, 8.8.8.8]
# Apply (use 'try' first on a remote box - it rolls back in 120s if SSH dies)
sudo netplan try
sudo netplan apply
ifupdown (Debian / Alpine)
# /etc/network/interfaces
auto eth0
iface eth0 inet static
address 192.168.1.10/24
gateway 192.168.1.1
dns-nameservers 1.1.1.1 8.8.8.8
# Apply
sudo systemctl restart networking
# (Alpine: sudo rc-service networking restart)
NetworkManager (nmcli)
sudo nmcli con add type ethernet con-name eth0-static ifname eth0 \ ip4 192.168.1.10/24 gw4 192.168.1.1 sudo nmcli con mod eth0-static ipv4.dns "1.1.1.1 8.8.8.8" sudo nmcli con mod eth0-static ipv4.method manual sudo nmcli con up eth0-static # Or interactive TUI sudo nmtui
systemd-networkd
# /etc/systemd/network/10-eth0.network [Match] Name=eth0 [Network] Address=192.168.1.10/24 Gateway=192.168.1.1 DNS=1.1.1.1 DNS=8.8.8.8 # Enable sudo systemctl enable --now systemd-networkd sudo systemctl restart systemd-networkd
wicked (openSUSE Leap)
# /etc/sysconfig/network/ifcfg-eth0 BOOTPROTO='static' IPADDR='192.168.1.10/24' STARTMODE='auto' # /etc/sysconfig/network/routes default 192.168.1.1 - - # /etc/sysconfig/network/config (DNS) NETCONFIG_DNS_STATIC_SERVERS="1.1.1.1 8.8.8.8" # Apply sudo wicked ifreload eth0 sudo netconfig update -f
DNS resolver: resolvconf, systemd-resolved, the manual route
DNS is where the cross-distro story gets confusing. Three approaches coexist:
- Manual /etc/resolv.conf: the file lists nameservers, one per line. Simple, predictable. The catch is that many network stacks overwrite it on every restart — your edit gets erased.
- systemd-resolved: a stub resolver at 127.0.0.53 that forwards to configured upstream servers and caches results. /etc/resolv.conf becomes a symlink to
/run/systemd/resolve/stub-resolv.conf. Default on Ubuntu, Arch with networkd, and increasingly elsewhere. - NetworkManager-managed: NM writes /etc/resolv.conf based on the connection’s
ipv4.dns. On systems that combine NM and systemd-resolved, NM tells resolved which DNS to use.
To check which approach is active on a given system:
resolvectl status 2>/dev/null # systemd-resolved is active if this returns ls -la /etc/resolv.conf # symlink target tells you the manager cat /etc/resolv.conf # what is actually being used
Migration patterns
From Debian ifupdown to netplan
If you are moving from Debian 12 to Ubuntu 24.04, the ifupdown configuration does not carry over: netplan does not read /etc/network/interfaces. Translation table:
# ifupdown
auto eth0
iface eth0 inet static
address 10.0.0.5/24
gateway 10.0.0.1
dns-nameservers 1.1.1.1
# Equivalent netplan
network:
version: 2
ethernets:
eth0:
addresses: [10.0.0.5/24]
routes:
- to: default
via: 10.0.0.1
nameservers:
addresses: [1.1.1.1]
From RHEL 7/8 network-scripts to RHEL 9 nmcli
RHEL 9 removed /etc/sysconfig/network-scripts as the source of truth. The legacy ifcfg-* files still parse on RHEL 9 if you install NetworkManager-initscripts-ifcfg-rh, but the canonical place is NetworkManager keyfiles. Translation:
# Legacy /etc/sysconfig/network-scripts/ifcfg-eth0 (RHEL 7/8) TYPE=Ethernet BOOTPROTO=none DEVICE=eth0 ONBOOT=yes IPADDR=10.0.0.5 PREFIX=24 GATEWAY=10.0.0.1 DNS1=1.1.1.1 # Equivalent on RHEL 9 (via nmcli) sudo nmcli con add type ethernet con-name eth0 ifname eth0 \ ip4 10.0.0.5/24 gw4 10.0.0.1 sudo nmcli con mod eth0 ipv4.dns 1.1.1.1 ipv4.method manual sudo nmcli con up eth0
For bulk migrations across many hosts, the nmcli con import type keyfile form lets you generate keyfiles offline and rsync them into place. Cleaner than running thousands of nmcli con add commands.
From wicked (openSUSE Leap) to NetworkManager (openSUSE Tumbleweed or next major Leap)
This is the migration most openSUSE admins will face in the next 12-18 months. SUSE has signalled NetworkManager will be the default in future Leap releases. The wicked /etc/sysconfig/network/ifcfg-* files do not work under NetworkManager directly, but the conversion is mechanical:
# wicked /etc/sysconfig/network/ifcfg-eth0 BOOTPROTO='static' IPADDR='10.0.0.5/24' STARTMODE='auto' # NetworkManager equivalent sudo nmcli con add type ethernet con-name eth0 ifname eth0 \ ip4 10.0.0.5/24 gw4 10.0.0.1 sudo nmcli con up eth0
Decision tree: which stack for which scenario
For a greenfield deployment, the choice is usually dictated by the distro default. When you have flexibility, pick by use case:
- Server, single static IP, no Wi-Fi, no mobile → systemd-networkd or netplan. Minimal moving parts, predictable, configuration-as-code-friendly.
- Server with complex routing, VPN, multiple network namespaces → NetworkManager. The state daemon handles transitions cleanly; nmcli scripting is mature.
- Desktop / laptop with Wi-Fi, VPN, multiple network locations → NetworkManager. Nothing else gets close on transition handling.
- Container host where pods get veth pairs and namespaces → systemd-networkd. Tiny footprint, plays well with cri-o / containerd / docker.
- Bare-metal Debian server with static IP that does not change → ifupdown. Boring, no daemons, well-documented in /etc.
- Cross-distro deployment automation (Ansible, Salt) → use netplan on Ubuntu and NetworkManager keyfiles elsewhere. Both render predictably; ifupdown’s stanza syntax is harder to template.
Common gotchas across all stacks
- Interface naming: modern distros use predictable interface names (
enp3s0,ens18) instead ofeth0. Your config must match whatip linkshows;eth0from a tutorial may not exist on your box. Disable the predictable naming with the kernel parameternet.ifnames=0if you really wanteth0back. - IPv6 enabled by default: all modern distros enable IPv6 by default. If your network does not have IPv6, you may see slow connection times due to AAAA lookups. Either provide v6 connectivity or disable v6 explicitly in the stack config.
- DNS does not work but ping does: classic systemd-resolved confusion.
ping 1.1.1.1works,ping google.comdoes not. Checkresolvectl statusfor the stub state. - Lost SSH after restart: applying network changes on a remote box without a fallback can lock you out.
netplan tryrolls back in 120 seconds.nmcliapplies live without restart. For ifupdown, schedule asleep 60 && systemctl restart networkingin a tmux session so you can reconnect and cancel if needed. - MAC address-based persistence: some stacks pin connections to MAC addresses. After a VM clone or a NIC swap, the connection profile may refuse to bind to the new interface. Look for
match-device-idorHWADDR=in the config and update or remove the binding.
Need the syntax for a specific distro?
Our Linux Distro Reference shows the exact command, file path and workflow for network configuration on the seven major distros — side-by-side compare mode included.
FAQ
Should I just use NetworkManager everywhere?
It is a valid strategy for a small fleet, especially with mixed desktops and servers. The downside is the configuration is in keyfiles that are not as natural to template as YAML. For a 50+ host fleet automated with Ansible, mixing netplan on Ubuntu and NetworkManager on RHEL family produces cleaner code than NetworkManager everywhere.
Why does Ubuntu have netplan if the backend is just NetworkManager or systemd-networkd?
Stability across versions and simpler abstraction for users. The YAML schema is stable; the backends evolve underneath. Ubuntu’s bet is that a stable user-facing config language is worth the indirection cost. In practice it works well for the 95 percent case and gets in the way for the 5 percent edge cases where you need backend-specific tuning.
Is wicked deprecated?
In the sense that openSUSE Tumbleweed has moved on, yes. In the sense that openSUSE Leap 15.5 still ships and supports it, no. New deployments on Leap should still use wicked because that is what the distro tooling assumes; new deployments on Tumbleweed should use NetworkManager.
Can I run multiple stacks on the same host?
Technically yes, in practice no. NetworkManager and systemd-networkd will both try to manage the same interface and fight over it. If two stacks are installed, disable one explicitly via systemctl mask. Containers and namespaces are an exception — the host stack manages the host interface, the container runtime manages the veth pairs inside namespaces.
How do I disable IPv6 across all stacks?
Three options. Kernel parameter ipv6.disable=1 at boot disables IPv6 globally and is the cleanest if you really mean it. Per-interface sysctl net.ipv6.conf.eth0.disable_ipv6=1 applies at runtime. Per-stack: link-local: false in netplan, ipv6.method ignore in nmcli. Note: many modern services assume v6 is available; disabling can break them subtly.
What about Wi-Fi configuration?
NetworkManager is the path of least resistance: nmcli device wifi connect <SSID> password <pw>. On systemd-networkd you also need iwd or wpa_supplicant. ifupdown supports wpa_supplicant via /etc/network/interfaces stanzas but the experience is dated.













