diff --git a/nixos/doc/manual/release-notes/rl-2003.xml b/nixos/doc/manual/release-notes/rl-2003.xml
index 0996791944f..3d83b526527 100644
--- a/nixos/doc/manual/release-notes/rl-2003.xml
+++ b/nixos/doc/manual/release-notes/rl-2003.xml
@@ -767,7 +767,15 @@ auth required pam_succeed_if.so uid >= 1000 quiet
-
+
+
+
+ The systemd.network.links option is now respected
+ even when systemd-networkd is disabled.
+ This mirrors the behaviour of systemd - It's udev that parses .link files,
+ not systemd-networkd.
+
+
diff --git a/nixos/modules/system/boot/networkd.nix b/nixos/modules/system/boot/networkd.nix
index 6dfbe66fc64..3078f84f6e9 100644
--- a/nixos/modules/system/boot/networkd.nix
+++ b/nixos/modules/system/boot/networkd.nix
@@ -355,6 +355,14 @@ let
};
linkOptions = commonNetworkOptions // {
+ # overwrite enable option from above
+ enable = mkOption {
+ default = true;
+ type = types.bool;
+ description = ''
+ Whether to enable this .link unit. It's handled by udev no matter if systemd-networkd is enabled or not
+ '';
+ };
linkConfig = mkOption {
default = {};
@@ -1045,44 +1053,49 @@ in
};
- config = mkIf config.systemd.network.enable {
+ config = mkMerge [
+ # .link units are honored by udev, no matter if systemd-networkd is enabled or not.
+ {
+ systemd.network.units = mapAttrs' (n: v: nameValuePair "${n}.link" (linkToUnit n v)) cfg.links;
+ environment.etc = unitFiles;
+ }
- users.users.systemd-network.group = "systemd-network";
+ (mkIf config.systemd.network.enable {
- systemd.additionalUpstreamSystemUnits = [
- "systemd-networkd.service" "systemd-networkd-wait-online.service"
- ];
+ users.users.systemd-network.group = "systemd-network";
- systemd.network.units = mapAttrs' (n: v: nameValuePair "${n}.link" (linkToUnit n v)) cfg.links
- // mapAttrs' (n: v: nameValuePair "${n}.netdev" (netdevToUnit n v)) cfg.netdevs
- // mapAttrs' (n: v: nameValuePair "${n}.network" (networkToUnit n v)) cfg.networks;
+ systemd.additionalUpstreamSystemUnits = [
+ "systemd-networkd.service" "systemd-networkd-wait-online.service"
+ ];
- environment.etc = unitFiles;
+ systemd.network.units = mapAttrs' (n: v: nameValuePair "${n}.netdev" (netdevToUnit n v)) cfg.netdevs
+ // mapAttrs' (n: v: nameValuePair "${n}.network" (networkToUnit n v)) cfg.networks;
- systemd.services.systemd-networkd = {
- wantedBy = [ "multi-user.target" ];
- restartTriggers = attrNames unitFiles;
- # prevent race condition with interface renaming (#39069)
- requires = [ "systemd-udev-settle.service" ];
- after = [ "systemd-udev-settle.service" ];
- };
-
- systemd.services.systemd-networkd-wait-online = {
- wantedBy = [ "network-online.target" ];
- };
-
- systemd.services."systemd-network-wait-online@" = {
- description = "Wait for Network Interface %I to be Configured";
- conflicts = [ "shutdown.target" ];
- requisite = [ "systemd-networkd.service" ];
- after = [ "systemd-networkd.service" ];
- serviceConfig = {
- Type = "oneshot";
- RemainAfterExit = true;
- ExecStart = "${config.systemd.package}/lib/systemd/systemd-networkd-wait-online -i %I";
+ systemd.services.systemd-networkd = {
+ wantedBy = [ "multi-user.target" ];
+ restartTriggers = attrNames unitFiles;
+ # prevent race condition with interface renaming (#39069)
+ requires = [ "systemd-udev-settle.service" ];
+ after = [ "systemd-udev-settle.service" ];
};
- };
- services.resolved.enable = mkDefault true;
- };
+ systemd.services.systemd-networkd-wait-online = {
+ wantedBy = [ "network-online.target" ];
+ };
+
+ systemd.services."systemd-network-wait-online@" = {
+ description = "Wait for Network Interface %I to be Configured";
+ conflicts = [ "shutdown.target" ];
+ requisite = [ "systemd-networkd.service" ];
+ after = [ "systemd-networkd.service" ];
+ serviceConfig = {
+ Type = "oneshot";
+ RemainAfterExit = true;
+ ExecStart = "${config.systemd.package}/lib/systemd/systemd-networkd-wait-online -i %I";
+ };
+ };
+
+ services.resolved.enable = mkDefault true;
+ })
+ ];
}
diff --git a/nixos/tests/networking.nix b/nixos/tests/networking.nix
index 933a4451af9..0a6507d2dc8 100644
--- a/nixos/tests/networking.nix
+++ b/nixos/tests/networking.nix
@@ -655,6 +655,31 @@ let
), "The IPv6 routing table has not been properly cleaned:\n{}".format(ipv6Residue)
'';
};
+ # even with disabled networkd, systemd.network.links should work
+ # (as it's handled by udev, not networkd)
+ link = {
+ name = "Link";
+ nodes.client = { pkgs, ... }: {
+ virtualisation.vlans = [ 1 ];
+ networking = {
+ useNetworkd = networkd;
+ useDHCP = false;
+ };
+ systemd.network.links."50-foo" = {
+ matchConfig = {
+ Name = "foo";
+ Driver = "dummy";
+ };
+ linkConfig.MTUBytes = "1442";
+ };
+ };
+ testScript = ''
+ print(client.succeed("ip l add name foo type dummy"))
+ print(client.succeed("stat /etc/systemd/network/50-foo.link"))
+ client.succeed("udevadm settle")
+ assert "mtu 1442" in client.succeed("ip l show dummy0")
+ '';
+ };
};
in mapAttrs (const (attrs: makeTest (attrs // {