diff --git a/lib/tests/modules.sh b/lib/tests/modules.sh index 65de8e378c7e..e0774383720b 100755 --- a/lib/tests/modules.sh +++ b/lib/tests/modules.sh @@ -115,6 +115,11 @@ set -- config.enable ./declare-enable.nix ./define-enable.nix ./define-loaOfSub- checkConfigError 'The option .* defined in .* does not exist.' "$@" checkConfigOutput "true" "$@" ./define-module-check.nix +# Check coerced value. +checkConfigOutput "\"42\"" config.value ./declare-coerced-value.nix +checkConfigOutput "\"24\"" config.value ./declare-coerced-value.nix ./define-value-string.nix +checkConfigError 'The option value .* in .* is not a coercedTo.' config.value ./declare-coerced-value.nix ./define-value-list.nix + cat < +As with IPv4 networking interfaces are automatically configured via +DHCPv6. You can configure an interface manually: + + +networking.interfaces.eth0.ip6 = [ { address = "fe00:aa:bb:cc::2"; prefixLength = 64; } ]; + + + +For configuring a gateway, optionally with explicitly specified interface: + + +networking.defaultGateway6 = { + address = "fe00::1"; + interface = "enp0s3"; +} + + + +See for similar examples and additional information. + diff --git a/nixos/modules/tasks/network-interfaces-scripted.nix b/nixos/modules/tasks/network-interfaces-scripted.nix index c50ea5c79643..aa86fc85feb6 100644 --- a/nixos/modules/tasks/network-interfaces-scripted.nix +++ b/nixos/modules/tasks/network-interfaces-scripted.nix @@ -102,17 +102,21 @@ in EOF # Set the default gateway. - ${optionalString (cfg.defaultGateway != null && cfg.defaultGateway != "") '' + ${optionalString (cfg.defaultGateway != null && cfg.defaultGateway.address != "") '' # FIXME: get rid of "|| true" (necessary to make it idempotent). - ip route add default via "${cfg.defaultGateway}" ${ + ip route add default via "${cfg.defaultGateway.address}" ${ optionalString (cfg.defaultGatewayWindowSize != null) - "window ${toString cfg.defaultGatewayWindowSize}"} || true + "window ${toString cfg.defaultGatewayWindowSize}"} ${ + optionalString (cfg.defaultGateway.interface != null) + "dev ${cfg.defaultGateway.interface}"}|| true ''} - ${optionalString (cfg.defaultGateway6 != null && cfg.defaultGateway6 != "") '' + ${optionalString (cfg.defaultGateway6 != null && cfg.defaultGateway6.address != "") '' # FIXME: get rid of "|| true" (necessary to make it idempotent). - ip -6 route add ::/0 via "${cfg.defaultGateway6}" ${ + ip -6 route add ::/0 via "${cfg.defaultGateway6.address}" ${ optionalString (cfg.defaultGatewayWindowSize != null) - "window ${toString cfg.defaultGatewayWindowSize}"} || true + "window ${toString cfg.defaultGatewayWindowSize}"} ${ + optionalString (cfg.defaultGateway6.interface != null) + "dev ${cfg.defaultGateway6.interface}"} || true ''} ''; }; diff --git a/nixos/modules/tasks/network-interfaces-systemd.nix b/nixos/modules/tasks/network-interfaces-systemd.nix index 974041d7e1a5..a1212c905560 100644 --- a/nixos/modules/tasks/network-interfaces-systemd.nix +++ b/nixos/modules/tasks/network-interfaces-systemd.nix @@ -38,6 +38,12 @@ in } { assertion = cfg.vswitches == {}; message = "networking.vswichtes are not supported by networkd."; + } { + assertion = cfg.defaultGateway == null || cfg.defaultGateway.interface == null; + message = "networking.defaultGateway.interface is not supported by networkd."; + } { + assertion = cfg.defaultGateway6 == null || cfg.defaultGateway6.interface == null; + message = "networking.defaultGateway6.interface is not supported by networkd."; } ] ++ flip mapAttrsToList cfg.bridges (n: { rstp, ... }: { assertion = !rstp; message = "networking.bridges.${n}.rstp is not supported by networkd."; diff --git a/nixos/modules/tasks/network-interfaces.nix b/nixos/modules/tasks/network-interfaces.nix index 83d9854d3517..3f56419d2a6d 100644 --- a/nixos/modules/tasks/network-interfaces.nix +++ b/nixos/modules/tasks/network-interfaces.nix @@ -116,6 +116,28 @@ let }; }; + gatewayCoerce = address: { inherit address; }; + + gatewayOpts = { ... }: { + + options = { + + address = mkOption { + type = types.str; + description = "The default gateway address."; + }; + + interface = mkOption { + type = types.nullOr types.str; + default = null; + example = "enp0s3"; + description = "The default gateway interface."; + }; + + }; + + }; + interfaceOpts = { name, ... }: { options = { @@ -327,19 +349,27 @@ in networking.defaultGateway = mkOption { default = null; - example = "131.211.84.1"; - type = types.nullOr types.str; + example = { + address = "131.211.84.1"; + device = "enp3s0"; + }; + type = types.nullOr (types.coercedTo types.str gatewayCoerce (types.submodule gatewayOpts)); description = '' - The default gateway. It can be left empty if it is auto-detected through DHCP. + The default gateway. It can be left empty if it is auto-detected through DHCP. + It can be specified as a string or an option set along with a network interface. ''; }; networking.defaultGateway6 = mkOption { default = null; - example = "2001:4d0:1e04:895::1"; - type = types.nullOr types.str; + example = { + address = "2001:4d0:1e04:895::1"; + device = "enp3s0"; + }; + type = types.nullOr (types.coercedTo types.str gatewayCoerce (types.submodule gatewayOpts)); description = '' - The default ipv6 gateway. It can be left empty if it is auto-detected through DHCP. + The default ipv6 gateway. It can be left empty if it is auto-detected through DHCP. + It can be specified as a string or an option set along with a network interface. ''; };