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" "AutoNegotiation" "WakeOnLan" "Port"
15 "TCPSegmentationOffload" "TCP6SegmentationOffload" "GenericSegmentationOffload"
16 "GenericReceiveOffload" "LargeReceiveOffload" "RxChannels" "TxChannels"
17 "OtherChannels" "CombinedChannels"
18 ])
19 (assertValueOneOf "MACAddressPolicy" ["persistent" "random" "none"])
20 (assertMacAddress "MACAddress")
21 (assertByteFormat "MTUBytes")
22 (assertByteFormat "BitsPerSecond")
23 (assertValueOneOf "Duplex" ["half" "full"])
24 (assertValueOneOf "AutoNegotiation" boolValues)
25 (assertValueOneOf "WakeOnLan" ["phy" "unicast" "multicast" "broadcast" "arp" "magic" "secureon" "off"])
26 (assertValueOneOf "Port" ["tp" "aui" "bnc" "mii" "fibre"])
27 (assertValueOneOf "TCPSegmentationOffload" boolValues)
28 (assertValueOneOf "TCP6SegmentationOffload" boolValues)
29 (assertValueOneOf "GenericSegmentationOffload" boolValues)
30 (assertValueOneOf "UDPSegmentationOffload" boolValues)
31 (assertValueOneOf "GenericReceiveOffload" boolValues)
32 (assertValueOneOf "LargeReceiveOffload" boolValues)
33 (assertInt "RxChannels")
34 (assertMinimum "RxChannels" 1)
35 (assertInt "TxChannels")
36 (assertMinimum "TxChannels" 1)
37 (assertInt "OtherChannels")
38 (assertMinimum "OtherChannels" 1)
39 (assertInt "CombinedChannels")
40 (assertMinimum "CombinedChannels" 1)
41 ];
42
43 checkNetdev = checkUnitConfig "Netdev" [
44 (assertOnlyFields [
45 "Description" "Name" "Kind" "MTUBytes" "MACAddress"
46 ])
47 (assertHasField "Name")
48 (assertHasField "Kind")
49 (assertValueOneOf "Kind" [
50 "bond" "bridge" "dummy" "gre" "gretap" "ip6gre" "ip6tnl" "ip6gretap" "ipip"
51 "ipvlan" "macvlan" "macvtap" "sit" "tap" "tun" "veth" "vlan" "vti" "vti6"
52 "vxlan" "geneve" "vrf" "vcan" "vxcan" "wireguard" "netdevsim"
53 ])
54 (assertByteFormat "MTUBytes")
55 (assertMacAddress "MACAddress")
56 ];
57
58 checkVlan = checkUnitConfig "VLAN" [
59 (assertOnlyFields ["Id" "GVRP" "MVRP" "LooseBinding" "ReorderHeader"])
60 (assertRange "Id" 0 4094)
61 (assertValueOneOf "GVRP" boolValues)
62 (assertValueOneOf "MVRP" boolValues)
63 (assertValueOneOf "LooseBinding" boolValues)
64 (assertValueOneOf "ReorderHeader" boolValues)
65 ];
66
67 checkMacvlan = checkUnitConfig "MACVLAN" [
68 (assertOnlyFields ["Mode"])
69 (assertValueOneOf "Mode" ["private" "vepa" "bridge" "passthru"])
70 ];
71
72 checkVxlan = checkUnitConfig "VXLAN" [
73 (assertOnlyFields [
74 "Id" "Remote" "Local" "TOS" "TTL" "MacLearning" "FDBAgeingSec"
75 "MaximumFDBEntries" "ReduceARPProxy" "L2MissNotification"
76 "L3MissNotification" "RouteShortCircuit" "UDPChecksum"
77 "UDP6ZeroChecksumTx" "UDP6ZeroChecksumRx" "RemoteChecksumTx"
78 "RemoteChecksumRx" "GroupPolicyExtension" "DestinationPort" "PortRange"
79 "FlowLabel"
80 ])
81 (assertRange "TTL" 0 255)
82 (assertValueOneOf "MacLearning" boolValues)
83 (assertValueOneOf "ReduceARPProxy" boolValues)
84 (assertValueOneOf "L2MissNotification" boolValues)
85 (assertValueOneOf "L3MissNotification" boolValues)
86 (assertValueOneOf "RouteShortCircuit" boolValues)
87 (assertValueOneOf "UDPChecksum" boolValues)
88 (assertValueOneOf "UDP6ZeroChecksumTx" boolValues)
89 (assertValueOneOf "UDP6ZeroChecksumRx" boolValues)
90 (assertValueOneOf "RemoteChecksumTx" boolValues)
91 (assertValueOneOf "RemoteChecksumRx" boolValues)
92 (assertValueOneOf "GroupPolicyExtension" boolValues)
93 (assertRange "FlowLabel" 0 1048575)
94 ];
95
96 checkTunnel = checkUnitConfig "Tunnel" [
97 (assertOnlyFields [
98 "Local" "Remote" "TOS" "TTL" "DiscoverPathMTU" "IPv6FlowLabel" "CopyDSCP"
99 "EncapsulationLimit" "Key" "InputKey" "OutputKey" "Mode" "Independent"
100 "AllowLocalRemote"
101 ])
102 (assertRange "TTL" 0 255)
103 (assertValueOneOf "DiscoverPathMTU" boolValues)
104 (assertValueOneOf "CopyDSCP" boolValues)
105 (assertValueOneOf "Mode" ["ip6ip6" "ipip6" "any"])
106 (assertValueOneOf "Independent" boolValues)
107 (assertValueOneOf "AllowLocalRemote" boolValues)
108 ];
109
110 checkPeer = checkUnitConfig "Peer" [
111 (assertOnlyFields ["Name" "MACAddress"])
112 (assertMacAddress "MACAddress")
113 ];
114
115 tunTapChecks = [
116 (assertOnlyFields ["OneQueue" "MultiQueue" "PacketInfo" "VNetHeader" "User" "Group"])
117 (assertValueOneOf "OneQueue" boolValues)
118 (assertValueOneOf "MultiQueue" boolValues)
119 (assertValueOneOf "PacketInfo" boolValues)
120 (assertValueOneOf "VNetHeader" boolValues)
121 ];
122
123 checkTun = checkUnitConfig "Tun" tunTapChecks;
124
125 checkTap = checkUnitConfig "Tap" tunTapChecks;
126
127 checkBond = checkUnitConfig "Bond" [
128 (assertOnlyFields [
129 "Mode" "TransmitHashPolicy" "LACPTransmitRate" "MIIMonitorSec"
130 "UpDelaySec" "DownDelaySec" "LearnPacketIntervalSec" "AdSelect"
131 "FailOverMACPolicy" "ARPValidate" "ARPIntervalSec" "ARPIPTargets"
132 "ARPAllTargets" "PrimaryReselectPolicy" "ResendIGMP" "PacketsPerSlave"
133 "GratuitousARP" "AllSlavesActive" "MinLinks"
134 ])
135 (assertValueOneOf "Mode" [
136 "balance-rr" "active-backup" "balance-xor"
137 "broadcast" "802.3ad" "balance-tlb" "balance-alb"
138 ])
139 (assertValueOneOf "TransmitHashPolicy" [
140 "layer2" "layer3+4" "layer2+3" "encap2+3" "encap3+4"
141 ])
142 (assertValueOneOf "LACPTransmitRate" ["slow" "fast"])
143 (assertValueOneOf "AdSelect" ["stable" "bandwidth" "count"])
144 (assertValueOneOf "FailOverMACPolicy" ["none" "active" "follow"])
145 (assertValueOneOf "ARPValidate" ["none" "active" "backup" "all"])
146 (assertValueOneOf "ARPAllTargets" ["any" "all"])
147 (assertValueOneOf "PrimaryReselectPolicy" ["always" "better" "failure"])
148 (assertRange "ResendIGMP" 0 255)
149 (assertRange "PacketsPerSlave" 0 65535)
150 (assertRange "GratuitousARP" 0 255)
151 (assertValueOneOf "AllSlavesActive" boolValues)
152 ];
153
154 checkNetwork = checkUnitConfig "Network" [
155 (assertOnlyFields [
156 "Description" "DHCP" "DHCPServer" "LinkLocalAddressing" "IPv4LLRoute"
157 "IPv6Token" "LLMNR" "MulticastDNS" "DNSOverTLS" "DNSSEC"
158 "DNSSECNegativeTrustAnchors" "LLDP" "EmitLLDP" "BindCarrier" "Address"
159 "Gateway" "DNS" "Domains" "NTP" "IPForward" "IPMasquerade"
160 "IPv6PrivacyExtensions" "IPv6AcceptRA" "IPv6DuplicateAddressDetection"
161 "IPv6HopLimit" "IPv4ProxyARP" "IPv6ProxyNDP" "IPv6ProxyNDPAddress"
162 "IPv6PrefixDelegation" "IPv6MTUBytes" "Bridge" "Bond" "VRF" "VLAN"
163 "IPVLAN" "MACVLAN" "VXLAN" "Tunnel" "ActiveSlave" "PrimarySlave"
164 "ConfigureWithoutCarrier"
165 ])
166 # Note: For DHCP the values both, none, v4, v6 are deprecated
167 (assertValueOneOf "DHCP" ["yes" "no" "ipv4" "ipv6" "both" "none" "v4" "v6"])
168 (assertValueOneOf "DHCPServer" boolValues)
169 (assertValueOneOf "LinkLocalAddressing" ["yes" "no" "ipv4" "ipv6"])
170 (assertValueOneOf "IPv4LLRoute" boolValues)
171 (assertValueOneOf "LLMNR" ["yes" "resolve" "no"])
172 (assertValueOneOf "MulticastDNS" ["yes" "resolve" "no"])
173 (assertValueOneOf "DNSOverTLS" ["opportunistic" "no"])
174 (assertValueOneOf "DNSSEC" ["yes" "allow-downgrade" "no"])
175 (assertValueOneOf "LLDP" ["yes" "routers-only" "no"])
176 (assertValueOneOf "EmitLLDP" ["yes" "no" "nearest-bridge" "non-tpmr-bridge" "customer-bridge"])
177 (assertValueOneOf "IPForward" ["yes" "no" "ipv4" "ipv6"])
178 (assertValueOneOf "IPMasquerade" boolValues)
179 (assertValueOneOf "IPv6PrivacyExtensions" ["yes" "no" "prefer-public" "kernel"])
180 (assertValueOneOf "IPv6AcceptRA" boolValues)
181 (assertValueOneOf "IPv4ProxyARP" boolValues)
182 (assertValueOneOf "IPv6ProxyNDP" boolValues)
183 (assertValueOneOf "IPv6PrefixDelegation" boolValues)
184 (assertValueOneOf "ActiveSlave" boolValues)
185 (assertValueOneOf "PrimarySlave" boolValues)
186 (assertValueOneOf "ConfigureWithoutCarrier" boolValues)
187 ];
188
189 checkAddress = checkUnitConfig "Address" [
190 (assertOnlyFields [
191 "Address" "Peer" "Broadcast" "Label" "PreferredLifetime" "Scope"
192 "HomeAddress" "DuplicateAddressDetection" "ManageTemporaryAddress"
193 "PrefixRoute" "AutoJoin"
194 ])
195 (assertHasField "Address")
196 (assertValueOneOf "PreferredLifetime" ["forever" "infinity" "0" 0])
197 (assertValueOneOf "HomeAddress" boolValues)
198 (assertValueOneOf "DuplicateAddressDetection" boolValues)
199 (assertValueOneOf "ManageTemporaryAddress" boolValues)
200 (assertValueOneOf "PrefixRoute" boolValues)
201 (assertValueOneOf "AutoJoin" boolValues)
202 ];
203
204 checkRoute = checkUnitConfig "Route" [
205 (assertOnlyFields [
206 "Gateway" "GatewayOnlink" "Destination" "Source" "Metric"
207 "IPv6Preference" "Scope" "PreferredSource" "Table" "Protocol" "Type"
208 "InitialCongestionWindow" "InitialAdvertisedReceiveWindow" "QuickAck"
209 "MTUBytes"
210 ])
211 (assertHasField "Gateway")
212 ];
213
214 checkDhcp = checkUnitConfig "DHCP" [
215 (assertOnlyFields [
216 "UseDNS" "UseNTP" "UseMTU" "Anonymize" "SendHostname" "UseHostname"
217 "Hostname" "UseDomains" "UseRoutes" "UseTimezone" "CriticalConnection"
218 "ClientIdentifier" "VendorClassIdentifier" "UserClass" "DUIDType"
219 "DUIDRawData" "IAID" "RequestBroadcast" "RouteMetric" "RouteTable"
220 "ListenPort" "RapidCommit"
221 ])
222 (assertValueOneOf "UseDNS" boolValues)
223 (assertValueOneOf "UseNTP" boolValues)
224 (assertValueOneOf "UseMTU" boolValues)
225 (assertValueOneOf "Anonymize" boolValues)
226 (assertValueOneOf "SendHostname" boolValues)
227 (assertValueOneOf "UseHostname" boolValues)
228 (assertValueOneOf "UseDomains" ["yes" "no" "route"])
229 (assertValueOneOf "UseRoutes" boolValues)
230 (assertValueOneOf "UseTimezone" boolValues)
231 (assertValueOneOf "CriticalConnection" boolValues)
232 (assertValueOneOf "RequestBroadcast" boolValues)
233 (assertInt "RouteTable")
234 (assertMinimum "RouteTable" 0)
235 (assertValueOneOf "RapidCommit" boolValues)
236 ];
237
238 checkDhcpServer = checkUnitConfig "DHCPServer" [
239 (assertOnlyFields [
240 "PoolOffset" "PoolSize" "DefaultLeaseTimeSec" "MaxLeaseTimeSec"
241 "EmitDNS" "DNS" "EmitNTP" "NTP" "EmitRouter" "EmitTimezone" "Timezone"
242 ])
243 (assertValueOneOf "EmitDNS" boolValues)
244 (assertValueOneOf "EmitNTP" boolValues)
245 (assertValueOneOf "EmitRouter" boolValues)
246 (assertValueOneOf "EmitTimezone" boolValues)
247 ];
248
249 # .network files have a [Link] section with different options than in .netlink files
250 checkNetworkLink = checkUnitConfig "Link" [
251 (assertOnlyFields [
252 "MACAddress" "MTUBytes" "ARP" "Unmanaged" "RequiredForOnline"
253 ])
254 (assertMacAddress "MACAddress")
255 (assertByteFormat "MTUBytes")
256 (assertValueOneOf "ARP" boolValues)
257 (assertValueOneOf "Unmanaged" boolValues)
258 (assertValueOneOf "RquiredForOnline" boolValues)
259 ];
260
261
262 commonNetworkOptions = {
263
264 enable = mkOption {
265 default = true;
266 type = types.bool;
267 description = ''
268 Whether to manage network configuration using <command>systemd-network</command>.
269 '';
270 };
271
272 matchConfig = mkOption {
273 default = {};
274 example = { Name = "eth0"; };
275 type = types.attrsOf unitOption;
276 description = ''
277 Each attribute in this set specifies an option in the
278 <literal>[Match]</literal> section of the unit. See
279 <citerefentry><refentrytitle>systemd.link</refentrytitle><manvolnum>5</manvolnum></citerefentry>
280 <citerefentry><refentrytitle>systemd.netdev</refentrytitle><manvolnum>5</manvolnum></citerefentry>
281 <citerefentry><refentrytitle>systemd.network</refentrytitle><manvolnum>5</manvolnum></citerefentry>
282 for details.
283 '';
284 };
285
286 extraConfig = mkOption {
287 default = "";
288 type = types.lines;
289 description = "Extra configuration append to unit";
290 };
291 };
292
293 linkOptions = commonNetworkOptions // {
294
295 linkConfig = mkOption {
296 default = {};
297 example = { MACAddress = "00:ff:ee:aa:cc:dd"; };
298 type = types.addCheck (types.attrsOf unitOption) checkLink;
299 description = ''
300 Each attribute in this set specifies an option in the
301 <literal>[Link]</literal> section of the unit. See
302 <citerefentry><refentrytitle>systemd.link</refentrytitle>
303 <manvolnum>5</manvolnum></citerefentry> for details.
304 '';
305 };
306
307 };
308
309 netdevOptions = commonNetworkOptions // {
310
311 netdevConfig = mkOption {
312 default = {};
313 example = { Name = "mybridge"; Kind = "bridge"; };
314 type = types.addCheck (types.attrsOf unitOption) checkNetdev;
315 description = ''
316 Each attribute in this set specifies an option in the
317 <literal>[Netdev]</literal> section of the unit. See
318 <citerefentry><refentrytitle>systemd.netdev</refentrytitle>
319 <manvolnum>5</manvolnum></citerefentry> for details.
320 '';
321 };
322
323 vlanConfig = mkOption {
324 default = {};
325 example = { Id = "4"; };
326 type = types.addCheck (types.attrsOf unitOption) checkVlan;
327 description = ''
328 Each attribute in this set specifies an option in the
329 <literal>[VLAN]</literal> section of the unit. See
330 <citerefentry><refentrytitle>systemd.netdev</refentrytitle>
331 <manvolnum>5</manvolnum></citerefentry> for details.
332 '';
333 };
334
335 macvlanConfig = mkOption {
336 default = {};
337 example = { Mode = "private"; };
338 type = types.addCheck (types.attrsOf unitOption) checkMacvlan;
339 description = ''
340 Each attribute in this set specifies an option in the
341 <literal>[MACVLAN]</literal> section of the unit. See
342 <citerefentry><refentrytitle>systemd.netdev</refentrytitle>
343 <manvolnum>5</manvolnum></citerefentry> for details.
344 '';
345 };
346
347 vxlanConfig = mkOption {
348 default = {};
349 example = { Id = "4"; };
350 type = types.addCheck (types.attrsOf unitOption) checkVxlan;
351 description = ''
352 Each attribute in this set specifies an option in the
353 <literal>[VXLAN]</literal> section of the unit. See
354 <citerefentry><refentrytitle>systemd.netdev</refentrytitle>
355 <manvolnum>5</manvolnum></citerefentry> for details.
356 '';
357 };
358
359 tunnelConfig = mkOption {
360 default = {};
361 example = { Remote = "192.168.1.1"; };
362 type = types.addCheck (types.attrsOf unitOption) checkTunnel;
363 description = ''
364 Each attribute in this set specifies an option in the
365 <literal>[Tunnel]</literal> section of the unit. See
366 <citerefentry><refentrytitle>systemd.netdev</refentrytitle>
367 <manvolnum>5</manvolnum></citerefentry> for details.
368 '';
369 };
370
371 peerConfig = mkOption {
372 default = {};
373 example = { Name = "veth2"; };
374 type = types.addCheck (types.attrsOf unitOption) checkPeer;
375 description = ''
376 Each attribute in this set specifies an option in the
377 <literal>[Peer]</literal> section of the unit. See
378 <citerefentry><refentrytitle>systemd.netdev</refentrytitle>
379 <manvolnum>5</manvolnum></citerefentry> for details.
380 '';
381 };
382
383 tunConfig = mkOption {
384 default = {};
385 example = { User = "openvpn"; };
386 type = types.addCheck (types.attrsOf unitOption) checkTun;
387 description = ''
388 Each attribute in this set specifies an option in the
389 <literal>[Tun]</literal> section of the unit. See
390 <citerefentry><refentrytitle>systemd.netdev</refentrytitle>
391 <manvolnum>5</manvolnum></citerefentry> for details.
392 '';
393 };
394
395 tapConfig = mkOption {
396 default = {};
397 example = { User = "openvpn"; };
398 type = types.addCheck (types.attrsOf unitOption) checkTap;
399 description = ''
400 Each attribute in this set specifies an option in the
401 <literal>[Tap]</literal> section of the unit. See
402 <citerefentry><refentrytitle>systemd.netdev</refentrytitle>
403 <manvolnum>5</manvolnum></citerefentry> for details.
404 '';
405 };
406
407 bondConfig = mkOption {
408 default = {};
409 example = { Mode = "802.3ad"; };
410 type = types.addCheck (types.attrsOf unitOption) checkBond;
411 description = ''
412 Each attribute in this set specifies an option in the
413 <literal>[Bond]</literal> section of the unit. See
414 <citerefentry><refentrytitle>systemd.netdev</refentrytitle>
415 <manvolnum>5</manvolnum></citerefentry> for details.
416 '';
417 };
418
419 };
420
421 addressOptions = {
422 options = {
423 addressConfig = mkOption {
424 default = {};
425 example = { Address = "192.168.0.100/24"; };
426 type = types.addCheck (types.attrsOf unitOption) checkAddress;
427 description = ''
428 Each attribute in this set specifies an option in the
429 <literal>[Address]</literal> section of the unit. See
430 <citerefentry><refentrytitle>systemd.network</refentrytitle>
431 <manvolnum>5</manvolnum></citerefentry> for details.
432 '';
433 };
434 };
435 };
436
437 routeOptions = {
438 options = {
439 routeConfig = mkOption {
440 default = {};
441 example = { Gateway = "192.168.0.1"; };
442 type = types.addCheck (types.attrsOf unitOption) checkRoute;
443 description = ''
444 Each attribute in this set specifies an option in the
445 <literal>[Route]</literal> section of the unit. See
446 <citerefentry><refentrytitle>systemd.network</refentrytitle>
447 <manvolnum>5</manvolnum></citerefentry> for details.
448 '';
449 };
450 };
451 };
452
453 networkOptions = commonNetworkOptions // {
454
455 networkConfig = mkOption {
456 default = {};
457 example = { Description = "My Network"; };
458 type = types.addCheck (types.attrsOf unitOption) checkNetwork;
459 description = ''
460 Each attribute in this set specifies an option in the
461 <literal>[Network]</literal> section of the unit. See
462 <citerefentry><refentrytitle>systemd.network</refentrytitle>
463 <manvolnum>5</manvolnum></citerefentry> for details.
464 '';
465 };
466
467 dhcpConfig = mkOption {
468 default = {};
469 example = { UseDNS = true; UseRoutes = true; };
470 type = types.addCheck (types.attrsOf unitOption) checkDhcp;
471 description = ''
472 Each attribute in this set specifies an option in the
473 <literal>[DHCP]</literal> section of the unit. See
474 <citerefentry><refentrytitle>systemd.network</refentrytitle>
475 <manvolnum>5</manvolnum></citerefentry> for details.
476 '';
477 };
478
479 dhcpServerConfig = mkOption {
480 default = {};
481 example = { PoolOffset = 50; EmitDNS = false; };
482 type = types.addCheck (types.attrsOf unitOption) checkDhcpServer;
483 description = ''
484 Each attribute in this set specifies an option in the
485 <literal>[DHCPServer]</literal> section of the unit. See
486 <citerefentry><refentrytitle>systemd.network</refentrytitle>
487 <manvolnum>5</manvolnum></citerefentry> for details.
488 '';
489 };
490
491 linkConfig = mkOption {
492 default = {};
493 example = { Unmanaged = true; };
494 type = types.addCheck (types.attrsOf unitOption) checkNetworkLink;
495 description = ''
496 Each attribute in this set specifies an option in the
497 <literal>[Link]</literal> section of the unit. See
498 <citerefentry><refentrytitle>systemd.network</refentrytitle>
499 <manvolnum>5</manvolnum></citerefentry> for details.
500 '';
501 };
502
503 name = mkOption {
504 type = types.nullOr types.str;
505 default = null;
506 description = ''
507 The name of the network interface to match against.
508 '';
509 };
510
511 DHCP = mkOption {
512 type = types.nullOr types.str;
513 default = null;
514 description = ''
515 Whether to enable DHCP on the interfaces matched.
516 '';
517 };
518
519 domains = mkOption {
520 type = types.nullOr (types.listOf types.str);
521 default = null;
522 description = ''
523 A list of domains to pass to the network config.
524 '';
525 };
526
527 address = mkOption {
528 default = [ ];
529 type = types.listOf types.str;
530 description = ''
531 A list of addresses to be added to the network section of the
532 unit. See <citerefentry><refentrytitle>systemd.network</refentrytitle>
533 <manvolnum>5</manvolnum></citerefentry> for details.
534 '';
535 };
536
537 gateway = mkOption {
538 default = [ ];
539 type = types.listOf types.str;
540 description = ''
541 A list of gateways to be added to the network section of the
542 unit. See <citerefentry><refentrytitle>systemd.network</refentrytitle>
543 <manvolnum>5</manvolnum></citerefentry> for details.
544 '';
545 };
546
547 dns = mkOption {
548 default = [ ];
549 type = types.listOf types.str;
550 description = ''
551 A list of dns servers to be added to the network section of the
552 unit. See <citerefentry><refentrytitle>systemd.network</refentrytitle>
553 <manvolnum>5</manvolnum></citerefentry> for details.
554 '';
555 };
556
557 ntp = mkOption {
558 default = [ ];
559 type = types.listOf types.str;
560 description = ''
561 A list of ntp servers to be added to the network section of the
562 unit. See <citerefentry><refentrytitle>systemd.network</refentrytitle>
563 <manvolnum>5</manvolnum></citerefentry> for details.
564 '';
565 };
566
567 bridge = mkOption {
568 default = [ ];
569 type = types.listOf types.str;
570 description = ''
571 A list of bridge interfaces to be added to the network section of the
572 unit. See <citerefentry><refentrytitle>systemd.network</refentrytitle>
573 <manvolnum>5</manvolnum></citerefentry> for details.
574 '';
575 };
576
577 bond = mkOption {
578 default = [ ];
579 type = types.listOf types.str;
580 description = ''
581 A list of bond interfaces to be added to the network section of the
582 unit. See <citerefentry><refentrytitle>systemd.network</refentrytitle>
583 <manvolnum>5</manvolnum></citerefentry> for details.
584 '';
585 };
586
587 vrf = mkOption {
588 default = [ ];
589 type = types.listOf types.str;
590 description = ''
591 A list of vrf interfaces to be added to the network section of the
592 unit. See <citerefentry><refentrytitle>systemd.network</refentrytitle>
593 <manvolnum>5</manvolnum></citerefentry> for details.
594 '';
595 };
596
597 vlan = mkOption {
598 default = [ ];
599 type = types.listOf types.str;
600 description = ''
601 A list of vlan interfaces to be added to the network section of the
602 unit. See <citerefentry><refentrytitle>systemd.network</refentrytitle>
603 <manvolnum>5</manvolnum></citerefentry> for details.
604 '';
605 };
606
607 macvlan = mkOption {
608 default = [ ];
609 type = types.listOf types.str;
610 description = ''
611 A list of macvlan interfaces to be added to the network section of the
612 unit. See <citerefentry><refentrytitle>systemd.network</refentrytitle>
613 <manvolnum>5</manvolnum></citerefentry> for details.
614 '';
615 };
616
617 vxlan = mkOption {
618 default = [ ];
619 type = types.listOf types.str;
620 description = ''
621 A list of vxlan interfaces to be added to the network section of the
622 unit. See <citerefentry><refentrytitle>systemd.network</refentrytitle>
623 <manvolnum>5</manvolnum></citerefentry> for details.
624 '';
625 };
626
627 tunnel = mkOption {
628 default = [ ];
629 type = types.listOf types.str;
630 description = ''
631 A list of tunnel interfaces to be added to the network section of the
632 unit. See <citerefentry><refentrytitle>systemd.network</refentrytitle>
633 <manvolnum>5</manvolnum></citerefentry> for details.
634 '';
635 };
636
637 addresses = mkOption {
638 default = [ ];
639 type = with types; listOf (submodule addressOptions);
640 description = ''
641 A list of address sections to be added to the unit. See
642 <citerefentry><refentrytitle>systemd.network</refentrytitle>
643 <manvolnum>5</manvolnum></citerefentry> for details.
644 '';
645 };
646
647 routes = mkOption {
648 default = [ ];
649 type = with types; listOf (submodule routeOptions);
650 description = ''
651 A list of route sections to be added to the unit. See
652 <citerefentry><refentrytitle>systemd.network</refentrytitle>
653 <manvolnum>5</manvolnum></citerefentry> for details.
654 '';
655 };
656
657 };
658
659 networkConfig = { config, ... }: {
660 config = {
661 matchConfig = optionalAttrs (config.name != null) {
662 Name = config.name;
663 };
664 networkConfig = optionalAttrs (config.DHCP != null) {
665 DHCP = config.DHCP;
666 } // optionalAttrs (config.domains != null) {
667 Domains = concatStringsSep " " config.domains;
668 };
669 };
670 };
671
672 commonMatchText = def: ''
673 [Match]
674 ${attrsToSection def.matchConfig}
675 '';
676
677 linkToUnit = name: def:
678 { inherit (def) enable;
679 text = commonMatchText def +
680 ''
681 [Link]
682 ${attrsToSection def.linkConfig}
683
684 ${def.extraConfig}
685 '';
686 };
687
688 netdevToUnit = name: def:
689 { inherit (def) enable;
690 text = commonMatchText def +
691 ''
692 [NetDev]
693 ${attrsToSection def.netdevConfig}
694
695 ${optionalString (def.vlanConfig != { }) ''
696 [VLAN]
697 ${attrsToSection def.vlanConfig}
698
699 ''}
700 ${optionalString (def.macvlanConfig != { }) ''
701 [MACVLAN]
702 ${attrsToSection def.macvlanConfig}
703
704 ''}
705 ${optionalString (def.vxlanConfig != { }) ''
706 [VXLAN]
707 ${attrsToSection def.vxlanConfig}
708
709 ''}
710 ${optionalString (def.tunnelConfig != { }) ''
711 [Tunnel]
712 ${attrsToSection def.tunnelConfig}
713
714 ''}
715 ${optionalString (def.peerConfig != { }) ''
716 [Peer]
717 ${attrsToSection def.peerConfig}
718
719 ''}
720 ${optionalString (def.tunConfig != { }) ''
721 [Tun]
722 ${attrsToSection def.tunConfig}
723
724 ''}
725 ${optionalString (def.tapConfig != { }) ''
726 [Tap]
727 ${attrsToSection def.tapConfig}
728
729 ''}
730 ${optionalString (def.bondConfig != { }) ''
731 [Bond]
732 ${attrsToSection def.bondConfig}
733
734 ''}
735 ${def.extraConfig}
736 '';
737 };
738
739 networkToUnit = name: def:
740 { inherit (def) enable;
741 text = commonMatchText def +
742 ''
743 ${optionalString (def.linkConfig != { }) ''
744 [Link]
745 ${attrsToSection def.linkConfig}
746
747 ''}
748
749 [Network]
750 ${attrsToSection def.networkConfig}
751 ${concatStringsSep "\n" (map (s: "Address=${s}") def.address)}
752 ${concatStringsSep "\n" (map (s: "Gateway=${s}") def.gateway)}
753 ${concatStringsSep "\n" (map (s: "DNS=${s}") def.dns)}
754 ${concatStringsSep "\n" (map (s: "NTP=${s}") def.ntp)}
755 ${concatStringsSep "\n" (map (s: "Bridge=${s}") def.bridge)}
756 ${concatStringsSep "\n" (map (s: "Bond=${s}") def.bond)}
757 ${concatStringsSep "\n" (map (s: "VRF=${s}") def.vrf)}
758 ${concatStringsSep "\n" (map (s: "VLAN=${s}") def.vlan)}
759 ${concatStringsSep "\n" (map (s: "MACVLAN=${s}") def.macvlan)}
760 ${concatStringsSep "\n" (map (s: "VXLAN=${s}") def.vxlan)}
761 ${concatStringsSep "\n" (map (s: "Tunnel=${s}") def.tunnel)}
762
763 ${optionalString (def.dhcpConfig != { }) ''
764 [DHCP]
765 ${attrsToSection def.dhcpConfig}
766
767 ''}
768 ${optionalString (def.dhcpServerConfig != { }) ''
769 [DHCPServer]
770 ${attrsToSection def.dhcpServerConfig}
771
772 ''}
773 ${flip concatMapStrings def.addresses (x: ''
774 [Address]
775 ${attrsToSection x.addressConfig}
776
777 '')}
778 ${flip concatMapStrings def.routes (x: ''
779 [Route]
780 ${attrsToSection x.routeConfig}
781
782 '')}
783 ${def.extraConfig}
784 '';
785 };
786
787 unitFiles = map (name: {
788 target = "systemd/network/${name}";
789 source = "${cfg.units.${name}.unit}/${name}";
790 }) (attrNames cfg.units);
791in
792
793{
794
795 options = {
796
797 systemd.network.enable = mkOption {
798 default = false;
799 type = types.bool;
800 description = ''
801 Whether to enable networkd or not.
802 '';
803 };
804
805 systemd.network.links = mkOption {
806 default = {};
807 type = with types; attrsOf (submodule [ { options = linkOptions; } ]);
808 description = "Definition of systemd network links.";
809 };
810
811 systemd.network.netdevs = mkOption {
812 default = {};
813 type = with types; attrsOf (submodule [ { options = netdevOptions; } ]);
814 description = "Definition of systemd network devices.";
815 };
816
817 systemd.network.networks = mkOption {
818 default = {};
819 type = with types; attrsOf (submodule [ { options = networkOptions; } networkConfig ]);
820 description = "Definition of systemd networks.";
821 };
822
823 systemd.network.units = mkOption {
824 description = "Definition of networkd units.";
825 default = {};
826 type = with types; attrsOf (submodule (
827 { name, config, ... }:
828 { options = concreteUnitOptions;
829 config = {
830 unit = mkDefault (makeUnit name config);
831 };
832 }));
833 };
834
835 };
836
837 config = mkIf config.systemd.network.enable {
838
839 systemd.additionalUpstreamSystemUnits = [
840 "systemd-networkd.service" "systemd-networkd-wait-online.service"
841 ];
842
843 systemd.network.units = mapAttrs' (n: v: nameValuePair "${n}.link" (linkToUnit n v)) cfg.links
844 // mapAttrs' (n: v: nameValuePair "${n}.netdev" (netdevToUnit n v)) cfg.netdevs
845 // mapAttrs' (n: v: nameValuePair "${n}.network" (networkToUnit n v)) cfg.networks;
846
847 environment.etc = unitFiles;
848
849 systemd.services.systemd-networkd = {
850 wantedBy = [ "multi-user.target" ];
851 restartTriggers = map (f: f.source) (unitFiles);
852 # prevent race condition with interface renaming (#39069)
853 requires = [ "systemd-udev-settle.service" ];
854 after = [ "systemd-udev-settle.service" ];
855 };
856
857 systemd.services.systemd-networkd-wait-online = {
858 wantedBy = [ "network-online.target" ];
859 };
860
861 systemd.services."systemd-network-wait-online@" = {
862 description = "Wait for Network Interface %I to be Configured";
863 conflicts = [ "shutdown.target" ];
864 requisite = [ "systemd-networkd.service" ];
865 after = [ "systemd-networkd.service" ];
866 serviceConfig = {
867 Type = "oneshot";
868 RemainAfterExit = true;
869 ExecStart = "${config.systemd.package}/lib/systemd/systemd-networkd-wait-online -i %I";
870 };
871 };
872
873 services.resolved.enable = mkDefault true;
874 };
875}