REALLY Persistent Ethernet Interfaces on Linux
So Linux has adopted Persistent Device Naming, which is a really great thing for most systems. Unlike the old days where we just had eth0
and eth1
and eth2
etc (which at least has no spaces unlike Local Area Connection 6
that another OS uses), whose order depended on driver initialization in the kernel. Most people just had eth0
and were happy, and most people will still just have one Ethernet interface and will still be happy.
But with more complex setups, this persistent naming can be a problem, especially as PCIe devices come and go and change the bus layout. I’d really like truly persistent naming, tied to the specific MAC address or something, that won’t ever change no matter what else I do with the system.
To be fair to persistent device names, for most people who are not making regular hardware changes, they are a good thing. The hierarchy of naming prefers onboard naming when possible (i.e. provided by the UEFI / HW), followed by the device path. This device path is consistent across reboots, but adding or removing hardware can cause items in the list to move up and down, changing their path ID (i.e. enp4
becomes enp5
after adding another PCIe card). But at least replacing hardware with identical hardware will keep the path IDs the same, so we can replace NICs or really anything else in the system without messing up our network configuration.
Solution⌗
The solution is to rename these devices on our own terms instead of the udev methodology. We can match hardware based on IDs such as the MAC address, which identifies a singular NIC, and use this to assign a name of our own. Now it’s up to us to modify this file if we ever replace a NIC, but at least other things in the system won’t change our name.
Here’s the documentation for systemd link units, it’s incredible really.
So given that information, I constructed the absolute minimal link file for my Proxmox system. We can’t use any name that the system might assign automatically (such as ethX, enoX, enpX, …) or we are in for trouble. I was originally going to name them geX
for gigabit ethernet and xgX
for 10/25Gig, but Proxmox’s web UI was not a fan of this and refused to do any networking administration since it couldn’t figure out what type those were by parsing the /etc/network/interfaces
file. So, I settled on enge0
for my onboard gigabit Ethernet and enxg1
for the port on the 25 gig card that I’m using (enxg0 is the other port on the card, since these used to be function 0 and function 1 of the device). Remember that enx
is used by devices identified by their MAC address and nothing else (usually USB NICs), so don’t use that. eno
, enp
, and ens
are all used by udev as well.
We now need to write a unit file for each interface we want to have a really permanent name, and it needs to start with a number less than 99, since 99-default.link will set the interface to regular persistent naming.
That results in a file like /etc/systemd/network/10-ge0.link
:
Add one for each, in my case I added 3. Make sure you get the MAC right. Now go into /etc/network/interfaces
and replace the old name with the new one. On reboot, udev should do its thing, call systemd-link, which will do it’s thing, and everything should magically come up.
My /etc/network/interfaces
on Proxmox now looks like this:
And they show up Proxmox UI too!
And of course ip a
shows the interfaces as expected!
So now I’m free to add/remove PCIe cards at will (this system gets used for a lot of testing random devices) and not worry about what that will do to my main NIC.