When upgrading from legacy systems using traditional interface names (eth0, eth1) to modern systemd-based distributions, administrators face a critical challenge: network interfaces get renamed according to the "predictable" naming scheme during the first boot after upgrade. This can break existing network configurations if not handled properly.
Systemd's predictable naming follows this hierarchy:
1. Firmware/BIOS provided index numbers (eno1) 2. PCI Express hotplug slot index numbers (ens1) 3. Physical location (enp2s0) 4. MAC address (enx78e7d1ea46da) 5. Traditional unpredictable (eth0)
Use udevadm
to simulate the naming process:
# udevadm test-builtin net_id /sys/class/net/eth0 2>/dev/null ID_NET_NAME_MAC=enx78e7d1ea46da ID_NET_NAME_PATH=enp3s0 ID_NET_NAME_SLOT=ens1
The final name will be the first available option from this list.
Create a udev rule to maintain legacy names:
# /etc/udev/rules.d/10-persistent-net.rules SUBSYSTEM=="net", ACTION=="add", ATTR{address}=="00:1a:4b:xx:xx:xx", NAME="eth0"
Alternatively, disable predictable naming by adding this kernel parameter in GRUB:
net.ifnames=0
For smooth upgrades:
- Predict new names using
udevadm
- Prepare both
/etc/network/interfaces
(legacy) and/etc/netplan/
(new) - Create udev rules as fallback
- Document interface mappings
Upgrading a server with two interfaces:
# Before upgrade: eth0: 00:1a:4b:12:34:56 (public) eth1: 00:1a:4b:12:34:57 (private) # Predict new names: udevadm test-builtin net_id /sys/class/net/eth0 → enp3s0 udevadm test-builtin net_id /sys/class/net/eth1 → enp3s1 # Prepare netplan configuration: network: version: 2 renderer: networkd ethernets: enp3s0: dhcp4: true enp3s1: addresses: [192.168.1.1/24]
Modern Linux distributions like Ubuntu (since 16.04) and Debian (since Stretch) have adopted systemd's predictable network interface naming scheme. While this brings consistency, it creates migration challenges when upgrading from systems using legacy names like eth0
.
systemd assigns interface names based on:
- Firmware/BIOS index numbers (eno1)
- PCI topology (ens1)
- MAC addresses (enx78e7d1ea46da)
- Virtual interfaces (veth0)
Here are reliable methods to predict interface names before reboot:
# Method 1: Use udevadm to simulate naming
sudo udevadm test-builtin net_id /sys/class/net/eth0 2>/dev/null | grep ID_NET_NAME_
# Sample output might show:
ID_NET_NAME_PATH=enp3s0
ID_NET_NAME_MAC=enx001122334455
This command reveals all possible naming variations that systemd might use.
For permanent naming, create a custom udev rule:
# /etc/udev/rules.d/70-persistent-net.rules
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*",
ATTR{address}=="00:11:22:33:44:55", NAME="eth0"
When moving from /etc/network/interfaces
to netplan
:
# /etc/netplan/01-netcfg.yaml
network:
version: 2
ethernets:
enp3s0:
dhcp4: true
Test your configuration changes:
sudo netplan generate
sudo netplan --debug apply
If you need to temporarily disable predictable naming:
# Edit kernel parameters in /etc/default/grub
GRUB_CMDLINE_LINUX="net.ifnames=0 biosdevname=0"
sudo update-grub
Here's a script to automate interface name prediction:
#!/bin/bash
for iface in $(ls /sys/class/net/ | grep -v lo); do
echo "Legacy name: $iface"
udevadm info -q path -n $iface | xargs udevadm test-builtin net_id 2>/dev/null | grep ID_NET_NAME_
done