<section xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xml:id="sec-rename-ifs">
  <title>Renaming network interfaces</title>
  <para>
    NixOS uses the udev
    <link xlink:href="https://systemd.io/PREDICTABLE_INTERFACE_NAMES/">predictable
    naming scheme</link> to assign names to network interfaces. This
    means that by default cards are not given the traditional names like
    <literal>eth0</literal> or <literal>eth1</literal>, whose order can
    change unpredictably across reboots. Instead, relying on physical
    locations and firmware information, the scheme produces names like
    <literal>ens1</literal>, <literal>enp2s0</literal>, etc.
  </para>
  <para>
    These names are predictable but less memorable and not necessarily
    stable: for example installing new hardware or changing firmware
    settings can result in a
    <link xlink:href="https://github.com/systemd/systemd/issues/3715#issue-165347602">name
    change</link>. If this is undesirable, for example if you have a
    single ethernet card, you can revert to the traditional scheme by
    setting
    <xref linkend="opt-networking.usePredictableInterfaceNames" /> to
    <literal>false</literal>.
  </para>
  <section xml:id="sec-custom-ifnames">
    <title>Assigning custom names</title>
    <para>
      In case there are multiple interfaces of the same type, it’s
      better to assign custom names based on the device hardware
      address. For example, we assign the name <literal>wan</literal> to
      the interface with MAC address
      <literal>52:54:00:12:01:01</literal> using a netword link unit:
    </para>
    <programlisting language="bash">
systemd.network.links.&quot;10-wan&quot; = {
  matchConfig.PermanentMACAddress = &quot;52:54:00:12:01:01&quot;;
  linkConfig.Name = &quot;wan&quot;;
};
</programlisting>
    <para>
      Note that links are directly read by udev, <emphasis>not
      networkd</emphasis>, and will work even if networkd is disabled.
    </para>
    <para>
      Alternatively, we can use a plain old udev rule:
    </para>
    <programlisting language="bash">
services.udev.initrdRules = ''
  SUBSYSTEM==&quot;net&quot;, ACTION==&quot;add&quot;, DRIVERS==&quot;?*&quot;, \
  ATTR{address}==&quot;52:54:00:12:01:01&quot;, KERNEL==&quot;eth*&quot;, NAME=&quot;wan&quot;
'';
</programlisting>
    <warning>
      <para>
        The rule must be installed in the initrd using
        <literal>services.udev.initrdRules</literal>, not the usual
        <literal>services.udev.extraRules</literal> option. This is to
        avoid race conditions with other programs controlling the
        interface.
      </para>
    </warning>
  </section>
</section>
