1{ config, lib, pkgs, ... }: 2 3with lib; 4with import ./systemd-unit-options.nix { inherit config lib; }; 5with import ./systemd-lib.nix { inherit config lib pkgs; }; 6 7let 8 9 cfg = config.systemd.network; 10 11 checkLink = checkUnitConfig "Link" [ 12 (assertOnlyFields [ 13 "Description" "Alias" "MACAddressPolicy" "MACAddress" "NamePolicy" "Name" 14 "MTUBytes" "BitsPerSecond" "Duplex" "WakeOnLan" 15 ]) 16 (assertValueOneOf "MACAddressPolicy" ["persistent" "random"]) 17 (assertMacAddress "MACAddress") 18 (assertValueOneOf "NamePolicy" [ 19 "kernel" "database" "onboard" "slot" "path" "mac" 20 ]) 21 (assertByteFormat "MTUBytes") 22 (assertByteFormat "BitsPerSecond") 23 (assertValueOneOf "Duplex" ["half" "full"]) 24 (assertValueOneOf "WakeOnLan" ["phy" "magic" "off"]) 25 ]; 26 27 checkNetdev = checkUnitConfig "Netdev" [ 28 (assertOnlyFields [ 29 "Description" "Name" "Kind" "MTUBytes" "MACAddress" 30 ]) 31 (assertHasField "Name") 32 (assertHasField "Kind") 33 (assertValueOneOf "Kind" [ 34 "bridge" "bond" "vlan" "macvlan" "vxlan" "ipip" 35 "gre" "sit" "vti" "veth" "tun" "tap" "dummy" 36 ]) 37 (assertByteFormat "MTUBytes") 38 (assertMacAddress "MACAddress") 39 ]; 40 41 checkVlan = checkUnitConfig "VLAN" [ 42 (assertOnlyFields ["Id"]) 43 (assertRange "Id" 0 4094) 44 ]; 45 46 checkMacvlan = checkUnitConfig "MACVLAN" [ 47 (assertOnlyFields ["Mode"]) 48 (assertValueOneOf "Mode" ["private" "vepa" "bridge" "passthru"]) 49 ]; 50 51 checkVxlan = checkUnitConfig "VXLAN" [ 52 (assertOnlyFields ["Id" "Group" "TOS" "TTL" "MacLearning"]) 53 (assertRange "TTL" 0 255) 54 (assertValueOneOf "MacLearning" boolValues) 55 ]; 56 57 checkTunnel = checkUnitConfig "Tunnel" [ 58 (assertOnlyFields ["Local" "Remote" "TOS" "TTL" "DiscoverPathMTU"]) 59 (assertRange "TTL" 0 255) 60 (assertValueOneOf "DiscoverPathMTU" boolValues) 61 ]; 62 63 checkPeer = checkUnitConfig "Peer" [ 64 (assertOnlyFields ["Name" "MACAddress"]) 65 (assertMacAddress "MACAddress") 66 ]; 67 68 tunTapChecks = [ 69 (assertOnlyFields ["OneQueue" "MultiQueue" "PacketInfo" "User" "Group"]) 70 (assertValueOneOf "OneQueue" boolValues) 71 (assertValueOneOf "MultiQueue" boolValues) 72 (assertValueOneOf "PacketInfo" boolValues) 73 ]; 74 75 checkTun = checkUnitConfig "Tun" tunTapChecks; 76 77 checkTap = checkUnitConfig "Tap" tunTapChecks; 78 79 checkBond = checkUnitConfig "Bond" [ 80 (assertOnlyFields [ 81 "Mode" "TransmitHashPolicy" "LACPTransmitRate" "MIIMonitorSec" 82 "UpDelaySec" "DownDelaySec" 83 ]) 84 (assertValueOneOf "Mode" [ 85 "balance-rr" "active-backup" "balance-xor" 86 "broadcast" "802.3ad" "balance-tlb" "balance-alb" 87 ]) 88 (assertValueOneOf "TransmitHashPolicy" [ 89 "layer2" "layer3+4" "layer2+3" "encap2+3" "802.3ad" "encap3+4" 90 ]) 91 (assertValueOneOf "LACPTransmitRate" ["slow" "fast"]) 92 ]; 93 94 checkNetwork = checkUnitConfig "Network" [ 95 (assertOnlyFields [ 96 "Description" "DHCP" "DHCPServer" "IPForward" "IPMasquerade" "IPv4LL" "IPv4LLRoute" 97 "LLMNR" "Domains" "Bridge" "Bond" 98 ]) 99 (assertValueOneOf "DHCP" ["both" "none" "v4" "v6"]) 100 (assertValueOneOf "DHCPServer" boolValues) 101 (assertValueOneOf "IPForward" ["yes" "no" "ipv4" "ipv6"]) 102 (assertValueOneOf "IPMasquerade" boolValues) 103 (assertValueOneOf "IPv4LL" boolValues) 104 (assertValueOneOf "IPv4LLRoute" boolValues) 105 (assertValueOneOf "LLMNR" boolValues) 106 ]; 107 108 checkAddress = checkUnitConfig "Address" [ 109 (assertOnlyFields ["Address" "Peer" "Broadcast" "Label"]) 110 (assertHasField "Address") 111 ]; 112 113 checkRoute = checkUnitConfig "Route" [ 114 (assertOnlyFields ["Gateway" "Destination" "Metric"]) 115 (assertHasField "Gateway") 116 ]; 117 118 checkDhcp = checkUnitConfig "DHCP" [ 119 (assertOnlyFields [ 120 "UseDNS" "UseMTU" "SendHostname" "UseHostname" "UseDomains" "UseRoutes" 121 "CriticalConnections" "VendorClassIdentifier" "RequestBroadcast" 122 "RouteMetric" 123 ]) 124 (assertValueOneOf "UseDNS" boolValues) 125 (assertValueOneOf "UseMTU" boolValues) 126 (assertValueOneOf "SendHostname" boolValues) 127 (assertValueOneOf "UseHostname" boolValues) 128 (assertValueOneOf "UseDomains" boolValues) 129 (assertValueOneOf "UseRoutes" boolValues) 130 (assertValueOneOf "CriticalConnections" boolValues) 131 (assertValueOneOf "RequestBroadcast" boolValues) 132 ]; 133 134 checkDhcpServer = checkUnitConfig "DHCPServer" [ 135 (assertOnlyFields [ 136 "PoolOffset" "PoolSize" "DefaultLeaseTimeSec" "MaxLeaseTimeSec" 137 "EmitDNS" "DNS" "EmitNTP" "NTP" "EmitTimezone" "Timezone" 138 ]) 139 (assertValueOneOf "EmitDNS" boolValues) 140 (assertValueOneOf "EmitNTP" boolValues) 141 (assertValueOneOf "EmitTimezone" boolValues) 142 ]; 143 144 commonNetworkOptions = { 145 146 enable = mkOption { 147 default = true; 148 type = types.bool; 149 description = '' 150 Whether to manage network configuration using <command>systemd-network</command>. 151 ''; 152 }; 153 154 matchConfig = mkOption { 155 default = {}; 156 example = { Name = "eth0"; }; 157 type = types.attrsOf unitOption; 158 description = '' 159 Each attribute in this set specifies an option in the 160 <literal>[Match]</literal> section of the unit. See 161 <citerefentry><refentrytitle>systemd.link</refentrytitle><manvolnum>5</manvolnum></citerefentry> 162 <citerefentry><refentrytitle>systemd.netdev</refentrytitle><manvolnum>5</manvolnum></citerefentry> 163 <citerefentry><refentrytitle>systemd.network</refentrytitle><manvolnum>5</manvolnum></citerefentry> 164 for details. 165 ''; 166 }; 167 168 }; 169 170 linkOptions = commonNetworkOptions // { 171 172 linkConfig = mkOption { 173 default = {}; 174 example = { MACAddress = "00:ff:ee:aa:cc:dd"; }; 175 type = types.addCheck (types.attrsOf unitOption) checkLink; 176 description = '' 177 Each attribute in this set specifies an option in the 178 <literal>[Link]</literal> section of the unit. See 179 <citerefentry><refentrytitle>systemd.link</refentrytitle> 180 <manvolnum>5</manvolnum></citerefentry> for details. 181 ''; 182 }; 183 184 }; 185 186 netdevOptions = commonNetworkOptions // { 187 188 netdevConfig = mkOption { 189 default = {}; 190 example = { Name = "mybridge"; Kind = "bridge"; }; 191 type = types.addCheck (types.attrsOf unitOption) checkNetdev; 192 description = '' 193 Each attribute in this set specifies an option in the 194 <literal>[Netdev]</literal> section of the unit. See 195 <citerefentry><refentrytitle>systemd.netdev</refentrytitle> 196 <manvolnum>5</manvolnum></citerefentry> for details. 197 ''; 198 }; 199 200 vlanConfig = mkOption { 201 default = {}; 202 example = { Id = "4"; }; 203 type = types.addCheck (types.attrsOf unitOption) checkVlan; 204 description = '' 205 Each attribute in this set specifies an option in the 206 <literal>[VLAN]</literal> section of the unit. See 207 <citerefentry><refentrytitle>systemd.netdev</refentrytitle> 208 <manvolnum>5</manvolnum></citerefentry> for details. 209 ''; 210 }; 211 212 macvlanConfig = mkOption { 213 default = {}; 214 example = { Mode = "private"; }; 215 type = types.addCheck (types.attrsOf unitOption) checkMacvlan; 216 description = '' 217 Each attribute in this set specifies an option in the 218 <literal>[MACVLAN]</literal> section of the unit. See 219 <citerefentry><refentrytitle>systemd.netdev</refentrytitle> 220 <manvolnum>5</manvolnum></citerefentry> for details. 221 ''; 222 }; 223 224 vxlanConfig = mkOption { 225 default = {}; 226 example = { Id = "4"; }; 227 type = types.addCheck (types.attrsOf unitOption) checkVxlan; 228 description = '' 229 Each attribute in this set specifies an option in the 230 <literal>[VXLAN]</literal> section of the unit. See 231 <citerefentry><refentrytitle>systemd.netdev</refentrytitle> 232 <manvolnum>5</manvolnum></citerefentry> for details. 233 ''; 234 }; 235 236 tunnelConfig = mkOption { 237 default = {}; 238 example = { Remote = "192.168.1.1"; }; 239 type = types.addCheck (types.attrsOf unitOption) checkTunnel; 240 description = '' 241 Each attribute in this set specifies an option in the 242 <literal>[Tunnel]</literal> section of the unit. See 243 <citerefentry><refentrytitle>systemd.netdev</refentrytitle> 244 <manvolnum>5</manvolnum></citerefentry> for details. 245 ''; 246 }; 247 248 peerConfig = mkOption { 249 default = {}; 250 example = { Name = "veth2"; }; 251 type = types.addCheck (types.attrsOf unitOption) checkPeer; 252 description = '' 253 Each attribute in this set specifies an option in the 254 <literal>[Peer]</literal> section of the unit. See 255 <citerefentry><refentrytitle>systemd.netdev</refentrytitle> 256 <manvolnum>5</manvolnum></citerefentry> for details. 257 ''; 258 }; 259 260 tunConfig = mkOption { 261 default = {}; 262 example = { User = "openvpn"; }; 263 type = types.addCheck (types.attrsOf unitOption) checkTun; 264 description = '' 265 Each attribute in this set specifies an option in the 266 <literal>[Tun]</literal> section of the unit. See 267 <citerefentry><refentrytitle>systemd.netdev</refentrytitle> 268 <manvolnum>5</manvolnum></citerefentry> for details. 269 ''; 270 }; 271 272 tapConfig = mkOption { 273 default = {}; 274 example = { User = "openvpn"; }; 275 type = types.addCheck (types.attrsOf unitOption) checkTap; 276 description = '' 277 Each attribute in this set specifies an option in the 278 <literal>[Tap]</literal> section of the unit. See 279 <citerefentry><refentrytitle>systemd.netdev</refentrytitle> 280 <manvolnum>5</manvolnum></citerefentry> for details. 281 ''; 282 }; 283 284 bondConfig = mkOption { 285 default = {}; 286 example = { Mode = "802.3ad"; }; 287 type = types.addCheck (types.attrsOf unitOption) checkBond; 288 description = '' 289 Each attribute in this set specifies an option in the 290 <literal>[Bond]</literal> section of the unit. See 291 <citerefentry><refentrytitle>systemd.netdev</refentrytitle> 292 <manvolnum>5</manvolnum></citerefentry> for details. 293 ''; 294 }; 295 296 }; 297 298 addressOptions = { 299 300 addressConfig = mkOption { 301 default = {}; 302 example = { Address = "192.168.0.100/24"; }; 303 type = types.addCheck (types.attrsOf unitOption) checkAddress; 304 description = '' 305 Each attribute in this set specifies an option in the 306 <literal>[Address]</literal> section of the unit. See 307 <citerefentry><refentrytitle>systemd.network</refentrytitle> 308 <manvolnum>5</manvolnum></citerefentry> for details. 309 ''; 310 }; 311 312 }; 313 314 routeOptions = { 315 316 routeConfig = mkOption { 317 default = {}; 318 example = { Gateway = "192.168.0.1"; }; 319 type = types.addCheck (types.attrsOf unitOption) checkRoute; 320 description = '' 321 Each attribute in this set specifies an option in the 322 <literal>[Route]</literal> section of the unit. See 323 <citerefentry><refentrytitle>systemd.network</refentrytitle> 324 <manvolnum>5</manvolnum></citerefentry> for details. 325 ''; 326 }; 327 328 }; 329 330 networkOptions = commonNetworkOptions // { 331 332 networkConfig = mkOption { 333 default = {}; 334 example = { Description = "My Network"; }; 335 type = types.addCheck (types.attrsOf unitOption) checkNetwork; 336 description = '' 337 Each attribute in this set specifies an option in the 338 <literal>[Network]</literal> section of the unit. See 339 <citerefentry><refentrytitle>systemd.network</refentrytitle> 340 <manvolnum>5</manvolnum></citerefentry> for details. 341 ''; 342 }; 343 344 dhcpConfig = mkOption { 345 default = {}; 346 example = { UseDNS = true; UseRoutes = true; }; 347 type = types.addCheck (types.attrsOf unitOption) checkDhcp; 348 description = '' 349 Each attribute in this set specifies an option in the 350 <literal>[DHCP]</literal> section of the unit. See 351 <citerefentry><refentrytitle>systemd.network</refentrytitle> 352 <manvolnum>5</manvolnum></citerefentry> for details. 353 ''; 354 }; 355 356 dhcpServerConfig = mkOption { 357 default = {}; 358 example = { PoolOffset = 50; EmitDNS = false; }; 359 type = types.addCheck (types.attrsOf unitOption) checkDhcpServer; 360 description = '' 361 Each attribute in this set specifies an option in the 362 <literal>[DHCPServer]</literal> section of the unit. See 363 <citerefentry><refentrytitle>systemd.network</refentrytitle> 364 <manvolnum>5</manvolnum></citerefentry> for details. 365 ''; 366 }; 367 368 name = mkOption { 369 type = types.nullOr types.str; 370 default = null; 371 description = '' 372 The name of the network interface to match against. 373 ''; 374 }; 375 376 DHCP = mkOption { 377 type = types.nullOr types.str; 378 default = null; 379 description = '' 380 Whether to enable DHCP on the interfaces matched. 381 ''; 382 }; 383 384 domains = mkOption { 385 type = types.nullOr (types.listOf types.str); 386 default = null; 387 description = '' 388 A list of domains to pass to the network config. 389 ''; 390 }; 391 392 address = mkOption { 393 default = [ ]; 394 type = types.listOf types.str; 395 description = '' 396 A list of addresses to be added to the network section of the 397 unit. See <citerefentry><refentrytitle>systemd.network</refentrytitle> 398 <manvolnum>5</manvolnum></citerefentry> for details. 399 ''; 400 }; 401 402 gateway = mkOption { 403 default = [ ]; 404 type = types.listOf types.str; 405 description = '' 406 A list of gateways to be added to the network section of the 407 unit. See <citerefentry><refentrytitle>systemd.network</refentrytitle> 408 <manvolnum>5</manvolnum></citerefentry> for details. 409 ''; 410 }; 411 412 dns = mkOption { 413 default = [ ]; 414 type = types.listOf types.str; 415 description = '' 416 A list of dns servers to be added to the network section of the 417 unit. See <citerefentry><refentrytitle>systemd.network</refentrytitle> 418 <manvolnum>5</manvolnum></citerefentry> for details. 419 ''; 420 }; 421 422 ntp = mkOption { 423 default = [ ]; 424 type = types.listOf types.str; 425 description = '' 426 A list of ntp servers to be added to the network section of the 427 unit. See <citerefentry><refentrytitle>systemd.network</refentrytitle> 428 <manvolnum>5</manvolnum></citerefentry> for details. 429 ''; 430 }; 431 432 vlan = mkOption { 433 default = [ ]; 434 type = types.listOf types.str; 435 description = '' 436 A list of vlan interfaces to be added to the network section of the 437 unit. See <citerefentry><refentrytitle>systemd.network</refentrytitle> 438 <manvolnum>5</manvolnum></citerefentry> for details. 439 ''; 440 }; 441 442 macvlan = mkOption { 443 default = [ ]; 444 type = types.listOf types.str; 445 description = '' 446 A list of macvlan interfaces to be added to the network section of the 447 unit. See <citerefentry><refentrytitle>systemd.network</refentrytitle> 448 <manvolnum>5</manvolnum></citerefentry> for details. 449 ''; 450 }; 451 452 vxlan = mkOption { 453 default = [ ]; 454 type = types.listOf types.str; 455 description = '' 456 A list of vxlan interfaces to be added to the network section of the 457 unit. See <citerefentry><refentrytitle>systemd.network</refentrytitle> 458 <manvolnum>5</manvolnum></citerefentry> for details. 459 ''; 460 }; 461 462 tunnel = mkOption { 463 default = [ ]; 464 type = types.listOf types.str; 465 description = '' 466 A list of tunnel interfaces to be added to the network section of the 467 unit. See <citerefentry><refentrytitle>systemd.network</refentrytitle> 468 <manvolnum>5</manvolnum></citerefentry> for details. 469 ''; 470 }; 471 472 addresses = mkOption { 473 default = [ ]; 474 type = types.listOf types.optionSet; 475 options = [ addressOptions ]; 476 description = '' 477 A list of address sections to be added to the unit. See 478 <citerefentry><refentrytitle>systemd.network</refentrytitle> 479 <manvolnum>5</manvolnum></citerefentry> for details. 480 ''; 481 }; 482 483 routes = mkOption { 484 default = [ ]; 485 type = types.listOf types.optionSet; 486 options = [ routeOptions ]; 487 description = '' 488 A list of route sections to be added to the unit. See 489 <citerefentry><refentrytitle>systemd.network</refentrytitle> 490 <manvolnum>5</manvolnum></citerefentry> for details. 491 ''; 492 }; 493 494 }; 495 496 networkConfig = { name, config, ... }: { 497 config = { 498 matchConfig = optionalAttrs (config.name != null) { 499 Name = config.name; 500 }; 501 networkConfig = optionalAttrs (config.DHCP != null) { 502 DHCP = config.DHCP; 503 } // optionalAttrs (config.domains != null) { 504 Domains = concatStringsSep " " config.domains; 505 }; 506 }; 507 }; 508 509 commonMatchText = def: '' 510 [Match] 511 ${attrsToSection def.matchConfig} 512 ''; 513 514 linkToUnit = name: def: 515 { inherit (def) enable; 516 text = commonMatchText def + 517 '' 518 [Link] 519 ${attrsToSection def.linkConfig} 520 ''; 521 }; 522 523 netdevToUnit = name: def: 524 { inherit (def) enable; 525 text = commonMatchText def + 526 '' 527 [NetDev] 528 ${attrsToSection def.netdevConfig} 529 530 ${optionalString (def.vlanConfig != { }) '' 531 [VLAN] 532 ${attrsToSection def.vlanConfig} 533 534 ''} 535 ${optionalString (def.macvlanConfig != { }) '' 536 [MACVLAN] 537 ${attrsToSection def.macvlanConfig} 538 539 ''} 540 ${optionalString (def.vxlanConfig != { }) '' 541 [VXLAN] 542 ${attrsToSection def.vxlanConfig} 543 544 ''} 545 ${optionalString (def.tunnelConfig != { }) '' 546 [Tunnel] 547 ${attrsToSection def.tunnelConfig} 548 549 ''} 550 ${optionalString (def.peerConfig != { }) '' 551 [Peer] 552 ${attrsToSection def.peerConfig} 553 554 ''} 555 ${optionalString (def.tunConfig != { }) '' 556 [Tun] 557 ${attrsToSection def.tunConfig} 558 559 ''} 560 ${optionalString (def.tapConfig != { }) '' 561 [Tap] 562 ${attrsToSection def.tapConfig} 563 564 ''} 565 ${optionalString (def.bondConfig != { }) '' 566 [Bond] 567 ${attrsToSection def.bondConfig} 568 569 ''} 570 ''; 571 }; 572 573 networkToUnit = name: def: 574 { inherit (def) enable; 575 text = commonMatchText def + 576 '' 577 [Network] 578 ${attrsToSection def.networkConfig} 579 ${concatStringsSep "\n" (map (s: "Address=${s}") def.address)} 580 ${concatStringsSep "\n" (map (s: "Gateway=${s}") def.gateway)} 581 ${concatStringsSep "\n" (map (s: "DNS=${s}") def.dns)} 582 ${concatStringsSep "\n" (map (s: "NTP=${s}") def.ntp)} 583 ${concatStringsSep "\n" (map (s: "VLAN=${s}") def.vlan)} 584 ${concatStringsSep "\n" (map (s: "MACVLAN=${s}") def.macvlan)} 585 ${concatStringsSep "\n" (map (s: "VXLAN=${s}") def.vxlan)} 586 ${concatStringsSep "\n" (map (s: "Tunnel=${s}") def.tunnel)} 587 588 ${optionalString (def.dhcpConfig != { }) '' 589 [DHCP] 590 ${attrsToSection def.dhcpConfig} 591 592 ''} 593 ${optionalString (def.dhcpServerConfig != { }) '' 594 [DHCPServer] 595 ${attrsToSection def.dhcpServerConfig} 596 597 ''} 598 ${flip concatMapStrings def.addresses (x: '' 599 [Address] 600 ${attrsToSection x.addressConfig} 601 602 '')} 603 ${flip concatMapStrings def.routes (x: '' 604 [Route] 605 ${attrsToSection x.routeConfig} 606 607 '')} 608 ''; 609 }; 610 611in 612 613{ 614 615 options = { 616 617 systemd.network.enable = mkOption { 618 default = false; 619 type = types.bool; 620 description = '' 621 Whether to enable networkd or not. 622 ''; 623 }; 624 625 systemd.network.links = mkOption { 626 default = {}; 627 type = types.attrsOf types.optionSet; 628 options = [ linkOptions ]; 629 description = "Definition of systemd network links."; 630 }; 631 632 systemd.network.netdevs = mkOption { 633 default = {}; 634 type = types.attrsOf types.optionSet; 635 options = [ netdevOptions ]; 636 description = "Definition of systemd network devices."; 637 }; 638 639 systemd.network.networks = mkOption { 640 default = {}; 641 type = types.attrsOf types.optionSet; 642 options = [ networkOptions networkConfig ]; 643 description = "Definition of systemd networks."; 644 }; 645 646 systemd.network.units = mkOption { 647 description = "Definition of networkd units."; 648 default = {}; 649 type = types.attrsOf types.optionSet; 650 options = { name, config, ... }: 651 { options = concreteUnitOptions; 652 config = { 653 unit = mkDefault (makeUnit name config); 654 }; 655 }; 656 }; 657 658 }; 659 660 config = mkIf config.systemd.network.enable { 661 662 systemd.additionalUpstreamSystemUnits = 663 [ "systemd-networkd.service" "systemd-networkd-wait-online.service" ]; 664 665 systemd.network.units = 666 mapAttrs' (n: v: nameValuePair "${n}.link" (linkToUnit n v)) cfg.links 667 // mapAttrs' (n: v: nameValuePair "${n}.netdev" (netdevToUnit n v)) cfg.netdevs 668 // mapAttrs' (n: v: nameValuePair "${n}.network" (networkToUnit n v)) cfg.networks; 669 670 environment.etc."systemd/network".source = 671 generateUnits "network" cfg.units [] []; 672 673 systemd.services.systemd-networkd = { 674 wantedBy = [ "multi-user.target" ]; 675 before = [ "network-interfaces.target" ]; 676 restartTriggers = [ config.environment.etc."systemd/network".source ]; 677 }; 678 679 systemd.services.systemd-networkd-wait-online = { 680 before = [ "network-online.target" "ip-up.target" ]; 681 wantedBy = [ "network-online.target" "ip-up.target" ]; 682 }; 683 684 systemd.services."systemd-network-wait-online@" = { 685 description = "Wait for Network Interface %I to be Configured"; 686 conflicts = [ "shutdown.target" ]; 687 requisite = [ "systemd-networkd.service" ]; 688 after = [ "systemd-networkd.service" ]; 689 serviceConfig = { 690 Type = "oneshot"; 691 RemainAfterExit = true; 692 ExecStart = "${config.systemd.package}/lib/systemd/systemd-networkd-wait-online -i %I"; 693 }; 694 }; 695 696 services.resolved.enable = mkDefault true; 697 services.timesyncd.enable = mkDefault config.services.ntp.enable; 698 699 }; 700 701}