Unverified Commit c4fd7cf1 authored by Maximilian Bosch's avatar Maximilian Bosch
Browse files

nixos/networkd: get rid of *Config attributes in lists

This patch is about removing `wireguardPeerConfig`,
`dhcpServerStaticLeaseConfig` - a.k.a. the
AbstractSingletonProxyFactoryBean of nixpkgs - and friends.

As a former colleague said

> worst abstraction ever

I second that. I've written enough networkd config for NixOS systems so
far to have a strong dislike. In fact, these don't even make sense:
`netdevs.wireguardPeers._.wireguardPeerConfig` will be rendered into
the key `[WireGuardPeer]` and every key from `wireguardPeerConfig` is in
there. Since it's INI, there's no place where sections on the same level
as wireguardPeerConfig fit into. Hence, get rid of it all.

For the transition, using the old way is still allowed, but gives a
warning. I think we could drop this after one release.

The tests of rosenpass and systemd-networkd-dhcpserver-static-leases
were broken on the rev before, hence they were updated, but are still
not building.
parent 805191d9
Loading
Loading
Loading
Loading
+24 −0
Original line number Diff line number Diff line
@@ -182,6 +182,30 @@ in rec {
  in if errors == [] then true
     else trace (concatStringsSep "\n" errors) false;

  checkUnitConfigWithLegacyKey = legacyKey: group: checks: attrs:
    let
      dump = lib.generators.toPretty { }
        (lib.generators.withRecursion { depthLimit = 2; throwOnDepthLimit = false; } attrs);
      attrs' =
        if legacyKey == null
          then attrs
        else if ! attrs?${legacyKey}
          then attrs
        else if removeAttrs attrs [ legacyKey ] == {}
          then attrs.${legacyKey}
        else throw ''
          The declaration

          ${dump}

          must not mix unit options with the legacy key '${legacyKey}'.

          This can be fixed by moving all settings from within ${legacyKey}
          one level up.
        '';
    in
    checkUnitConfig group checks attrs';

  toOption = x:
    if x == true then "true"
    else if x == false then "false"
+11 −11
Original line number Diff line number Diff line
@@ -63,13 +63,13 @@ in {
      ${attrsToSection def.l2tpConfig}
    '' + flip concatMapStrings def.l2tpSessions (x: ''
      [L2TPSession]
      ${attrsToSection x.l2tpSessionConfig}
      ${attrsToSection x}
    '') + optionalString (def.wireguardConfig != { }) ''
      [WireGuard]
      ${attrsToSection def.wireguardConfig}
    '' + flip concatMapStrings def.wireguardPeers (x: ''
      [WireGuardPeer]
      ${attrsToSection x.wireguardPeerConfig}
      ${attrsToSection x}
    '') + optionalString (def.bondConfig != { }) ''
      [Bond]
      ${attrsToSection def.bondConfig}
@@ -122,13 +122,13 @@ in {
      ${concatStringsSep "\n" (map (s: "Xfrm=${s}") def.xfrm)}
    '' + "\n" + flip concatMapStrings def.addresses (x: ''
      [Address]
      ${attrsToSection x.addressConfig}
      ${attrsToSection x}
    '') + flip concatMapStrings def.routingPolicyRules (x: ''
      [RoutingPolicyRule]
      ${attrsToSection x.routingPolicyRuleConfig}
      ${attrsToSection x}
    '') + flip concatMapStrings def.routes (x: ''
      [Route]
      ${attrsToSection x.routeConfig}
      ${attrsToSection x}
    '') + optionalString (def.dhcpV4Config != { }) ''
      [DHCPv4]
      ${attrsToSection def.dhcpV4Config}
@@ -149,22 +149,22 @@ in {
      ${attrsToSection def.ipv6SendRAConfig}
    '' + flip concatMapStrings def.ipv6Prefixes (x: ''
      [IPv6Prefix]
      ${attrsToSection x.ipv6PrefixConfig}
      ${attrsToSection x}
    '') + flip concatMapStrings def.ipv6RoutePrefixes (x: ''
      [IPv6RoutePrefix]
      ${attrsToSection x.ipv6RoutePrefixConfig}
      ${attrsToSection x}
    '') + flip concatMapStrings def.dhcpServerStaticLeases (x: ''
      [DHCPServerStaticLease]
      ${attrsToSection x.dhcpServerStaticLeaseConfig}
      ${attrsToSection x}
    '') + optionalString (def.bridgeConfig != { }) ''
      [Bridge]
      ${attrsToSection def.bridgeConfig}
    '' + flip concatMapStrings def.bridgeFDBs (x: ''
      [BridgeFDB]
      ${attrsToSection x.bridgeFDBConfig}
      ${attrsToSection x}
    '') + flip concatMapStrings def.bridgeMDBs (x: ''
      [BridgeMDB]
      ${attrsToSection x.bridgeMDBConfig}
      ${attrsToSection x}
    '') + optionalString (def.lldpConfig != { }) ''
      [LLDP]
      ${attrsToSection def.lldpConfig}
@@ -251,7 +251,7 @@ in {
      ${attrsToSection def.quickFairQueueingConfigClass}
    '' + flip concatMapStrings def.bridgeVLANs (x: ''
      [BridgeVLAN]
      ${attrsToSection x.bridgeVLANConfig}
      ${attrsToSection x}
    '') + def.extraConfig;

}
+2 −2
Original line number Diff line number Diff line
@@ -130,8 +130,8 @@ in
            relevant = config.systemd.network.enable;
            root = config.systemd.network.netdevs;
            peer = (x: x.wireguardPeers);
            key = (x: if x.wireguardPeerConfig ? PublicKey then x.wireguardPeerConfig.PublicKey else null);
            description = "${options.systemd.network.netdevs}.\"<name>\".wireguardPeers.*.wireguardPeerConfig.PublicKey";
            key = x: x.PublicKey or null;
            description = "${options.systemd.network.netdevs}.\"<name>\".wireguardPeers.*.PublicKey";
          }
          {
            relevant = config.networking.wireguard.enable;
+49 −196
Original line number Diff line number Diff line
@@ -386,7 +386,7 @@ let
        (assertValueOneOf "UDP6ZeroChecksumRx" boolValues)
      ];

      sectionL2TPSession = checkUnitConfig "L2TPSession" [
      sectionL2TPSession = checkUnitConfigWithLegacyKey "l2tpSessionConfig" "L2TPSession" [
        (assertOnlyFields [
          "Name"
          "SessionId"
@@ -421,7 +421,7 @@ let
      # NOTE The PresharedKey directive is missing on purpose here, please
      # do not add it to this list. The nix store is world-readable,let's
      # refrain ourselves from providing a footgun.
      sectionWireGuardPeer = checkUnitConfig "WireGuardPeer" [
      sectionWireGuardPeer = checkUnitConfigWithLegacyKey "wireguardPeerConfig" "WireGuardPeer" [
        (assertOnlyFields [
          "PublicKey"
          "PresharedKeyFile"
@@ -712,7 +712,7 @@ let
        (assertValueOneOf "KeepConfiguration" (boolValues ++ ["static" "dhcp-on-stop" "dhcp"]))
      ];

      sectionAddress = checkUnitConfig "Address" [
      sectionAddress = checkUnitConfigWithLegacyKey "addressConfig" "Address" [
        (assertOnlyFields [
          "Address"
          "Peer"
@@ -737,7 +737,7 @@ let
        (assertValueOneOf "AutoJoin" boolValues)
      ];

      sectionRoutingPolicyRule = checkUnitConfig "RoutingPolicyRule" [
      sectionRoutingPolicyRule = checkUnitConfigWithLegacyKey "routingPolicyRuleConfig" "RoutingPolicyRule" [
        (assertOnlyFields [
          "TypeOfService"
          "From"
@@ -772,7 +772,7 @@ let
        (assertRange "SuppressInterfaceGroup" 0 2147483647)
      ];

      sectionRoute = checkUnitConfig "Route" [
      sectionRoute = checkUnitConfigWithLegacyKey "routeConfig" "Route" [
        (assertOnlyFields [
          "Gateway"
          "GatewayOnLink"
@@ -1033,7 +1033,7 @@ let
        (assertValueOneOf "EmitDomains" boolValues)
      ];

      sectionIPv6Prefix = checkUnitConfig "IPv6Prefix" [
      sectionIPv6Prefix = checkUnitConfigWithLegacyKey "ipv6PrefixConfig" "IPv6Prefix" [
        (assertOnlyFields [
          "AddressAutoconfiguration"
          "OnLink"
@@ -1048,7 +1048,7 @@ let
        (assertValueOneOf "Assign" boolValues)
      ];

      sectionIPv6RoutePrefix = checkUnitConfig "IPv6RoutePrefix" [
      sectionIPv6RoutePrefix = checkUnitConfigWithLegacyKey "ipv6RoutePrefixConfig" "IPv6RoutePrefix" [
        (assertOnlyFields [
          "Route"
          "LifetimeSec"
@@ -1057,7 +1057,7 @@ let
        (assertInt "LifetimeSec")
      ];

      sectionDHCPServerStaticLease = checkUnitConfig "DHCPServerStaticLease" [
      sectionDHCPServerStaticLease = checkUnitConfigWithLegacyKey "dhcpServerStaticLeaseConfig" "DHCPServerStaticLease" [
        (assertOnlyFields [
          "MACAddress"
          "Address"
@@ -1104,7 +1104,7 @@ let
        (assertRange "Priority" 0 63)
      ];

      sectionBridgeFDB = checkUnitConfig "BridgeFDB" [
      sectionBridgeFDB = checkUnitConfigWithLegacyKey "bridgeFDBConfig" "BridgeFDB" [
        (assertOnlyFields [
          "MACAddress"
          "Destination"
@@ -1121,7 +1121,7 @@ let
        (assertValueOneOf "AssociatedWith" [ "use" "self" "master" "router" ])
      ];

      sectionBridgeMDB = checkUnitConfig "BridgeMDB" [
      sectionBridgeMDB = checkUnitConfigWithLegacyKey "bridgeMDBConfig" "BridgeMDB" [
        (assertOnlyFields [
          "MulticastGroupAddress"
          "VLANId"
@@ -1524,7 +1524,7 @@ let
        (assertRange "Weight" 1 1023)
      ];

      sectionBridgeVLAN = checkUnitConfig "BridgeVLAN" [
      sectionBridgeVLAN = checkUnitConfigWithLegacyKey "bridgeVLANConfig" "BridgeVLAN" [
        (assertOnlyFields [
          "VLAN"
          "EgressUntagged"
@@ -1627,33 +1627,20 @@ let

  };


  l2tpSessionOptions = {
    options = {
      l2tpSessionConfig = mkOption {
        default = {};
        type = types.addCheck (types.attrsOf unitOption) check.netdev.sectionL2TPSession;
        description = ''
          Each attribute in this set specifies an option in the
          `[L2TPSession]` section of the unit.  See
          {manpage}`systemd.netdev(5)` for details.
        '';
      };
    };
  };

  wireguardPeerOptions = {
    options = {
      wireguardPeerConfig = mkOption {
        default = {};
        type = types.addCheck (types.attrsOf unitOption) check.netdev.sectionWireGuardPeer;
        description = ''
          Each attribute in this set specifies an option in the
          `[WireGuardPeer]` section of the unit.  See
          {manpage}`systemd.netdev(5)` for details.
        '';
      };
    };
  mkSubsectionType = oldKey: checkF:
    let
      type = types.addCheck (types.attrsOf unitOption) checkF;
    in type // {
      merge = loc: defs:
        let
          final = type.merge loc defs;
        in
        if final?${oldKey}
          then warn
            "Using '${oldKey}' is deprecated! Move all attributes inside one level up and remove it."
            final.${oldKey}
        else
          final;
    };

  netdevOptions = commonNetworkOptions // {
@@ -1805,12 +1792,12 @@ let

    l2tpSessions = mkOption {
      default = [];
      example = [ { l2tpSessionConfig={
      example = [ {
        SessionId = 25;
        PeerSessionId = 26;
        Name = "l2tp-sess";
      };}];
      type = with types; listOf (submodule l2tpSessionOptions);
      }];
      type = types.listOf (mkSubsectionType "l2tpSessionConfig" check.netdev.sectionL2TPSession);
      description = ''
        Each item in this array specifies an option in the
        `[L2TPSession]` section of the unit. See
@@ -1838,14 +1825,14 @@ let

    wireguardPeers = mkOption {
      default = [];
      example = [ { wireguardPeerConfig={
      example = [ {
        Endpoint = "192.168.1.1:51820";
        PublicKey = "27s0OvaBBdHoJYkH9osZpjpgSOVNw+RaKfboT/Sfq0g=";
        PresharedKeyFile = "/etc/wireguard/psk.key";
        AllowedIPs = [ "10.0.0.1/32" ];
        PersistentKeepalive = 15;
      };}];
      type = with types; listOf (submodule wireguardPeerOptions);
      } ];
      type = types.listOf (mkSubsectionType "wireguardPeerConfig" check.netdev.sectionWireGuardPeer);
      description = ''
        Each item in this array specifies an option in the
        `[WireGuardPeer]` section of the unit. See
@@ -1917,143 +1904,6 @@ let

  };

  addressOptions = {
    options = {
      addressConfig = mkOption {
        example = { Address = "192.168.0.100/24"; };
        type = types.addCheck (types.attrsOf unitOption) check.network.sectionAddress;
        description = ''
          Each attribute in this set specifies an option in the
          `[Address]` section of the unit.  See
          {manpage}`systemd.network(5)` for details.
        '';
      };
    };
  };

  routingPolicyRulesOptions = {
    options = {
      routingPolicyRuleConfig = mkOption {
        default = { };
        example = { Table = 10; IncomingInterface = "eth1"; Family = "both"; };
        type = types.addCheck (types.attrsOf unitOption) check.network.sectionRoutingPolicyRule;
        description = ''
          Each attribute in this set specifies an option in the
          `[RoutingPolicyRule]` section of the unit.  See
          {manpage}`systemd.network(5)` for details.
        '';
      };
    };
  };

  routeOptions = {
    options = {
      routeConfig = mkOption {
        default = {};
        example = { Gateway = "192.168.0.1"; };
        type = types.addCheck (types.attrsOf unitOption) check.network.sectionRoute;
        description = ''
          Each attribute in this set specifies an option in the
          `[Route]` section of the unit.  See
          {manpage}`systemd.network(5)` for details.
        '';
      };
    };
  };

  ipv6PrefixOptions = {
    options = {
      ipv6PrefixConfig = mkOption {
        default = {};
        example = { Prefix = "fd00::/64"; };
        type = types.addCheck (types.attrsOf unitOption) check.network.sectionIPv6Prefix;
        description = ''
          Each attribute in this set specifies an option in the
          `[IPv6Prefix]` section of the unit.  See
          {manpage}`systemd.network(5)` for details.
        '';
      };
    };
  };

  ipv6RoutePrefixOptions = {
    options = {
      ipv6RoutePrefixConfig = mkOption {
        default = {};
        example = { Route = "fd00::/64"; };
        type = types.addCheck (types.attrsOf unitOption) check.network.sectionIPv6RoutePrefix;
        description = ''
          Each attribute in this set specifies an option in the
          `[IPv6RoutePrefix]` section of the unit.  See
          {manpage}`systemd.network(5)` for details.
        '';
      };
    };
  };

  dhcpServerStaticLeaseOptions = {
    options = {
      dhcpServerStaticLeaseConfig = mkOption {
        default = {};
        example = { MACAddress = "65:43:4a:5b:d8:5f"; Address = "192.168.1.42"; };
        type = types.addCheck (types.attrsOf unitOption) check.network.sectionDHCPServerStaticLease;
        description = ''
          Each attribute in this set specifies an option in the
          `[DHCPServerStaticLease]` section of the unit.  See
          {manpage}`systemd.network(5)` for details.

          Make sure to configure the corresponding client interface to use
          `ClientIdentifier=mac`.
        '';
      };
    };
  };

  bridgeFDBOptions = {
    options = {
      bridgeFDBConfig = mkOption {
        default = {};
        example = { MACAddress = "65:43:4a:5b:d8:5f"; Destination = "192.168.1.42"; VNI = 20; };
        type = types.addCheck (types.attrsOf unitOption) check.network.sectionBridgeFDB;
        description = ''
          Each attribute in this set specifies an option in the
          `[BridgeFDB]` section of the unit.  See
          {manpage}`systemd.network(5)` for details.
        '';
      };
    };
  };

  bridgeMDBOptions = {
    options = {
      bridgeMDBConfig = mkOption {
        default = {};
        example = { MulticastGroupAddress = "ff02::1:2:3:4"; VLANId = 10; };
        type = types.addCheck (types.attrsOf unitOption) check.network.sectionBridgeMDB;
        description = ''
          Each attribute in this set specifies an option in the
          `[BridgeMDB]` section of the unit.  See
          {manpage}`systemd.network(5)` for details.
        '';
      };
    };
  };

  bridgeVLANOptions = {
    options = {
      bridgeVLANConfig = mkOption {
        default = {};
        example = { VLAN = 20; };
        type = types.addCheck (types.attrsOf unitOption) check.network.sectionBridgeVLAN;
        description = ''
          Each attribute in this set specifies an option in the
          `[BridgeVLAN]` section of the unit.  See
          {manpage}`systemd.network(5)` for details.
        '';
      };
    };
  };

  networkOptions = commonNetworkOptions // {

    linkConfig = mkOption {
@@ -2165,8 +2015,8 @@ let

    dhcpServerStaticLeases = mkOption {
      default = [];
      example = [ { dhcpServerStaticLeaseConfig = { MACAddress = "65:43:4a:5b:d8:5f"; Address = "192.168.1.42"; }; } ];
      type = with types; listOf (submodule dhcpServerStaticLeaseOptions);
      example = [ { MACAddress = "65:43:4a:5b:d8:5f"; Address = "192.168.1.42"; } ];
      type = types.listOf (mkSubsectionType "dhcpServerStaticLeaseConfig" check.network.sectionDHCPServerStaticLease);
      description = ''
        A list of DHCPServerStaticLease sections to be added to the unit.  See
        {manpage}`systemd.network(5)` for details.
@@ -2175,8 +2025,8 @@ let

    ipv6Prefixes = mkOption {
      default = [];
      example = [ { ipv6PrefixConfig = { AddressAutoconfiguration = true; OnLink = true; }; } ];
      type = with types; listOf (submodule ipv6PrefixOptions);
      example = [ { AddressAutoconfiguration = true; OnLink = true; } ];
      type = types.listOf (mkSubsectionType "ipv6PrefixConfig" check.network.sectionIPv6Prefix);
      description = ''
        A list of ipv6Prefix sections to be added to the unit.  See
        {manpage}`systemd.network(5)` for details.
@@ -2185,8 +2035,8 @@ let

    ipv6RoutePrefixes = mkOption {
      default = [];
      example = [ { ipv6RoutePrefixConfig = { Route = "fd00::/64"; LifetimeSec = 3600; }; } ];
      type = with types; listOf (submodule ipv6RoutePrefixOptions);
      example = [ { Route = "fd00::/64"; LifetimeSec = 3600; } ];
      type = types.listOf (mkSubsectionType "ipv6RoutePrefixConfig" check.network.sectionIPv6RoutePrefix);
      description = ''
        A list of ipv6RoutePrefix sections to be added to the unit.  See
        {manpage}`systemd.network(5)` for details.
@@ -2206,8 +2056,8 @@ let

    bridgeFDBs = mkOption {
      default = [];
      example = [ { bridgeFDBConfig = { MACAddress = "90:e2:ba:43:fc:71"; Destination = "192.168.100.4"; VNI = 3600; }; } ];
      type = with types; listOf (submodule bridgeFDBOptions);
      example = [ { MACAddress = "90:e2:ba:43:fc:71"; Destination = "192.168.100.4"; VNI = 3600; } ];
      type = types.listOf (mkSubsectionType "bridgeFDBConfig" check.network.sectionBridgeFDB);
      description = ''
        A list of BridgeFDB sections to be added to the unit.  See
        {manpage}`systemd.network(5)` for details.
@@ -2216,8 +2066,8 @@ let

    bridgeMDBs = mkOption {
      default = [];
      example = [ { bridgeMDBConfig = { MulticastGroupAddress = "ff02::1:2:3:4"; VLANId = 10; } ; } ];
      type = with types; listOf (submodule bridgeMDBOptions);
      example = [ { MulticastGroupAddress = "ff02::1:2:3:4"; VLANId = 10; } ];
      type = types.listOf (mkSubsectionType "bridgeMDBConfig" check.network.sectionBridgeMDB);
      description = ''
        A list of BridgeMDB sections to be added to the unit.  See
        {manpage}`systemd.network(5)` for details.
@@ -2534,8 +2384,8 @@ let

    bridgeVLANs = mkOption {
      default = [];
      example = [ { bridgeVLANConfig = { VLAN = "10-20"; }; } ];
      type = with types; listOf (submodule bridgeVLANOptions);
      example = [ { VLAN = "10-20"; } ];
      type = types.listOf (mkSubsectionType "bridgeVLANConfig" check.network.sectionBridgeVLAN);
      description = ''
        A list of BridgeVLAN sections to be added to the unit.  See
        {manpage}`systemd.network(5)` for details.
@@ -2685,7 +2535,8 @@ let

    addresses = mkOption {
      default = [ ];
      type = with types; listOf (submodule addressOptions);
      example = [ { Address = "192.168.0.100/24"; } ];
      type = types.listOf (mkSubsectionType "addressConfig" check.network.sectionAddress);
      description = ''
        A list of address sections to be added to the unit.  See
        {manpage}`systemd.network(5)` for details.
@@ -2694,7 +2545,8 @@ let

    routingPolicyRules = mkOption {
      default = [ ];
      type = with types; listOf (submodule routingPolicyRulesOptions);
      example = [ { Table = 10; IncomingInterface = "eth1"; Family = "both"; } ];
      type = types.listOf (mkSubsectionType "routingPolicyRuleConfig" check.network.sectionRoutingPolicyRule);
      description = ''
        A list of routing policy rules sections to be added to the unit.  See
        {manpage}`systemd.network(5)` for details.
@@ -2703,7 +2555,8 @@ let

    routes = mkOption {
      default = [ ];
      type = with types; listOf (submodule routeOptions);
      example = [ { Gateway = "192.168.0.1"; } ];
      type = types.listOf (mkSubsectionType "routeConfig" check.network.sectionRoute);
      description = ''
        A list of route sections to be added to the unit.  See
        {manpage}`systemd.network(5)` for details.
+59 −61
Original line number Diff line number Diff line
@@ -32,13 +32,13 @@ let
    optionalAttrs (gateway != null && gateway.interface != null) {
      networks."40-${gateway.interface}" = {
        matchConfig.Name = gateway.interface;
        routes = [{
          routeConfig = {
        routes = [
          ({
            Gateway = gateway.address;
          } // optionalAttrs (gateway.metric != null) {
            Metric = gateway.metric;
          };
        }];
          })
        ];
      };
    }
  ));
@@ -95,10 +95,9 @@ let
      address = forEach (interfaceIps i)
        (ip: "${ip.address}/${toString ip.prefixLength}");
      routes = forEach (interfaceRoutes i)
        (route: {
        (route:
          # Most of these route options have not been tested.
          # Please fix or report any mistakes you may find.
          routeConfig =
          optionalAttrs (route.address != null && route.prefixLength != null) {
            Destination = "${route.address}/${toString route.prefixLength}";
          } //
@@ -152,7 +151,6 @@ let
          } //
          optionalAttrs (route.options ? ttl-propagate) {
            TTLPropagate = route.options.ttl-propagate == "enabled";
            };
          });
      networkConfig.IPv6PrivacyExtensions = "kernel";
      linkConfig = optionalAttrs (i.macAddress != null) {
Loading