Persistent interface names
Generates a systemd .link file per physical NIC that pins the kernel-assigned name to the card's MAC address. Once applied (after the next reboot), interface names stop drifting when you add, remove or move PCIe cards.
What this does
/etc/systemd/network/10-<iface>.link that says: "the device with this MAC must always be called this name". systemd-udevd applies the rule at every boot, before ifupdown reads /etc/network/interfaces.The problem this solves
Linux derives default interface names from PCI topology — eno1 = onboard, enp3s0 = the card in PCI bus 3, slot 0, etc. The naming scheme is deterministic given the same hardware layout. Change the layout and names shift:
- Add a GPU in front of an existing NIC → the NIC bus number can change → name changes.
- Move a card to a different PCIe slot → name changes.
- BIOS / UEFI update that re-enumerates devices → names can change.
- Replace a faulty card with the same model in a different slot → name changes.
After such a change, /etc/network/interfaces still references the old name; the bridge fails to come up; the host loses network. Setting up persistent names prevents this scenario from happening again.
How it works
Each generated file is intentionally minimal:
# /etc/systemd/network/10-eno1.link [Match] MACAddress=aa:bb:cc:dd:ee:ff [Link] Name=eno1
At boot, systemd-udevd matches the device by MAC and assigns the requested name before any other component (ifupdown, kernel default naming) gets to it. The file prefix 10- ensures these rules load early, ahead of the default 99-default.link.
What gets written, what gets skipped
| Type | Behaviour | Why |
|---|---|---|
| Onboard / PCIe NIC | .link file written | Backed by a real PCI device — the case the tool is for |
| Wi-Fi (phy80211) | .link file written | Has a real MAC and benefits from name stability |
| Bridges (vmbrX) | Skipped | Virtual; name comes from /etc/network/interfaces |
| Bonds (bondX) | Skipped | Virtual; bond name is set by ifupdown |
| veth / docker0 / br-XXXX | Skipped | Created on demand by Docker / LXC — not persistent hardware |
| tap / fwpr / fwln | Skipped | Created on demand by Proxmox per VM/CT |
| WireGuard / Cilium / Tailscale | Skipped | Software interfaces managed by their own daemons |
Safety net: previous .link files are backed up
If /etc/systemd/network/ already contains .link files (from a previous run or other tooling), they are copied to a timestamped backup directory before the new ones are generated:
/etc/systemd/network/backup-20260426-143012/ ├── 10-eno1.link (previous version) └── 10-enp3s0.link (previous version)
To roll back: copy the files back from the backup directory and reboot.
Takes effect on next reboot, not immediately
.link files only apply at boot, when udev re-enumerates devices. The tool reports "Changes will apply after reboot" for this reason. Renaming an interface live is risky and not attempted: an active vmbr0 with members would have to be reconfigured atomically, which is why the operation is deferred to the next clean boot.After the reboot
Once the names are pinned, the workflow for future hardware changes is simple:
- Power off, change hardware (add card, move slot, …), boot.
- Each NIC keeps its previous name because its MAC matches a
.linkfile. - If a NIC is replaced (different MAC), it gets a default kernel name (
enp<bus>s<slot>); re-run this menu to add a.linkentry for the new card's MAC.
Troubleshooting
"No physical interfaces found" after running the tool
ls -l /sys/class/net/ — every entry should have either a device symlink (PCI) or a phy80211 entry (Wi-Fi). If both are missing for what should be a real NIC, the driver is not loaded.After the reboot, names did not change as expected
cat /etc/systemd/network/10-<iface>.link. Then check udev logs: journalctl -u systemd-udevd -b | grep -i link. A common cause is a stale net.ifnames=0 kernel parameter that disables predictable naming entirely — remove it from /etc/default/grub, run update-grub, reboot.I want to undo persistent naming
.link files (rm /etc/systemd/network/10-*.link) or restore from the backup directory generated on the previous run. Reboot to apply.Related
- Bridge analysis & guided repair — the recovery path when names have already shifted.
- Config analysis & guided cleanup — to remove orphan blocks left behind by name shifts.
- Diagnostics — confirm the new names with Show Routing Table after reboot.