diff --git a/nixos/modules/system/boot/systemd-unit-options.nix b/nixos/modules/system/boot/systemd-unit-options.nix
index 07f3cb9e952..b8d04953e9e 100644
--- a/nixos/modules/system/boot/systemd-unit-options.nix
+++ b/nixos/modules/system/boot/systemd-unit-options.nix
@@ -441,4 +441,321 @@ in rec {
targetOptions = commonUnitOptions;
+ commonNetworkOptions = {
+
+ enable = mkOption {
+ default = true;
+ type = types.bool;
+ description = ''
+ If set to false, this unit will be a symlink to
+ /dev/null.
+ '';
+ };
+
+ matchConfig = mkOption {
+ default = {};
+ example = { Name = "eth0"; };
+ type = types.attrsOf unitOption;
+ description = ''
+ Each attribute in this set specifies an option in the
+ [Match] section of the unit. See
+ systemd.link5
+ systemd.netdev5
+ systemd.network5
+ for details.
+ '';
+ };
+
+ };
+
+ linkOptions = commonNetworkOptions // {
+
+ linkConfig = mkOption {
+ default = {};
+ example = { MACAddress = "00:ff:ee:aa:cc:dd"; };
+ type = types.attrsOf unitOption;
+ description = ''
+ Each attribute in this set specifies an option in the
+ [Link] section of the unit. See
+ systemd.link
+ 5 for details.
+ '';
+ };
+
+ };
+
+ netdevOptions = commonNetworkOptions // {
+
+ netdevConfig = mkOption {
+ default = {};
+ example = { Name = "mybridge"; Kind = "bridge"; };
+ type = types.attrsOf unitOption;
+ description = ''
+ Each attribute in this set specifies an option in the
+ [Netdev] section of the unit. See
+ systemd.netdev
+ 5 for details.
+ '';
+ };
+
+ vlanConfig = mkOption {
+ default = {};
+ example = { Id = "4"; };
+ type = types.attrsOf unitOption;
+ description = ''
+ Each attribute in this set specifies an option in the
+ [VLAN] section of the unit. See
+ systemd.netdev
+ 5 for details.
+ '';
+ };
+
+ macvlanConfig = mkOption {
+ default = {};
+ example = { Mode = "private"; };
+ type = types.attrsOf unitOption;
+ description = ''
+ Each attribute in this set specifies an option in the
+ [MACVLAN] section of the unit. See
+ systemd.netdev
+ 5 for details.
+ '';
+ };
+
+ vxlanConfig = mkOption {
+ default = {};
+ example = { Id = "4"; };
+ type = types.attrsOf unitOption;
+ description = ''
+ Each attribute in this set specifies an option in the
+ [VXLAN] section of the unit. See
+ systemd.netdev
+ 5 for details.
+ '';
+ };
+
+ tunnelConfig = mkOption {
+ default = {};
+ example = { Remote = "192.168.1.1"; };
+ type = types.attrsOf unitOption;
+ description = ''
+ Each attribute in this set specifies an option in the
+ [Tunnel] section of the unit. See
+ systemd.netdev
+ 5 for details.
+ '';
+ };
+
+ peerConfig = mkOption {
+ default = {};
+ example = { Name = "veth2"; };
+ type = types.attrsOf unitOption;
+ description = ''
+ Each attribute in this set specifies an option in the
+ [Peer] section of the unit. See
+ systemd.netdev
+ 5 for details.
+ '';
+ };
+
+ tunConfig = mkOption {
+ default = {};
+ example = { User = "openvpn"; };
+ type = types.attrsOf unitOption;
+ description = ''
+ Each attribute in this set specifies an option in the
+ [Tun] section of the unit. See
+ systemd.netdev
+ 5 for details.
+ '';
+ };
+
+ tapConfig = mkOption {
+ default = {};
+ example = { User = "openvpn"; };
+ type = types.attrsOf unitOption;
+ description = ''
+ Each attribute in this set specifies an option in the
+ [Tap] section of the unit. See
+ systemd.netdev
+ 5 for details.
+ '';
+ };
+
+ bondConfig = mkOption {
+ default = {};
+ example = { Mode = "802.3ad"; };
+ type = types.attrsOf unitOption;
+ description = ''
+ Each attribute in this set specifies an option in the
+ [Bond] section of the unit. See
+ systemd.netdev
+ 5 for details.
+ '';
+ };
+
+ };
+
+ addressOptions = {
+
+ addressConfig = mkOption {
+ default = {};
+ example = { Address = "192.168.0.100/24"; };
+ type = types.attrsOf unitOption;
+ description = ''
+ Each attribute in this set specifies an option in the
+ [Address] section of the unit. See
+ systemd.network
+ 5 for details.
+ '';
+ };
+
+ };
+
+ routeOptions = {
+
+ routeConfig = mkOption {
+ default = {};
+ example = { Gateway = "192.168.0.1"; };
+ type = types.attrsOf unitOption;
+ description = ''
+ Each attribute in this set specifies an option in the
+ [Route] section of the unit. See
+ systemd.network
+ 5 for details.
+ '';
+ };
+
+ };
+
+ networkOptions = commonNetworkOptions // {
+
+ networkConfig = mkOption {
+ default = {};
+ example = { Description = "My Network"; };
+ type = types.attrsOf unitOption;
+ description = ''
+ Each attribute in this set specifies an option in the
+ [Network] section of the unit. See
+ systemd.network
+ 5 for details.
+ '';
+ };
+
+ dhcpConfig = mkOption {
+ default = {};
+ example = { UseDNS = true; UseRoutes = true; };
+ type = types.attrsOf unitOption;
+ description = ''
+ Each attribute in this set specifies an option in the
+ [DHCP] section of the unit. See
+ systemd.network
+ 5 for details.
+ '';
+ };
+
+ address = mkOption {
+ default = [ ];
+ type = types.listOf types.str;
+ description = ''
+ A list of addresses to be added to the network section of the
+ unit. See systemd.network
+ 5 for details.
+ '';
+ };
+
+ gateway = mkOption {
+ default = [ ];
+ type = types.listOf types.str;
+ description = ''
+ A list of gateways to be added to the network section of the
+ unit. See systemd.network
+ 5 for details.
+ '';
+ };
+
+ dns = mkOption {
+ default = [ ];
+ type = types.listOf types.str;
+ description = ''
+ A list of dns servers to be added to the network section of the
+ unit. See systemd.network
+ 5 for details.
+ '';
+ };
+
+ ntp = mkOption {
+ default = [ ];
+ type = types.listOf types.str;
+ description = ''
+ A list of ntp servers to be added to the network section of the
+ unit. See systemd.network
+ 5 for details.
+ '';
+ };
+
+ vlan = mkOption {
+ default = [ ];
+ type = types.listOf types.str;
+ description = ''
+ A list of vlan interfaces to be added to the network section of the
+ unit. See systemd.network
+ 5 for details.
+ '';
+ };
+
+ macvlan = mkOption {
+ default = [ ];
+ type = types.listOf types.str;
+ description = ''
+ A list of macvlan interfaces to be added to the network section of the
+ unit. See systemd.network
+ 5 for details.
+ '';
+ };
+
+ vxlan = mkOption {
+ default = [ ];
+ type = types.listOf types.str;
+ description = ''
+ A list of vxlan interfaces to be added to the network section of the
+ unit. See systemd.network
+ 5 for details.
+ '';
+ };
+
+ tunnel = mkOption {
+ default = [ ];
+ type = types.listOf types.str;
+ description = ''
+ A list of tunnel interfaces to be added to the network section of the
+ unit. See systemd.network
+ 5 for details.
+ '';
+ };
+
+ addresses = mkOption {
+ default = [ ];
+ type = types.listOf types.optionSet;
+ options = [ addressOptions ];
+ description = ''
+ A list of address sections to be added to the unit. See
+ systemd.network
+ 5 for details.
+ '';
+ };
+
+ routes = mkOption {
+ default = [ ];
+ type = types.listOf types.optionSet;
+ options = [ routeOptions ];
+ description = ''
+ A list of route sections to be added to the unit. See
+ systemd.network
+ 5 for details.
+ '';
+ };
+
+ };
+
}
diff --git a/nixos/modules/system/boot/systemd.nix b/nixos/modules/system/boot/systemd.nix
index 8a86149a9e1..a24edf2b191 100644
--- a/nixos/modules/system/boot/systemd.nix
+++ b/nixos/modules/system/boot/systemd.nix
@@ -96,6 +96,9 @@ let
"systemd-modules-load.service"
"kmod-static-nodes.service"
+ # Networking
+ "systemd-networkd.service"
+
# Filesystems.
"systemd-fsck@.service"
"systemd-fsck-root.service"
@@ -384,6 +387,103 @@ let
'';
};
+ commonMatchText = def: ''
+ [Match]
+ ${attrsToSection def.matchConfig}
+ '';
+
+ linkToUnit = name: def:
+ { inherit (def) enable;
+ text = commonMatchText def +
+ ''
+ [Link]
+ ${attrsToSection def.linkConfig}
+ '';
+ };
+
+ netdevToUnit = name: def:
+ { inherit (def) enable;
+ text = commonMatchText def +
+ ''
+ [NetDev]
+ ${attrsToSection def.netdevConfig}
+
+ ${optionalString (def.vlanConfig != { }) ''
+ [VLAN]
+ ${attrsToSection def.vlanConfig}
+
+ ''}
+ ${optionalString (def.macvlanConfig != { }) ''
+ [MACVLAN]
+ ${attrsToSection def.macvlanConfig}
+
+ ''}
+ ${optionalString (def.vxlanConfig != { }) ''
+ [VXLAN]
+ ${attrsToSection def.vxlanConfig}
+
+ ''}
+ ${optionalString (def.tunnelConfig != { }) ''
+ [Tunnel]
+ ${attrsToSection def.tunnelConfig}
+
+ ''}
+ ${optionalString (def.peerConfig != { }) ''
+ [Peer]
+ ${attrsToSection def.peerConfig}
+
+ ''}
+ ${optionalString (def.tunConfig != { }) ''
+ [Tun]
+ ${attrsToSection def.tunConfig}
+
+ ''}
+ ${optionalString (def.tapConfig != { }) ''
+ [Tap]
+ ${attrsToSection def.tapConfig}
+
+ ''}
+ ${optionalString (def.bondConfig != { }) ''
+ [Bond]
+ ${attrsToSection def.bondConfig}
+
+ ''}
+ '';
+ };
+
+ networkToUnit = name: def:
+ { inherit (def) enable;
+ text = commonMatchText def +
+ ''
+ [Network]
+ ${attrsToSection def.networkConfig}
+ ${concatStringsSep "\n" (map (s: "Address=${s}") def.address)}
+ ${concatStringsSep "\n" (map (s: "Gateway=${s}") def.gateway)}
+ ${concatStringsSep "\n" (map (s: "DNS=${s}") def.dns)}
+ ${concatStringsSep "\n" (map (s: "NTP=${s}") def.ntp)}
+ ${concatStringsSep "\n" (map (s: "VLAN=${s}") def.vlan)}
+ ${concatStringsSep "\n" (map (s: "MACVLAN=${s}") def.macvlan)}
+ ${concatStringsSep "\n" (map (s: "VXLAN=${s}") def.vxlan)}
+ ${concatStringsSep "\n" (map (s: "Tunnel=${s}") def.tunnel)}
+
+ ${optionalString (def.dhcpConfig != { }) ''
+ [DHCP]
+ ${attrsToSection def.dhcpConfig}
+
+ ''}
+ ${flip concatMapStrings def.addresses (x: ''
+ [Address]
+ ${attrsToSection x.addressConfig}
+
+ '')}
+ ${flip concatMapStrings def.routes (x: ''
+ [Route]
+ ${attrsToSection x.routeConfig}
+
+ '')}
+ '';
+ };
+
generateUnits = type: units: upstreamUnits: upstreamWants:
pkgs.runCommand "${type}-units" { preferLocalBuild = true; } ''
mkdir -p $out
@@ -562,6 +662,47 @@ in
'';
};
+ systemd.network.enable = mkOption {
+ default = false;
+ type = types.bool;
+ description = ''
+ Whether to enable networkd or not.
+ '';
+ };
+
+ systemd.network.links = mkOption {
+ default = {};
+ type = types.attrsOf types.optionSet;
+ options = [ linkOptions ];
+ description = "Definiton of systemd network links.";
+ };
+
+ systemd.network.netdevs = mkOption {
+ default = {};
+ type = types.attrsOf types.optionSet;
+ options = [ netdevOptions ];
+ description = "Definiton of systemd network devices.";
+ };
+
+ systemd.network.networks = mkOption {
+ default = {};
+ type = types.attrsOf types.optionSet;
+ options = [ networkOptions ];
+ description = "Definiton of systemd networks.";
+ };
+
+ systemd.network.units = mkOption {
+ description = "Definition of networkd units.";
+ default = {};
+ type = types.attrsOf types.optionSet;
+ options = { name, config, ... }:
+ { options = concreteUnitOptions;
+ config = {
+ unit = mkDefault (makeUnit name config);
+ };
+ };
+ };
+
systemd.defaultUnit = mkOption {
default = "multi-user.target";
type = types.str;
@@ -714,6 +855,9 @@ in
environment.etc."systemd/system".source =
generateUnits "system" cfg.units upstreamSystemUnits upstreamSystemWants;
+ environment.etc."systemd/network".source =
+ generateUnits "network" cfg.network.units [] [];
+
environment.etc."systemd/user".source =
generateUnits "user" cfg.user.units upstreamUserUnits [];
@@ -779,6 +923,11 @@ in
(v: let n = escapeSystemdPath v.where;
in nameValuePair "${n}.automount" (automountToUnit n v)) cfg.automounts);
+ systemd.network.units =
+ mapAttrs' (n: v: nameValuePair "${n}.link" (linkToUnit n v)) cfg.network.links
+ // mapAttrs' (n: v: nameValuePair "${n}.netdev" (netdevToUnit n v)) cfg.network.netdevs
+ // mapAttrs' (n: v: nameValuePair "${n}.network" (networkToUnit n v)) cfg.network.networks;
+
systemd.user.units =
mapAttrs' (n: v: nameValuePair "${n}.service" (serviceToUnit n v)) cfg.user.services
// mapAttrs' (n: v: nameValuePair "${n}.socket" (socketToUnit n v)) cfg.user.sockets;
@@ -800,6 +949,14 @@ in
users.extraUsers.systemd-journal-gateway.uid = config.ids.uids.systemd-journal-gateway;
users.extraGroups.systemd-journal-gateway.gid = config.ids.gids.systemd-journal-gateway;
+ # Networkd
+ users.extraUsers.systemd-network.uid = config.ids.uids.systemd-network;
+ users.extraGroups.systemd-network.gid = config.ids.gids.systemd-network;
+ systemd.services.systemd-networkd.wantedBy =
+ optional config.systemd.network.enable "multi-user.target";
+ systemd.services.systemd-networkd.restartTriggers =
+ [ config.environment.etc."systemd/network".source ];
+
# Generate timer units for all services that have a ‘startAt’ value.
systemd.timers =
mapAttrs (name: service: