diff --git a/nixos/doc/manual/configuration/networking.xml b/nixos/doc/manual/configuration/networking.xml index 02cf811e0bd..8369e9c9c85 100644 --- a/nixos/doc/manual/configuration/networking.xml +++ b/nixos/doc/manual/configuration/networking.xml @@ -15,5 +15,6 @@ + diff --git a/nixos/doc/manual/configuration/renaming-interfaces.xml b/nixos/doc/manual/configuration/renaming-interfaces.xml new file mode 100644 index 00000000000..d760bb3a4da --- /dev/null +++ b/nixos/doc/manual/configuration/renaming-interfaces.xml @@ -0,0 +1,67 @@ +
+ Renaming network interfaces + + + NixOS uses the udev + predictable naming scheme + to assign names to network interfaces. This means that by default + cards are not given the traditional names like + eth0 or eth1, whose order can + change unpredictably across reboots. Instead, relying on physical + locations and firmware information, the scheme produces names like + ens1, enp2s0, etc. + + + + These names are predictable but less memorable and not necessarily + stable: for example installing new hardware or changing firmware + settings can result in a + name change. + If this is undesirable, for example if you have a single ethernet + card, you can revert to the traditional scheme by setting + to + false. + + +
+ Assigning custom names + + 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 wan to the interface + with MAC address 52:54:00:12:01:01 using a + netword link unit: + + + systemd.network.links."10-wan" = { + matchConfig.MACAddress = "52:54:00:12:01:01"; + linkConfig.Name = "wan"; + }; + + + Note that links are directly read by udev, not networkd, + and will work even if networkd is disabled. + + + Alternatively, we can use a plain old udev rule: + + + services.udev.initrdRules = '' + SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", \ + ATTR{address}=="52:54:00:12:01:01", KERNEL=="eth*", NAME="wan" + ''; + + + + The rule must be installed in the initrd using + services.udev.initrdRules, not the usual + services.udev.extraRules option. This is to avoid race + conditions with other programs controlling the interface. + +
+ +
diff --git a/nixos/doc/manual/release-notes/rl-2105.xml b/nixos/doc/manual/release-notes/rl-2105.xml index 3760c52d363..9894ab02500 100644 --- a/nixos/doc/manual/release-notes/rl-2105.xml +++ b/nixos/doc/manual/release-notes/rl-2105.xml @@ -91,6 +91,16 @@ + + + If you are using to assign + custom names to network interfaces, this may stop working due to a change + in the initialisation of dhcpcd and systemd networkd. To avoid this, either + move them to or see the new + Assigning custom names section + of the NixOS manual for an example using networkd links. + + The systemConfig kernel parameter is no longer added to boot loader entries. It has been unused since September 2010, but if do have a system generation from that era, you will now be unable to boot into them. diff --git a/nixos/modules/services/hardware/udev.nix b/nixos/modules/services/hardware/udev.nix index 63027f7744d..d48b5444677 100644 --- a/nixos/modules/services/hardware/udev.nix +++ b/nixos/modules/services/hardware/udev.nix @@ -202,12 +202,26 @@ in ''; }; - extraRules = mkOption { + initrdRules = mkOption { default = ""; example = '' SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="00:1D:60:B9:6D:4F", KERNEL=="eth*", NAME="my_fast_network_card" ''; type = types.lines; + description = '' + udev rules to include in the initrd + only. They'll be written into file + 99-local.rules. Thus they are read and applied + after the essential initrd rules. + ''; + }; + + extraRules = mkOption { + default = ""; + example = '' + ENV{ID_VENDOR_ID}=="046d", ENV{ID_MODEL_ID}=="0825", ENV{PULSE_IGNORE}="1" + ''; + type = types.lines; description = '' Additional udev rules. They'll be written into file 99-local.rules. Thus they are @@ -284,6 +298,13 @@ in boot.kernelParams = mkIf (!config.networking.usePredictableInterfaceNames) [ "net.ifnames=0" ]; + boot.initrd.extraUdevRulesCommands = optionalString (cfg.initrdRules != "") + '' + cat <<'EOF' > $out/99-local.rules + ${cfg.initrdRules} + EOF + ''; + environment.etc = { "udev/rules.d".source = udevRules; diff --git a/nixos/modules/services/networking/dhcpcd.nix b/nixos/modules/services/networking/dhcpcd.nix index d10bffd9147..31e4b6ad298 100644 --- a/nixos/modules/services/networking/dhcpcd.nix +++ b/nixos/modules/services/networking/dhcpcd.nix @@ -191,9 +191,8 @@ in { description = "DHCP Client"; wantedBy = [ "multi-user.target" ] ++ optional (!hasDefaultGatewaySet) "network-online.target"; - wants = [ "network.target" "systemd-udev-settle.service" ]; + wants = [ "network.target" ]; before = [ "network-online.target" ]; - after = [ "systemd-udev-settle.service" ]; restartTriggers = [ exitHook ]; diff --git a/nixos/modules/system/boot/networkd.nix b/nixos/modules/system/boot/networkd.nix index 3b01bc00baf..914d3e62eb4 100644 --- a/nixos/modules/system/boot/networkd.nix +++ b/nixos/modules/system/boot/networkd.nix @@ -1553,9 +1553,6 @@ in wantedBy = [ "multi-user.target" ]; aliases = [ "dbus-org.freedesktop.network1.service" ]; restartTriggers = map (x: x.source) (attrValues unitFiles); - # prevent race condition with interface renaming (#39069) - requires = [ "systemd-udev-settle.service" ]; - after = [ "systemd-udev-settle.service" ]; }; systemd.services.systemd-networkd-wait-online = { diff --git a/nixos/modules/system/boot/stage-1.nix b/nixos/modules/system/boot/stage-1.nix index 44287f3cf09..4074f2e0235 100644 --- a/nixos/modules/system/boot/stage-1.nix +++ b/nixos/modules/system/boot/stage-1.nix @@ -205,13 +205,22 @@ let ''; # */ + # Networkd link files are used early by udev to set up interfaces early. + # This must be done in stage 1 to avoid race conditions between udev and + # network daemons. linkUnits = pkgs.runCommand "link-units" { allowedReferences = [ extraUtils ]; preferLocalBuild = true; - } '' + } ('' mkdir -p $out cp -v ${udev}/lib/systemd/network/*.link $out/ - ''; + '' + ( + let + links = filterAttrs (n: v: hasSuffix ".link" n) config.systemd.network.units; + files = mapAttrsToList (n: v: "${v.unit}/${n}") links; + in + concatMapStringsSep "\n" (file: "cp -v ${file} $out/") files + )); udevRules = pkgs.runCommand "udev-rules" { allowedReferences = [ extraUtils ]; diff --git a/nixos/tests/networking.nix b/nixos/tests/networking.nix index 58adab9d40a..1ea61f99a95 100644 --- a/nixos/tests/networking.nix +++ b/nixos/tests/networking.nix @@ -672,6 +672,30 @@ let ), "The IPv6 routing table has not been properly cleaned:\n{}".format(ipv6Residue) ''; }; + rename = { + name = "RenameInterface"; + machine = { pkgs, ... }: { + virtualisation.vlans = [ 1 ]; + networking = { + useNetworkd = networkd; + useDHCP = false; + }; + } // + (if networkd + then { systemd.network.links."10-custom_name" = { + matchConfig.MACAddress = "52:54:00:12:01:01"; + linkConfig.Name = "custom_name"; + }; + } + else { services.udev.initrdRules = '' + SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="52:54:00:12:01:01", KERNEL=="eth*", NAME="custom_name" + ''; + }); + testScript = '' + machine.succeed("udevadm settle") + print(machine.succeed("ip link show dev custom_name")) + ''; + }; # even with disabled networkd, systemd.network.links should work # (as it's handled by udev, not networkd) link = {