How to Predict and Preserve Systemd’s Predictable Network Interface Names During Ubuntu/Debian Upgrades


2 views

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:

  1. Predict new names using udevadm
  2. Prepare both /etc/network/interfaces (legacy) and /etc/netplan/ (new)
  3. Create udev rules as fallback
  4. 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