summaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
authorGregor Kleen <gkleen@yggdrasil.li>2022-07-29 11:07:19 +0200
committerGregor Kleen <gkleen@yggdrasil.li>2022-07-29 11:07:19 +0200
commitbda1a6b603a3944223707a6d090622b574ea7505 (patch)
treee223290d0c3e4f91862f429e65f083d3ecb3b1cd /modules
parentece84e99219c1d57dcee7ee93045edc81cd0cbc7 (diff)
downloadnixos-bda1a6b603a3944223707a6d090622b574ea7505.tar
nixos-bda1a6b603a3944223707a6d090622b574ea7505.tar.gz
nixos-bda1a6b603a3944223707a6d090622b574ea7505.tar.bz2
nixos-bda1a6b603a3944223707a6d090622b574ea7505.tar.xz
nixos-bda1a6b603a3944223707a6d090622b574ea7505.zip
bump & vpn
Diffstat (limited to 'modules')
-rw-r--r--modules/netns.nix155
-rw-r--r--modules/networkd/default.nix1687
-rw-r--r--modules/networkd/systemd-lib.nix241
-rw-r--r--modules/networkd/systemd-unit-options.nix536
-rw-r--r--modules/yggdrasil-wg/default.nix11
5 files changed, 158 insertions, 2472 deletions
diff --git a/modules/netns.nix b/modules/netns.nix
new file mode 100644
index 00000000..18e066e5
--- /dev/null
+++ b/modules/netns.nix
@@ -0,0 +1,155 @@
1{ pkgs, config, lib, ... }:
2
3with lib;
4
5let
6 cfg = config.networking.namespaces;
7
8 containerOpts = { name, ... }: {
9 options = {
10 config = mkOption {
11 description = ''
12 A specification of the desired configuration of this
13 container, as a NixOS module.
14 '';
15 type = let
16 confPkgs = if config.pkgs == null then pkgs else config.pkgs;
17 in mkOptionType {
18 name = "Toplevel NixOS config";
19 merge = loc: defs: (import (pkgs.path + "/nixos/lib/eval-config.nix") {
20 inherit (config.nixpkgs.localSystem) system;
21 inherit pkgs;
22 baseModules = import (pkgs.path + "/nixos/modules/module-list.nix");
23 inherit (pkgs) lib;
24 modules =
25 let
26 extraConfig = {
27 _file = "module at ${__curPos.file}:${toString __curPos.line}";
28 config = {
29 boot.isContainer = true;
30 networking.hostName = mkDefault name;
31 system.stateVersion = config.system.nixos.release; # No state
32 };
33 };
34 in [ extraConfig ] ++ (map (x: x.value) defs);
35 prefix = [ "containers" "upstream" ];
36 }).config;
37 };
38 };
39
40 netns = mkOption {
41 example = "upstream";
42 type = types.str;
43 description = "Name of network namespace to put the container in.";
44 };
45 };
46
47 config = {
48 netns = mkDefault name;
49 };
50 };
51
52 mkContainerService = containerName: containerCfg: nameValuePair "netns-container@${containerName}" {
53 after = ["network.target" "systemd-udevd.service" "systemd-sysctl.service" "netns@${containerCfg.netns}.service"];
54 bindsTo = ["netns@${containerCfg.netns}.service"];
55 before = ["shutdown.target"];
56 wants = ["network.target"];
57 conflicts = ["shutdown.target"];
58
59 path = with pkgs; [ iproute config.systemd.package ];
60
61 serviceConfig = {
62 SyslogIdentifier = "netns container ${containerName}";
63 Type = "notify";
64
65 RestartForceExitStatus = "133";
66 SuccessExitStatus = "133";
67
68 Restart = "no";
69
70 DevicePolicy = "closed";
71
72 RuntimeDirectory = ["netns-containers/${containerName}"];
73 };
74 unitConfig = {
75 ConditionCapability = ["CAP_SYS_TTY_CONFIG" "CAP_NET_ADMIN" "CAP_NET_RAW" "CAP_SYS_ADMIN"];
76 };
77
78 script = let
79 containerInit = pkgs.writeScript "container-init" ''
80 #!${pkgs.runtimeShell} -e
81 exec "$1"
82 '';
83 in ''
84 mkdir -p -m 0755 "''${RUNTIME_DIRECTORY}/etc" "''${RUNTIME_DIRECTORY}/var/lib"
85 mkdir -p -m 0700 "''${RUNTIME_DIRECTORY}/var/lib/private" "''${RUNTIME_DIRECTORY}/root" /run/containers
86 if ! [ -e "''${RUNTIME_DIRECTORY}/etc/os-release" ]; then
87 touch "''${RUNTIME_DIRECTORY}/etc/os-release"
88 fi
89 if ! [ -e "''${RUNTIME_DIRECTORY}/etc/machine-id" ]; then
90 touch "''${RUNTIME_DIRECTORY}/etc/machine-id"
91 fi
92 mkdir -p -m 0755 \
93 "/nix/var/nix/profiles/per-container/${containerName}" \
94 "/nix/var/nix/gcroots/per-container/${containerName}"
95 credsBind=""
96 if [ -n "''${CREDENTIALS_DIRECTORY}" ]; then
97 credsBind="--bind-ro=''${CREDENTIALS_DIRECTORY}:/run/host/credentials"
98 fi
99 # Run systemd-nspawn without startup notification (we'll
100 # wait for the container systemd to signal readiness).
101 exec ${config.systemd.package}/bin/systemd-nspawn \
102 --keep-unit \
103 -M "${containerName}" -D "''${RUNTIME_DIRECTORY}" \
104 --notify-ready=yes \
105 --bind-ro=/nix/store \
106 --bind-ro=/nix/var/nix/db \
107 --bind-ro=/nix/var/nix/daemon-socket \
108 $credsBind \
109 --bind="/nix/var/nix/profiles/per-container/${containerName}:/nix/var/nix/profiles" \
110 --bind="/nix/var/nix/gcroots/per-container/${containerName}:/nix/var/nix/gcroots" \
111 --setenv PATH="$PATH" \
112 --capability=CAP_SYS_TTY_CONFIG,CAP_NET_ADMIN,CAP_NET_RAW,CAP_SYS_ADMIN \
113 --ephemeral \
114 --network-namespace-path=/run/netns/${containerCfg.netns} \
115 ${containerInit} "${containerCfg.config.system.build.toplevel}/init"
116 '';
117 };
118in {
119 options = {
120 networking.namespaces = {
121 enable = mkEnableOption "netns@ service template";
122
123 containers = mkOption {
124 default = {};
125 type = types.attrsOf (types.submodule containerOpts);
126 };
127 };
128 };
129
130 config = {
131 assertions = [
132 { assertion = cfg.containers != {} -> cfg.enable; message = "netns containers require netns@ service template"; }
133 ];
134
135 systemd.services = {
136 "netns@" = mkIf cfg.enable {
137 description = "%I network namspace";
138 before = [ "network-pre.target" ];
139 wants = [ "network-pre.target" ];
140 path = with pkgs; [ iproute utillinux ];
141 serviceConfig = {
142 Type = "oneshot";
143 RemainAfterExit = true;
144 PrivateNetwork = true;
145 ExecStart = "${pkgs.writers.writeDash "netns-up" ''
146 ip netns add "$1"
147 umount /var/run/netns/"$1"
148 mount --bind /proc/self/ns/net /var/run/netns/"$1"
149 ''} %I";
150 ExecStop = "${pkgs.iproute}/bin/ip netns del %I";
151 };
152 };
153 } // mapAttrs' mkContainerService cfg.containers;
154 };
155}
diff --git a/modules/networkd/default.nix b/modules/networkd/default.nix
deleted file mode 100644
index f78a9aee..00000000
--- a/modules/networkd/default.nix
+++ /dev/null
@@ -1,1687 +0,0 @@
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 check = {
12
13 link = {
14
15 sectionLink = checkUnitConfig "Link" [
16 (assertOnlyFields [
17 "Description"
18 "Alias"
19 "MACAddressPolicy"
20 "MACAddress"
21 "NamePolicy"
22 "Name"
23 "AlternativeNamesPolicy"
24 "AlternativeName"
25 "MTUBytes"
26 "BitsPerSecond"
27 "Duplex"
28 "AutoNegotiation"
29 "WakeOnLan"
30 "Port"
31 "Advertise"
32 "ReceiveChecksumOffload"
33 "TransmitChecksumOffload"
34 "TCPSegmentationOffload"
35 "TCP6SegmentationOffload"
36 "GenericSegmentationOffload"
37 "GenericReceiveOffload"
38 "LargeReceiveOffload"
39 "RxChannels"
40 "TxChannels"
41 "OtherChannels"
42 "CombinedChannels"
43 "RxBufferSize"
44 "TxBufferSize"
45 ])
46 (assertValueOneOf "MACAddressPolicy" ["persistent" "random" "none"])
47 (assertMacAddress "MACAddress")
48 (assertByteFormat "MTUBytes")
49 (assertByteFormat "BitsPerSecond")
50 (assertValueOneOf "Duplex" ["half" "full"])
51 (assertValueOneOf "AutoNegotiation" boolValues)
52 (assertValueOneOf "WakeOnLan" ["phy" "unicast" "multicast" "broadcast" "arp" "magic" "secureon" "off"])
53 (assertValueOneOf "Port" ["tp" "aui" "bnc" "mii" "fibre"])
54 (assertValueOneOf "ReceiveChecksumOffload" boolValues)
55 (assertValueOneOf "TransmitChecksumOffload" boolValues)
56 (assertValueOneOf "TCPSegmentationOffload" boolValues)
57 (assertValueOneOf "TCP6SegmentationOffload" boolValues)
58 (assertValueOneOf "GenericSegmentationOffload" boolValues)
59 (assertValueOneOf "GenericReceiveOffload" boolValues)
60 (assertValueOneOf "LargeReceiveOffload" boolValues)
61 (assertInt "RxChannels")
62 (assertRange "RxChannels" 1 4294967295)
63 (assertInt "TxChannels")
64 (assertRange "TxChannels" 1 4294967295)
65 (assertInt "OtherChannels")
66 (assertRange "OtherChannels" 1 4294967295)
67 (assertInt "CombinedChannels")
68 (assertRange "CombinedChannels" 1 4294967295)
69 (assertInt "RxBufferSize")
70 (assertInt "TxBufferSize")
71 ];
72 };
73
74 netdev = let
75
76 tunChecks = [
77 (assertOnlyFields [
78 "MultiQueue"
79 "PacketInfo"
80 "VNetHeader"
81 "User"
82 "Group"
83 ])
84 (assertValueOneOf "MultiQueue" boolValues)
85 (assertValueOneOf "PacketInfo" boolValues)
86 (assertValueOneOf "VNetHeader" boolValues)
87 ];
88 in {
89
90 sectionNetdev = checkUnitConfig "Netdev" [
91 (assertOnlyFields [
92 "Description"
93 "Name"
94 "Kind"
95 "MTUBytes"
96 "MACAddress"
97 ])
98 (assertHasField "Name")
99 (assertMaxLength "Name" 15)
100 (assertHasField "Kind")
101 (assertValueOneOf "Kind" [
102 "bond"
103 "bridge"
104 "dummy"
105 "gre"
106 "gretap"
107 "erspan"
108 "ip6gre"
109 "ip6tnl"
110 "ip6gretap"
111 "ipip"
112 "ipvlan"
113 "macvlan"
114 "macvtap"
115 "sit"
116 "tap"
117 "tun"
118 "veth"
119 "vlan"
120 "vti"
121 "vti6"
122 "vxlan"
123 "geneve"
124 "l2tp"
125 "macsec"
126 "vrf"
127 "vcan"
128 "vxcan"
129 "wireguard"
130 "netdevsim"
131 "nlmon"
132 "fou"
133 "xfrm"
134 "ifb"
135 "bareudp"
136 "batadv"
137 ])
138 (assertByteFormat "MTUBytes")
139 (assertMacAddress "MACAddress")
140 ];
141
142 sectionVLAN = checkUnitConfig "VLAN" [
143 (assertOnlyFields [
144 "Id"
145 "GVRP"
146 "MVRP"
147 "LooseBinding"
148 "ReorderHeader"
149 ])
150 (assertInt "Id")
151 (assertRange "Id" 0 4094)
152 (assertValueOneOf "GVRP" boolValues)
153 (assertValueOneOf "MVRP" boolValues)
154 (assertValueOneOf "LooseBinding" boolValues)
155 (assertValueOneOf "ReorderHeader" boolValues)
156 ];
157
158 sectionMACVLAN = checkUnitConfig "MACVLAN" [
159 (assertOnlyFields [
160 "Mode"
161 ])
162 (assertValueOneOf "Mode" ["private" "vepa" "bridge" "passthru"])
163 ];
164
165 sectionVXLAN = checkUnitConfig "VXLAN" [
166 (assertOnlyFields [
167 "VNI"
168 "Remote"
169 "Local"
170 "Group"
171 "TOS"
172 "TTL"
173 "MacLearning"
174 "FDBAgeingSec"
175 "MaximumFDBEntries"
176 "ReduceARPProxy"
177 "L2MissNotification"
178 "L3MissNotification"
179 "RouteShortCircuit"
180 "UDPChecksum"
181 "UDP6ZeroChecksumTx"
182 "UDP6ZeroChecksumRx"
183 "RemoteChecksumTx"
184 "RemoteChecksumRx"
185 "GroupPolicyExtension"
186 "GenericProtocolExtension"
187 "DestinationPort"
188 "PortRange"
189 "FlowLabel"
190 "IPDoNotFragment"
191 ])
192 (assertInt "VNI")
193 (assertRange "VNI" 1 16777215)
194 (assertValueOneOf "MacLearning" boolValues)
195 (assertInt "MaximumFDBEntries")
196 (assertValueOneOf "ReduceARPProxy" boolValues)
197 (assertValueOneOf "L2MissNotification" boolValues)
198 (assertValueOneOf "L3MissNotification" boolValues)
199 (assertValueOneOf "RouteShortCircuit" boolValues)
200 (assertValueOneOf "UDPChecksum" boolValues)
201 (assertValueOneOf "UDP6ZeroChecksumTx" boolValues)
202 (assertValueOneOf "UDP6ZeroChecksumRx" boolValues)
203 (assertValueOneOf "RemoteChecksumTx" boolValues)
204 (assertValueOneOf "RemoteChecksumRx" boolValues)
205 (assertValueOneOf "GroupPolicyExtension" boolValues)
206 (assertValueOneOf "GenericProtocolExtension" boolValues)
207 (assertInt "FlowLabel")
208 (assertRange "FlowLabel" 0 1048575)
209 (assertValueOneOf "IPDoNotFragment" (boolValues + ["inherit"]))
210 ];
211
212 sectionTunnel = checkUnitConfig "Tunnel" [
213 (assertOnlyFields [
214 "Local"
215 "Remote"
216 "TOS"
217 "TTL"
218 "DiscoverPathMTU"
219 "IPv6FlowLabel"
220 "CopyDSCP"
221 "EncapsulationLimit"
222 "Key"
223 "InputKey"
224 "OutputKey"
225 "Mode"
226 "Independent"
227 "AssignToLoopback"
228 "AllowLocalRemote"
229 "FooOverUDP"
230 "FOUDestinationPort"
231 "FOUSourcePort"
232 "Encapsulation"
233 "IPv6RapidDeploymentPrefix"
234 "ISATAP"
235 "SerializeTunneledPackets"
236 "ERSPANIndex"
237 ])
238 (assertInt "TTL")
239 (assertRange "TTL" 0 255)
240 (assertValueOneOf "DiscoverPathMTU" boolValues)
241 (assertValueOneOf "CopyDSCP" boolValues)
242 (assertValueOneOf "Mode" ["ip6ip6" "ipip6" "any"])
243 (assertValueOneOf "Independent" boolValues)
244 (assertValueOneOf "AssignToLoopback" boolValues)
245 (assertValueOneOf "AllowLocalRemote" boolValues)
246 (assertValueOneOf "FooOverUDP" boolValues)
247 (assertPort "FOUDestinationPort")
248 (assertPort "FOUSourcePort")
249 (assertValueOneOf "Encapsulation" ["FooOverUDP" "GenericUDPEncapsulation"])
250 (assertValueOneOf "ISATAP" boolValues)
251 (assertValueOneOf "SerializeTunneledPackets" boolValues)
252 (assertInt "ERSPANIndex")
253 (assertRange "ERSPANIndex" 1 1048575)
254 ];
255
256 sectionPeer = checkUnitConfig "Peer" [
257 (assertOnlyFields [
258 "Name"
259 "MACAddress"
260 ])
261 (assertMacAddress "MACAddress")
262 ];
263
264 sectionTun = checkUnitConfig "Tun" tunChecks;
265
266 sectionTap = checkUnitConfig "Tap" tunChecks;
267
268 # NOTE The PrivateKey directive is missing on purpose here, please
269 # do not add it to this list. The nix store is world-readable let's
270 # refrain ourselves from providing a footgun.
271 sectionWireGuard = checkUnitConfig "WireGuard" [
272 (assertOnlyFields [
273 "PrivateKeyFile"
274 "ListenPort"
275 "FirewallMark"
276 ])
277 (assertInt "FirewallMark")
278 (assertRange "FirewallMark" 1 4294967295)
279 ];
280
281 # NOTE The PresharedKey directive is missing on purpose here, please
282 # do not add it to this list. The nix store is world-readable,let's
283 # refrain ourselves from providing a footgun.
284 sectionWireGuardPeer = checkUnitConfig "WireGuardPeer" [
285 (assertOnlyFields [
286 "PublicKey"
287 "PresharedKeyFile"
288 "AllowedIPs"
289 "Endpoint"
290 "PersistentKeepalive"
291 ])
292 (assertInt "PersistentKeepalive")
293 (assertRange "PersistentKeepalive" 0 65535)
294 ];
295
296 sectionBond = checkUnitConfig "Bond" [
297 (assertOnlyFields [
298 "Mode"
299 "TransmitHashPolicy"
300 "LACPTransmitRate"
301 "MIIMonitorSec"
302 "UpDelaySec"
303 "DownDelaySec"
304 "LearnPacketIntervalSec"
305 "AdSelect"
306 "AdActorSystemPriority"
307 "AdUserPortKey"
308 "AdActorSystem"
309 "FailOverMACPolicy"
310 "ARPValidate"
311 "ARPIntervalSec"
312 "ARPIPTargets"
313 "ARPAllTargets"
314 "PrimaryReselectPolicy"
315 "ResendIGMP"
316 "PacketsPerSlave"
317 "GratuitousARP"
318 "AllSlavesActive"
319 "DynamicTransmitLoadBalancing"
320 "MinLinks"
321 ])
322 (assertValueOneOf "Mode" [
323 "balance-rr"
324 "active-backup"
325 "balance-xor"
326 "broadcast"
327 "802.3ad"
328 "balance-tlb"
329 "balance-alb"
330 ])
331 (assertValueOneOf "TransmitHashPolicy" [
332 "layer2"
333 "layer3+4"
334 "layer2+3"
335 "encap2+3"
336 "encap3+4"
337 ])
338 (assertValueOneOf "LACPTransmitRate" ["slow" "fast"])
339 (assertValueOneOf "AdSelect" ["stable" "bandwidth" "count"])
340 (assertInt "AdActorSystemPriority")
341 (assertRange "AdActorSystemPriority" 1 65535)
342 (assertInt "AdUserPortKey")
343 (assertRange "AdUserPortKey" 0 1023)
344 (assertValueOneOf "FailOverMACPolicy" ["none" "active" "follow"])
345 (assertValueOneOf "ARPValidate" ["none" "active" "backup" "all"])
346 (assertValueOneOf "ARPAllTargets" ["any" "all"])
347 (assertValueOneOf "PrimaryReselectPolicy" ["always" "better" "failure"])
348 (assertInt "ResendIGMP")
349 (assertRange "ResendIGMP" 0 255)
350 (assertInt "PacketsPerSlave")
351 (assertRange "PacketsPerSlave" 0 65535)
352 (assertInt "GratuitousARP")
353 (assertRange "GratuitousARP" 0 255)
354 (assertValueOneOf "AllSlavesActive" boolValues)
355 (assertValueOneOf "DynamicTransmitLoadBalancing" boolValues)
356 (assertInt "MinLinks")
357 (assertMinimum "MinLinks" 0)
358 ];
359
360 sectionXfrm = checkUnitConfig "Xfrm" [
361 (assertOnlyFields [
362 "InterfaceId"
363 "Independent"
364 ])
365 (assertInt "InterfaceId")
366 (assertRange "InterfaceId" 1 4294967295)
367 (assertValueOneOf "Independent" boolValues)
368 ];
369
370 sectionVRF = checkUnitConfig "VRF" [
371 (assertOnlyFields [
372 "Table"
373 ])
374 (assertInt "Table")
375 (assertMinimum "Table" 0)
376 ];
377 };
378
379 network = {
380
381 sectionLink = checkUnitConfig "Link" [
382 (assertOnlyFields [
383 "MACAddress"
384 "MTUBytes"
385 "ARP"
386 "Multicast"
387 "AllMulticast"
388 "Unmanaged"
389 "RequiredForOnline"
390 "ActivationPolicy"
391 ])
392 (assertMacAddress "MACAddress")
393 (assertByteFormat "MTUBytes")
394 (assertValueOneOf "ARP" boolValues)
395 (assertValueOneOf "Multicast" boolValues)
396 (assertValueOneOf "AllMulticast" boolValues)
397 (assertValueOneOf "Unmanaged" boolValues)
398 (assertValueOneOf "RequiredForOnline" (boolValues ++ [
399 "missing"
400 "off"
401 "no-carrier"
402 "dormant"
403 "degraded-carrier"
404 "carrier"
405 "degraded"
406 "enslaved"
407 "routable"
408 ]))
409 (assertValueOneOf "ActivationPolicy" ([
410 "up"
411 "always-up"
412 "manual"
413 "always-down"
414 "down"
415 "bound"
416 ]))
417 ];
418
419 sectionNetwork = checkUnitConfig "Network" [
420 (assertOnlyFields [
421 "Description"
422 "DHCP"
423 "DHCPServer"
424 "LinkLocalAddressing"
425 "IPv4LLRoute"
426 "DefaultRouteOnDevice"
427 "IPv6Token"
428 "LLMNR"
429 "MulticastDNS"
430 "DNSOverTLS"
431 "DNSSEC"
432 "DNSSECNegativeTrustAnchors"
433 "LLDP"
434 "EmitLLDP"
435 "BindCarrier"
436 "Address"
437 "Gateway"
438 "DNS"
439 "Domains"
440 "DNSDefaultRoute"
441 "NTP"
442 "IPForward"
443 "IPMasquerade"
444 "IPv6PrivacyExtensions"
445 "IPv6AcceptRA"
446 "IPv6DuplicateAddressDetection"
447 "IPv6HopLimit"
448 "IPv4ProxyARP"
449 "IPv6ProxyNDP"
450 "IPv6ProxyNDPAddress"
451 "IPv6SendRA"
452 "DHCPv6PrefixDelegation"
453 "IPv6MTUBytes"
454 "BatmanAdvanced"
455 "Bridge"
456 "Bond"
457 "VRF"
458 "VLAN"
459 "IPVLAN"
460 "MACVLAN"
461 "VXLAN"
462 "Tunnel"
463 "MACsec"
464 "ActiveSlave"
465 "PrimarySlave"
466 "ConfigureWithoutCarrier"
467 "IgnoreCarrierLoss"
468 "Xfrm"
469 "KeepConfiguration"
470 ])
471 # Note: For DHCP the values both, none, v4, v6 are deprecated
472 (assertValueOneOf "DHCP" ["yes" "no" "ipv4" "ipv6"])
473 (assertValueOneOf "DHCPServer" boolValues)
474 (assertValueOneOf "LinkLocalAddressing" ["yes" "no" "ipv4" "ipv6" "fallback" "ipv4-fallback"])
475 (assertValueOneOf "IPv4LLRoute" boolValues)
476 (assertValueOneOf "DefaultRouteOnDevice" boolValues)
477 (assertValueOneOf "LLMNR" (boolValues ++ ["resolve"]))
478 (assertValueOneOf "MulticastDNS" (boolValues ++ ["resolve"]))
479 (assertValueOneOf "DNSOverTLS" (boolValues ++ ["opportunistic"]))
480 (assertValueOneOf "DNSSEC" (boolValues ++ ["allow-downgrade"]))
481 (assertValueOneOf "LLDP" (boolValues ++ ["routers-only"]))
482 (assertValueOneOf "EmitLLDP" (boolValues ++ ["nearest-bridge" "non-tpmr-bridge" "customer-bridge"]))
483 (assertValueOneOf "DNSDefaultRoute" boolValues)
484 (assertValueOneOf "IPForward" (boolValues ++ ["ipv4" "ipv6"]))
485 (assertValueOneOf "IPMasquerade" boolValues)
486 (assertValueOneOf "IPv6PrivacyExtensions" (boolValues ++ ["prefer-public" "kernel"]))
487 (assertValueOneOf "IPv6AcceptRA" boolValues)
488 (assertInt "IPv6DuplicateAddressDetection")
489 (assertMinimum "IPv6DuplicateAddressDetection" 0)
490 (assertInt "IPv6HopLimit")
491 (assertMinimum "IPv6HopLimit" 0)
492 (assertValueOneOf "IPv4ProxyARP" boolValues)
493 (assertValueOneOf "IPv6ProxyNDP" boolValues)
494 (assertValueOneOf "IPv6SendRA" boolValues)
495 (assertValueOneOf "DHCPv6PrefixDelegation" boolValues)
496 (assertByteFormat "IPv6MTUBytes")
497 (assertValueOneOf "ActiveSlave" boolValues)
498 (assertValueOneOf "PrimarySlave" boolValues)
499 (assertValueOneOf "ConfigureWithoutCarrier" boolValues)
500 (assertValueOneOf "IgnoreCarrierLoss" boolValues)
501 (assertValueOneOf "KeepConfiguration" (boolValues ++ ["static" "dhcp-on-stop" "dhcp"]))
502 ];
503
504 sectionAddress = checkUnitConfig "Address" [
505 (assertOnlyFields [
506 "Address"
507 "Peer"
508 "Broadcast"
509 "Label"
510 "PreferredLifetime"
511 "Scope"
512 "HomeAddress"
513 "DuplicateAddressDetection"
514 "ManageTemporaryAddress"
515 "AddPrefixRoute"
516 "AutoJoin"
517 ])
518 (assertHasField "Address")
519 (assertValueOneOf "PreferredLifetime" ["forever" "infinity" "0" 0])
520 (assertValueOneOf "HomeAddress" boolValues)
521 (assertValueOneOf "DuplicateAddressDetection" ["ipv4" "ipv6" "both" "none"])
522 (assertValueOneOf "ManageTemporaryAddress" boolValues)
523 (assertValueOneOf "AddPrefixRoute" boolValues)
524 (assertValueOneOf "AutoJoin" boolValues)
525 ];
526
527 sectionRoutingPolicyRule = checkUnitConfig "RoutingPolicyRule" [
528 (assertOnlyFields [
529 "TypeOfService"
530 "From"
531 "To"
532 "FirewallMark"
533 "Table"
534 "Priority"
535 "IncomingInterface"
536 "OutgoingInterface"
537 "SourcePort"
538 "DestinationPort"
539 "IPProtocol"
540 "InvertRule"
541 "Family"
542 "User"
543 "SuppressPrefixLength"
544 ])
545 (assertInt "TypeOfService")
546 (assertRange "TypeOfService" 0 255)
547 (assertInt "FirewallMark")
548 (assertRange "FirewallMark" 1 4294967295)
549 (assertInt "Priority")
550 (assertPort "SourcePort")
551 (assertPort "DestinationPort")
552 (assertValueOneOf "InvertRule" boolValues)
553 (assertValueOneOf "Family" ["ipv4" "ipv6" "both"])
554 (assertInt "SuppressPrefixLength")
555 (assertRange "SuppressPrefixLength" 0 128)
556 ];
557
558 sectionRoute = checkUnitConfig "Route" [
559 (assertOnlyFields [
560 "Gateway"
561 "GatewayOnLink"
562 "Destination"
563 "Source"
564 "Metric"
565 "IPv6Preference"
566 "Scope"
567 "PreferredSource"
568 "Table"
569 "Protocol"
570 "Type"
571 "InitialCongestionWindow"
572 "InitialAdvertisedReceiveWindow"
573 "QuickAck"
574 "FastOpenNoCookie"
575 "TTLPropagate"
576 "MTUBytes"
577 "IPServiceType"
578 "MultiPathRoute"
579 ])
580 (assertValueOneOf "GatewayOnLink" boolValues)
581 (assertInt "Metric")
582 (assertValueOneOf "IPv6Preference" ["low" "medium" "high"])
583 (assertValueOneOf "Scope" ["global" "site" "link" "host" "nowhere"])
584 (assertValueOneOf "Type" [
585 "unicast"
586 "local"
587 "broadcast"
588 "anycast"
589 "multicast"
590 "blackhole"
591 "unreachable"
592 "prohibit"
593 "throw"
594 "nat"
595 "xresolve"
596 ])
597 (assertValueOneOf "QuickAck" boolValues)
598 (assertValueOneOf "FastOpenNoCookie" boolValues)
599 (assertValueOneOf "TTLPropagate" boolValues)
600 (assertByteFormat "MTUBytes")
601 (assertValueOneOf "IPServiceType" ["CS6" "CS4"])
602 ];
603
604 sectionDHCPv4 = checkUnitConfig "DHCPv4" [
605 (assertOnlyFields [
606 "UseDNS"
607 "RoutesToDNS"
608 "UseNTP"
609 "UseSIP"
610 "UseMTU"
611 "Anonymize"
612 "SendHostname"
613 "UseHostname"
614 "Hostname"
615 "UseDomains"
616 "UseRoutes"
617 "UseTimezone"
618 "ClientIdentifier"
619 "VendorClassIdentifier"
620 "UserClass"
621 "MaxAttempts"
622 "DUIDType"
623 "DUIDRawData"
624 "IAID"
625 "RequestBroadcast"
626 "RouteMetric"
627 "RouteTable"
628 "RouteMTUBytes"
629 "ListenPort"
630 "SendRelease"
631 "SendDecline"
632 "BlackList"
633 "RequestOptions"
634 "SendOption"
635 ])
636 (assertValueOneOf "UseDNS" boolValues)
637 (assertValueOneOf "RoutesToDNS" boolValues)
638 (assertValueOneOf "UseNTP" boolValues)
639 (assertValueOneOf "UseSIP" boolValues)
640 (assertValueOneOf "UseMTU" boolValues)
641 (assertValueOneOf "Anonymize" boolValues)
642 (assertValueOneOf "SendHostname" boolValues)
643 (assertValueOneOf "UseHostname" boolValues)
644 (assertValueOneOf "UseDomains" (boolValues ++ ["route"]))
645 (assertValueOneOf "UseRoutes" boolValues)
646 (assertValueOneOf "UseTimezone" boolValues)
647 (assertValueOneOf "ClientIdentifier" ["mac" "duid" "duid-only"])
648 (assertInt "IAID")
649 (assertValueOneOf "RequestBroadcast" boolValues)
650 (assertInt "RouteMetric")
651 (assertInt "RouteTable")
652 (assertRange "RouteTable" 0 4294967295)
653 (assertByteFormat "RouteMTUBytes")
654 (assertPort "ListenPort")
655 (assertValueOneOf "SendRelease" boolValues)
656 (assertValueOneOf "SendDecline" boolValues)
657 ];
658
659 sectionDHCPv6 = checkUnitConfig "DHCPv6" [
660 (assertOnlyFields [
661 "UseAddress"
662 "UseDNS"
663 "UseNTP"
664 "RouteMetric"
665 "RapidCommit"
666 "MUDURL"
667 "RequestOptions"
668 "SendVendorOption"
669 "ForceDHCPv6PDOtherInformation"
670 "PrefixDelegationHint"
671 "WithoutRA"
672 "SendOption"
673 "UserClass"
674 "VendorClass"
675 ])
676 (assertValueOneOf "UseAddress" boolValues)
677 (assertValueOneOf "UseDNS" boolValues)
678 (assertValueOneOf "UseNTP" boolValues)
679 (assertInt "RouteMetric")
680 (assertValueOneOf "RapidCommit" boolValues)
681 (assertValueOneOf "ForceDHCPv6PDOtherInformation" boolValues)
682 (assertValueOneOf "WithoutRA" ["solicit" "information-request"])
683 (assertRange "SendOption" 1 65536)
684 ];
685
686 sectionDHCPv6PrefixDelegation = checkUnitConfig "DHCPv6PrefixDelegation" [
687 (assertOnlyFields [
688 "SubnetId"
689 "Announce"
690 "Assign"
691 "Token"
692 ])
693 (assertValueOneOf "Announce" boolValues)
694 (assertValueOneOf "Assign" boolValues)
695 ];
696
697 sectionIPv6AcceptRA = checkUnitConfig "IPv6AcceptRA" [
698 (assertOnlyFields [
699 "UseDNS"
700 "UseDomains"
701 "RouteTable"
702 "UseAutonomousPrefix"
703 "UseOnLinkPrefix"
704 "RouterDenyList"
705 "RouterAllowList"
706 "PrefixDenyList"
707 "PrefixAllowList"
708 "RouteDenyList"
709 "RouteAllowList"
710 "DHCPv6Client"
711 ])
712 (assertValueOneOf "UseDNS" boolValues)
713 (assertValueOneOf "UseDomains" (boolValues ++ ["route"]))
714 (assertRange "RouteTable" 0 4294967295)
715 (assertValueOneOf "UseAutonomousPrefix" boolValues)
716 (assertValueOneOf "UseOnLinkPrefix" boolValues)
717 (assertValueOneOf "DHCPv6Client" (boolValues ++ ["always"]))
718 ];
719
720 sectionDHCPServer = checkUnitConfig "DHCPServer" [
721 (assertOnlyFields [
722 "PoolOffset"
723 "PoolSize"
724 "DefaultLeaseTimeSec"
725 "MaxLeaseTimeSec"
726 "EmitDNS"
727 "DNS"
728 "EmitNTP"
729 "NTP"
730 "EmitSIP"
731 "SIP"
732 "EmitPOP3"
733 "POP3"
734 "EmitSMTP"
735 "SMTP"
736 "EmitLPR"
737 "LPR"
738 "EmitRouter"
739 "EmitTimezone"
740 "Timezone"
741 "SendOption"
742 "SendVendorOption"
743 ])
744 (assertInt "PoolOffset")
745 (assertMinimum "PoolOffset" 0)
746 (assertInt "PoolSize")
747 (assertMinimum "PoolSize" 0)
748 (assertValueOneOf "EmitDNS" boolValues)
749 (assertValueOneOf "EmitNTP" boolValues)
750 (assertValueOneOf "EmitSIP" boolValues)
751 (assertValueOneOf "EmitPOP3" boolValues)
752 (assertValueOneOf "EmitSMTP" boolValues)
753 (assertValueOneOf "EmitLPR" boolValues)
754 (assertValueOneOf "EmitRouter" boolValues)
755 (assertValueOneOf "EmitTimezone" boolValues)
756 ];
757
758 sectionIPv6SendRA = checkUnitConfig "IPv6SendRA" [
759 (assertOnlyFields [
760 "Managed"
761 "OtherInformation"
762 "RouterLifetimeSec"
763 "RouterPreference"
764 "EmitDNS"
765 "DNS"
766 "EmitDomains"
767 "Domains"
768 "DNSLifetimeSec"
769 ])
770 (assertValueOneOf "Managed" boolValues)
771 (assertValueOneOf "OtherInformation" boolValues)
772 (assertValueOneOf "RouterPreference" ["high" "medium" "low" "normal" "default"])
773 (assertValueOneOf "EmitDNS" boolValues)
774 (assertValueOneOf "EmitDomains" boolValues)
775 ];
776
777 sectionIPv6Prefix = checkUnitConfig "IPv6Prefix" [
778 (assertOnlyFields [
779 "AddressAutoconfiguration"
780 "OnLink"
781 "Prefix"
782 "PreferredLifetimeSec"
783 "ValidLifetimeSec"
784 ])
785 (assertValueOneOf "AddressAutoconfiguration" boolValues)
786 (assertValueOneOf "OnLink" boolValues)
787 ];
788
789 };
790 };
791
792 commonNetworkOptions = {
793
794 enable = mkOption {
795 default = true;
796 type = types.bool;
797 description = ''
798 Whether to manage network configuration using <command>systemd-network</command>.
799 '';
800 };
801
802 matchConfig = mkOption {
803 default = {};
804 example = { Name = "eth0"; };
805 type = types.attrsOf unitOption;
806 description = ''
807 Each attribute in this set specifies an option in the
808 <literal>[Match]</literal> section of the unit. See
809 <citerefentry><refentrytitle>systemd.link</refentrytitle><manvolnum>5</manvolnum></citerefentry>
810 <citerefentry><refentrytitle>systemd.netdev</refentrytitle><manvolnum>5</manvolnum></citerefentry>
811 <citerefentry><refentrytitle>systemd.network</refentrytitle><manvolnum>5</manvolnum></citerefentry>
812 for details.
813 '';
814 };
815
816 extraConfig = mkOption {
817 default = "";
818 type = types.lines;
819 description = "Extra configuration append to unit";
820 };
821 };
822
823 linkOptions = commonNetworkOptions // {
824 # overwrite enable option from above
825 enable = mkOption {
826 default = true;
827 type = types.bool;
828 description = ''
829 Whether to enable this .link unit. It's handled by udev no matter if <command>systemd-networkd</command> is enabled or not
830 '';
831 };
832
833 linkConfig = mkOption {
834 default = {};
835 example = { MACAddress = "00:ff:ee:aa:cc:dd"; };
836 type = types.addCheck (types.attrsOf unitOption) check.link.sectionLink;
837 description = ''
838 Each attribute in this set specifies an option in the
839 <literal>[Link]</literal> section of the unit. See
840 <citerefentry><refentrytitle>systemd.link</refentrytitle>
841 <manvolnum>5</manvolnum></citerefentry> for details.
842 '';
843 };
844
845 };
846
847 wireguardPeerOptions = {
848 options = {
849 wireguardPeerConfig = mkOption {
850 default = {};
851 example = { };
852 type = types.addCheck (types.attrsOf unitOption) check.netdev.sectionWireGuardPeer;
853 description = ''
854 Each attribute in this set specifies an option in the
855 <literal>[WireGuardPeer]</literal> section of the unit. See
856 <citerefentry><refentrytitle>systemd.network</refentrytitle>
857 <manvolnum>5</manvolnum></citerefentry> for details.
858 '';
859 };
860 };
861 };
862
863 netdevOptions = commonNetworkOptions // {
864
865 netdevConfig = mkOption {
866 default = {};
867 example = { Name = "mybridge"; Kind = "bridge"; };
868 type = types.addCheck (types.attrsOf unitOption) check.netdev.sectionNetdev;
869 description = ''
870 Each attribute in this set specifies an option in the
871 <literal>[Netdev]</literal> section of the unit. See
872 <citerefentry><refentrytitle>systemd.netdev</refentrytitle>
873 <manvolnum>5</manvolnum></citerefentry> for details.
874 '';
875 };
876
877 vlanConfig = mkOption {
878 default = {};
879 example = { Id = 4; };
880 type = types.addCheck (types.attrsOf unitOption) check.netdev.sectionVLAN;
881 description = ''
882 Each attribute in this set specifies an option in the
883 <literal>[VLAN]</literal> section of the unit. See
884 <citerefentry><refentrytitle>systemd.netdev</refentrytitle>
885 <manvolnum>5</manvolnum></citerefentry> for details.
886 '';
887 };
888
889 macvlanConfig = mkOption {
890 default = {};
891 example = { Mode = "private"; };
892 type = types.addCheck (types.attrsOf unitOption) check.netdev.sectionMACVLAN;
893 description = ''
894 Each attribute in this set specifies an option in the
895 <literal>[MACVLAN]</literal> section of the unit. See
896 <citerefentry><refentrytitle>systemd.netdev</refentrytitle>
897 <manvolnum>5</manvolnum></citerefentry> for details.
898 '';
899 };
900
901 vxlanConfig = mkOption {
902 default = {};
903 example = { Id = "4"; };
904 type = types.addCheck (types.attrsOf unitOption) check.netdev.sectionVXLAN;
905 description = ''
906 Each attribute in this set specifies an option in the
907 <literal>[VXLAN]</literal> section of the unit. See
908 <citerefentry><refentrytitle>systemd.netdev</refentrytitle>
909 <manvolnum>5</manvolnum></citerefentry> for details.
910 '';
911 };
912
913 tunnelConfig = mkOption {
914 default = {};
915 example = { Remote = "192.168.1.1"; };
916 type = types.addCheck (types.attrsOf unitOption) check.netdev.sectionTunnel;
917 description = ''
918 Each attribute in this set specifies an option in the
919 <literal>[Tunnel]</literal> section of the unit. See
920 <citerefentry><refentrytitle>systemd.netdev</refentrytitle>
921 <manvolnum>5</manvolnum></citerefentry> for details.
922 '';
923 };
924
925 peerConfig = mkOption {
926 default = {};
927 example = { Name = "veth2"; };
928 type = types.addCheck (types.attrsOf unitOption) check.netdev.sectionPeer;
929 description = ''
930 Each attribute in this set specifies an option in the
931 <literal>[Peer]</literal> section of the unit. See
932 <citerefentry><refentrytitle>systemd.netdev</refentrytitle>
933 <manvolnum>5</manvolnum></citerefentry> for details.
934 '';
935 };
936
937 tunConfig = mkOption {
938 default = {};
939 example = { User = "openvpn"; };
940 type = types.addCheck (types.attrsOf unitOption) check.netdev.sectionTun;
941 description = ''
942 Each attribute in this set specifies an option in the
943 <literal>[Tun]</literal> section of the unit. See
944 <citerefentry><refentrytitle>systemd.netdev</refentrytitle>
945 <manvolnum>5</manvolnum></citerefentry> for details.
946 '';
947 };
948
949 tapConfig = mkOption {
950 default = {};
951 example = { User = "openvpn"; };
952 type = types.addCheck (types.attrsOf unitOption) check.netdev.sectionTap;
953 description = ''
954 Each attribute in this set specifies an option in the
955 <literal>[Tap]</literal> section of the unit. See
956 <citerefentry><refentrytitle>systemd.netdev</refentrytitle>
957 <manvolnum>5</manvolnum></citerefentry> for details.
958 '';
959 };
960
961 wireguardConfig = mkOption {
962 default = {};
963 example = {
964 PrivateKeyFile = "/etc/wireguard/secret.key";
965 ListenPort = 51820;
966 FwMark = 42;
967 };
968 type = types.addCheck (types.attrsOf unitOption) check.netdev.sectionWireGuard;
969 description = ''
970 Each attribute in this set specifies an option in the
971 <literal>[WireGuard]</literal> section of the unit. See
972 <citerefentry><refentrytitle>systemd.netdev</refentrytitle>
973 <manvolnum>5</manvolnum></citerefentry> for details.
974 Use <literal>PrivateKeyFile</literal> instead of
975 <literal>PrivateKey</literal>: the nix store is
976 world-readable.
977 '';
978 };
979
980 wireguardPeers = mkOption {
981 default = [];
982 example = [ { wireguardPeerConfig={
983 Endpoint = "192.168.1.1:51820";
984 PublicKey = "27s0OvaBBdHoJYkH9osZpjpgSOVNw+RaKfboT/Sfq0g=";
985 PresharedKeyFile = "/etc/wireguard/psk.key";
986 AllowedIPs = [ "10.0.0.1/32" ];
987 PersistentKeepalive = 15;
988 };}];
989 type = with types; listOf (submodule wireguardPeerOptions);
990 description = ''
991 Each item in this array specifies an option in the
992 <literal>[WireGuardPeer]</literal> section of the unit. See
993 <citerefentry><refentrytitle>systemd.netdev</refentrytitle>
994 <manvolnum>5</manvolnum></citerefentry> for details.
995 Use <literal>PresharedKeyFile</literal> instead of
996 <literal>PresharedKey</literal>: the nix store is
997 world-readable.
998 '';
999 };
1000
1001 bondConfig = mkOption {
1002 default = {};
1003 example = { Mode = "802.3ad"; };
1004 type = types.addCheck (types.attrsOf unitOption) check.netdev.sectionBond;
1005 description = ''
1006 Each attribute in this set specifies an option in the
1007 <literal>[Bond]</literal> section of the unit. See
1008 <citerefentry><refentrytitle>systemd.netdev</refentrytitle>
1009 <manvolnum>5</manvolnum></citerefentry> for details.
1010 '';
1011 };
1012
1013 xfrmConfig = mkOption {
1014 default = {};
1015 example = { InterfaceId = 1; };
1016 type = types.addCheck (types.attrsOf unitOption) check.netdev.sectionXfrm;
1017 description = ''
1018 Each attribute in this set specifies an option in the
1019 <literal>[Xfrm]</literal> section of the unit. See
1020 <citerefentry><refentrytitle>systemd.netdev</refentrytitle>
1021 <manvolnum>5</manvolnum></citerefentry> for details.
1022 '';
1023 };
1024
1025 vrfConfig = mkOption {
1026 default = {};
1027 example = { Table = 2342; };
1028 type = types.addCheck (types.attrsOf unitOption) check.netdev.sectionVRF;
1029 description = ''
1030 Each attribute in this set specifies an option in the
1031 <literal>[VRF]</literal> section of the unit. See
1032 <citerefentry><refentrytitle>systemd.netdev</refentrytitle>
1033 <manvolnum>5</manvolnum></citerefentry> for details.
1034 A detailed explanation about how VRFs work can be found in the
1035 <link xlink:href="https://www.kernel.org/doc/Documentation/networking/vrf.txt">kernel
1036 docs</link>.
1037 '';
1038 };
1039
1040 };
1041
1042 addressOptions = {
1043 options = {
1044 addressConfig = mkOption {
1045 default = {};
1046 example = { Address = "192.168.0.100/24"; };
1047 type = types.addCheck (types.attrsOf unitOption) check.network.sectionAddress;
1048 description = ''
1049 Each attribute in this set specifies an option in the
1050 <literal>[Address]</literal> section of the unit. See
1051 <citerefentry><refentrytitle>systemd.network</refentrytitle>
1052 <manvolnum>5</manvolnum></citerefentry> for details.
1053 '';
1054 };
1055 };
1056 };
1057
1058 routingPolicyRulesOptions = {
1059 options = {
1060 routingPolicyRuleConfig = mkOption {
1061 default = { };
1062 example = { routingPolicyRuleConfig = { Table = 10; IncomingInterface = "eth1"; Family = "both"; } ;};
1063 type = types.addCheck (types.attrsOf unitOption) check.network.sectionRoutingPolicyRule;
1064 description = ''
1065 Each attribute in this set specifies an option in the
1066 <literal>[RoutingPolicyRule]</literal> section of the unit. See
1067 <citerefentry><refentrytitle>systemd.network</refentrytitle>
1068 <manvolnum>5</manvolnum></citerefentry> for details.
1069 '';
1070 };
1071 };
1072 };
1073
1074 routeOptions = {
1075 options = {
1076 routeConfig = mkOption {
1077 default = {};
1078 example = { Gateway = "192.168.0.1"; };
1079 type = types.addCheck (types.attrsOf unitOption) check.network.sectionRoute;
1080 description = ''
1081 Each attribute in this set specifies an option in the
1082 <literal>[Route]</literal> section of the unit. See
1083 <citerefentry><refentrytitle>systemd.network</refentrytitle>
1084 <manvolnum>5</manvolnum></citerefentry> for details.
1085 '';
1086 };
1087 };
1088 };
1089
1090 ipv6PrefixOptions = {
1091 options = {
1092 ipv6PrefixConfig = mkOption {
1093 default = {};
1094 example = { Prefix = "fd00::/64"; };
1095 type = types.addCheck (types.attrsOf unitOption) check.network.sectionIPv6Prefix;
1096 description = ''
1097 Each attribute in this set specifies an option in the
1098 <literal>[IPv6Prefix]</literal> section of the unit. See
1099 <citerefentry><refentrytitle>systemd.network</refentrytitle>
1100 <manvolnum>5</manvolnum></citerefentry> for details.
1101 '';
1102 };
1103 };
1104 };
1105
1106 networkOptions = commonNetworkOptions // {
1107
1108 linkConfig = mkOption {
1109 default = {};
1110 example = { Unmanaged = true; };
1111 type = types.addCheck (types.attrsOf unitOption) check.network.sectionLink;
1112 description = ''
1113 Each attribute in this set specifies an option in the
1114 <literal>[Link]</literal> section of the unit. See
1115 <citerefentry><refentrytitle>systemd.network</refentrytitle>
1116 <manvolnum>5</manvolnum></citerefentry> for details.
1117 '';
1118 };
1119
1120 networkConfig = mkOption {
1121 default = {};
1122 example = { Description = "My Network"; };
1123 type = types.addCheck (types.attrsOf unitOption) check.network.sectionNetwork;
1124 description = ''
1125 Each attribute in this set specifies an option in the
1126 <literal>[Network]</literal> section of the unit. See
1127 <citerefentry><refentrytitle>systemd.network</refentrytitle>
1128 <manvolnum>5</manvolnum></citerefentry> for details.
1129 '';
1130 };
1131
1132 # systemd.network.networks.*.dhcpConfig has been deprecated in favor of ….dhcpV4Config
1133 # Produce a nice warning message so users know it is gone.
1134 dhcpConfig = mkOption {
1135 visible = false;
1136 apply = _: throw "The option `systemd.network.networks.*.dhcpConfig` can no longer be used since it's been removed. Please use `systemd.network.networks.*.dhcpV4Config` instead.";
1137 };
1138
1139 dhcpV4Config = mkOption {
1140 default = {};
1141 example = { UseDNS = true; UseRoutes = true; };
1142 type = types.addCheck (types.attrsOf unitOption) check.network.sectionDHCPv4;
1143 description = ''
1144 Each attribute in this set specifies an option in the
1145 <literal>[DHCPv4]</literal> section of the unit. See
1146 <citerefentry><refentrytitle>systemd.network</refentrytitle>
1147 <manvolnum>5</manvolnum></citerefentry> for details.
1148 '';
1149 };
1150
1151 dhcpV6Config = mkOption {
1152 default = {};
1153 example = { UseDNS = true; UseRoutes = true; };
1154 type = types.addCheck (types.attrsOf unitOption) check.network.sectionDHCPv6;
1155 description = ''
1156 Each attribute in this set specifies an option in the
1157 <literal>[DHCPv6]</literal> section of the unit. See
1158 <citerefentry><refentrytitle>systemd.network</refentrytitle>
1159 <manvolnum>5</manvolnum></citerefentry> for details.
1160 '';
1161 };
1162
1163 dhcpV6PrefixDelegationConfig = mkOption {
1164 default = {};
1165 example = { SubnetId = "auto"; Announce = true; };
1166 type = types.addCheck (types.attrsOf unitOption) check.network.sectionDHCPv6PrefixDelegation;
1167 description = ''
1168 Each attribute in this set specifies an option in the
1169 <literal>[DHCPv6PrefixDelegation]</literal> section of the unit. See
1170 <citerefentry><refentrytitle>systemd.network</refentrytitle>
1171 <manvolnum>5</manvolnum></citerefentry> for details.
1172 '';
1173 };
1174
1175 ipv6AcceptRAConfig = mkOption {
1176 default = {};
1177 example = { UseDNS = true; DHCPv6Client = "always"; };
1178 type = types.addCheck (types.attrsOf unitOption) check.network.sectionIPv6AcceptRA;
1179 description = ''
1180 Each attribute in this set specifies an option in the
1181 <literal>[IPv6AcceptRA]</literal> section of the unit. See
1182 <citerefentry><refentrytitle>systemd.network</refentrytitle>
1183 <manvolnum>5</manvolnum></citerefentry> for details.
1184 '';
1185 };
1186
1187 dhcpServerConfig = mkOption {
1188 default = {};
1189 example = { PoolOffset = 50; EmitDNS = false; };
1190 type = types.addCheck (types.attrsOf unitOption) check.network.sectionDHCPServer;
1191 description = ''
1192 Each attribute in this set specifies an option in the
1193 <literal>[DHCPServer]</literal> section of the unit. See
1194 <citerefentry><refentrytitle>systemd.network</refentrytitle>
1195 <manvolnum>5</manvolnum></citerefentry> for details.
1196 '';
1197 };
1198
1199 # systemd.network.networks.*.ipv6PrefixDelegationConfig has been deprecated
1200 # in 247 in favor of systemd.network.networks.*.ipv6SendRAConfig.
1201 ipv6PrefixDelegationConfig = mkOption {
1202 visible = false;
1203 apply = _: throw "The option `systemd.network.networks.*.ipv6PrefixDelegationConfig` has been replaced by `systemd.network.networks.*.ipv6SendRAConfig`.";
1204 };
1205
1206 ipv6SendRAConfig = mkOption {
1207 default = {};
1208 example = { EmitDNS = true; Managed = true; OtherInformation = true; };
1209 type = types.addCheck (types.attrsOf unitOption) check.network.sectionIPv6SendRA;
1210 description = ''
1211 Each attribute in this set specifies an option in the
1212 <literal>[IPv6SendRA]</literal> section of the unit. See
1213 <citerefentry><refentrytitle>systemd.network</refentrytitle>
1214 <manvolnum>5</manvolnum></citerefentry> for details.
1215 '';
1216 };
1217
1218 ipv6Prefixes = mkOption {
1219 default = [];
1220 example = { AddressAutoconfiguration = true; OnLink = true; };
1221 type = with types; listOf (submodule ipv6PrefixOptions);
1222 description = ''
1223 A list of ipv6Prefix sections to be added to the unit. See
1224 <citerefentry><refentrytitle>systemd.network</refentrytitle>
1225 <manvolnum>5</manvolnum></citerefentry> for details.
1226 '';
1227 };
1228
1229 name = mkOption {
1230 type = types.nullOr types.str;
1231 default = null;
1232 description = ''
1233 The name of the network interface to match against.
1234 '';
1235 };
1236
1237 DHCP = mkOption {
1238 type = types.nullOr types.str;
1239 default = null;
1240 description = ''
1241 Whether to enable DHCP on the interfaces matched.
1242 '';
1243 };
1244
1245 domains = mkOption {
1246 type = types.nullOr (types.listOf types.str);
1247 default = null;
1248 description = ''
1249 A list of domains to pass to the network config.
1250 '';
1251 };
1252
1253 address = mkOption {
1254 default = [ ];
1255 type = types.listOf types.str;
1256 description = ''
1257 A list of addresses to be added to the network section of the
1258 unit. See <citerefentry><refentrytitle>systemd.network</refentrytitle>
1259 <manvolnum>5</manvolnum></citerefentry> for details.
1260 '';
1261 };
1262
1263 gateway = mkOption {
1264 default = [ ];
1265 type = types.listOf types.str;
1266 description = ''
1267 A list of gateways to be added to the network section of the
1268 unit. See <citerefentry><refentrytitle>systemd.network</refentrytitle>
1269 <manvolnum>5</manvolnum></citerefentry> for details.
1270 '';
1271 };
1272
1273 dns = mkOption {
1274 default = [ ];
1275 type = types.listOf types.str;
1276 description = ''
1277 A list of dns servers to be added to the network section of the
1278 unit. See <citerefentry><refentrytitle>systemd.network</refentrytitle>
1279 <manvolnum>5</manvolnum></citerefentry> for details.
1280 '';
1281 };
1282
1283 ntp = mkOption {
1284 default = [ ];
1285 type = types.listOf types.str;
1286 description = ''
1287 A list of ntp servers to be added to the network section of the
1288 unit. See <citerefentry><refentrytitle>systemd.network</refentrytitle>
1289 <manvolnum>5</manvolnum></citerefentry> for details.
1290 '';
1291 };
1292
1293 bridge = mkOption {
1294 default = [ ];
1295 type = types.listOf types.str;
1296 description = ''
1297 A list of bridge interfaces to be added to the network section of the
1298 unit. See <citerefentry><refentrytitle>systemd.network</refentrytitle>
1299 <manvolnum>5</manvolnum></citerefentry> for details.
1300 '';
1301 };
1302
1303 bond = mkOption {
1304 default = [ ];
1305 type = types.listOf types.str;
1306 description = ''
1307 A list of bond interfaces to be added to the network section of the
1308 unit. See <citerefentry><refentrytitle>systemd.network</refentrytitle>
1309 <manvolnum>5</manvolnum></citerefentry> for details.
1310 '';
1311 };
1312
1313 vrf = mkOption {
1314 default = [ ];
1315 type = types.listOf types.str;
1316 description = ''
1317 A list of vrf interfaces to be added to the network section of the
1318 unit. See <citerefentry><refentrytitle>systemd.network</refentrytitle>
1319 <manvolnum>5</manvolnum></citerefentry> for details.
1320 '';
1321 };
1322
1323 vlan = mkOption {
1324 default = [ ];
1325 type = types.listOf types.str;
1326 description = ''
1327 A list of vlan interfaces to be added to the network section of the
1328 unit. See <citerefentry><refentrytitle>systemd.network</refentrytitle>
1329 <manvolnum>5</manvolnum></citerefentry> for details.
1330 '';
1331 };
1332
1333 macvlan = mkOption {
1334 default = [ ];
1335 type = types.listOf types.str;
1336 description = ''
1337 A list of macvlan interfaces to be added to the network section of the
1338 unit. See <citerefentry><refentrytitle>systemd.network</refentrytitle>
1339 <manvolnum>5</manvolnum></citerefentry> for details.
1340 '';
1341 };
1342
1343 vxlan = mkOption {
1344 default = [ ];
1345 type = types.listOf types.str;
1346 description = ''
1347 A list of vxlan interfaces to be added to the network section of the
1348 unit. See <citerefentry><refentrytitle>systemd.network</refentrytitle>
1349 <manvolnum>5</manvolnum></citerefentry> for details.
1350 '';
1351 };
1352
1353 tunnel = mkOption {
1354 default = [ ];
1355 type = types.listOf types.str;
1356 description = ''
1357 A list of tunnel interfaces to be added to the network section of the
1358 unit. See <citerefentry><refentrytitle>systemd.network</refentrytitle>
1359 <manvolnum>5</manvolnum></citerefentry> for details.
1360 '';
1361 };
1362
1363 xfrm = mkOption {
1364 default = [ ];
1365 type = types.listOf types.str;
1366 description = ''
1367 A list of xfrm interfaces to be added to the network section of the
1368 unit. See <citerefentry><refentrytitle>systemd.network</refentrytitle>
1369 <manvolnum>5</manvolnum></citerefentry> for details.
1370 '';
1371 };
1372
1373 addresses = mkOption {
1374 default = [ ];
1375 type = with types; listOf (submodule addressOptions);
1376 description = ''
1377 A list of address sections to be added to the unit. See
1378 <citerefentry><refentrytitle>systemd.network</refentrytitle>
1379 <manvolnum>5</manvolnum></citerefentry> for details.
1380 '';
1381 };
1382
1383 routingPolicyRules = mkOption {
1384 default = [ ];
1385 type = with types; listOf (submodule routingPolicyRulesOptions);
1386 description = ''
1387 A list of routing policy rules sections to be added to the unit. See
1388 <citerefentry><refentrytitle>systemd.network</refentrytitle>
1389 <manvolnum>5</manvolnum></citerefentry> for details.
1390 '';
1391 };
1392
1393 routes = mkOption {
1394 default = [ ];
1395 type = with types; listOf (submodule routeOptions);
1396 description = ''
1397 A list of route sections to be added to the unit. See
1398 <citerefentry><refentrytitle>systemd.network</refentrytitle>
1399 <manvolnum>5</manvolnum></citerefentry> for details.
1400 '';
1401 };
1402
1403 };
1404
1405 networkConfig = { config, ... }: {
1406 config = {
1407 matchConfig = optionalAttrs (config.name != null) {
1408 Name = config.name;
1409 };
1410 networkConfig = optionalAttrs (config.DHCP != null) {
1411 DHCP = config.DHCP;
1412 } // optionalAttrs (config.domains != null) {
1413 Domains = concatStringsSep " " config.domains;
1414 };
1415 };
1416 };
1417
1418 commonMatchText = def: optionalString (def.matchConfig != { }) ''
1419 [Match]
1420 ${attrsToSection def.matchConfig}
1421 '';
1422
1423 linkToUnit = name: def:
1424 { inherit (def) enable;
1425 text = commonMatchText def
1426 + ''
1427 [Link]
1428 ${attrsToSection def.linkConfig}
1429 ''
1430 + def.extraConfig;
1431 };
1432
1433 netdevToUnit = name: def:
1434 { inherit (def) enable;
1435 text = commonMatchText def
1436 + ''
1437 [NetDev]
1438 ${attrsToSection def.netdevConfig}
1439 ''
1440 + optionalString (def.vlanConfig != { }) ''
1441 [VLAN]
1442 ${attrsToSection def.vlanConfig}
1443 ''
1444 + optionalString (def.macvlanConfig != { }) ''
1445 [MACVLAN]
1446 ${attrsToSection def.macvlanConfig}
1447 ''
1448 + optionalString (def.vxlanConfig != { }) ''
1449 [VXLAN]
1450 ${attrsToSection def.vxlanConfig}
1451 ''
1452 + optionalString (def.tunnelConfig != { }) ''
1453 [Tunnel]
1454 ${attrsToSection def.tunnelConfig}
1455 ''
1456 + optionalString (def.peerConfig != { }) ''
1457 [Peer]
1458 ${attrsToSection def.peerConfig}
1459 ''
1460 + optionalString (def.tunConfig != { }) ''
1461 [Tun]
1462 ${attrsToSection def.tunConfig}
1463 ''
1464 + optionalString (def.tapConfig != { }) ''
1465 [Tap]
1466 ${attrsToSection def.tapConfig}
1467 ''
1468 + optionalString (def.wireguardConfig != { }) ''
1469 [WireGuard]
1470 ${attrsToSection def.wireguardConfig}
1471 ''
1472 + flip concatMapStrings def.wireguardPeers (x: ''
1473 [WireGuardPeer]
1474 ${attrsToSection x.wireguardPeerConfig}
1475 '')
1476 + optionalString (def.bondConfig != { }) ''
1477 [Bond]
1478 ${attrsToSection def.bondConfig}
1479 ''
1480 + optionalString (def.xfrmConfig != { }) ''
1481 [Xfrm]
1482 ${attrsToSection def.xfrmConfig}
1483 ''
1484 + optionalString (def.vrfConfig != { }) ''
1485 [VRF]
1486 ${attrsToSection def.vrfConfig}
1487 ''
1488 + def.extraConfig;
1489 };
1490
1491 networkToUnit = name: def:
1492 { inherit (def) enable;
1493 text = commonMatchText def
1494 + optionalString (def.linkConfig != { }) ''
1495 [Link]
1496 ${attrsToSection def.linkConfig}
1497 ''
1498 + ''
1499 [Network]
1500 ''
1501 + attrsToSection def.networkConfig
1502 + optionalString (def.address != [ ]) ''
1503 ${concatStringsSep "\n" (map (s: "Address=${s}") def.address)}
1504 ''
1505 + optionalString (def.gateway != [ ]) ''
1506 ${concatStringsSep "\n" (map (s: "Gateway=${s}") def.gateway)}
1507 ''
1508 + optionalString (def.dns != [ ]) ''
1509 ${concatStringsSep "\n" (map (s: "DNS=${s}") def.dns)}
1510 ''
1511 + optionalString (def.ntp != [ ]) ''
1512 ${concatStringsSep "\n" (map (s: "NTP=${s}") def.ntp)}
1513 ''
1514 + optionalString (def.bridge != [ ]) ''
1515 ${concatStringsSep "\n" (map (s: "Bridge=${s}") def.bridge)}
1516 ''
1517 + optionalString (def.bond != [ ]) ''
1518 ${concatStringsSep "\n" (map (s: "Bond=${s}") def.bond)}
1519 ''
1520 + optionalString (def.vrf != [ ]) ''
1521 ${concatStringsSep "\n" (map (s: "VRF=${s}") def.vrf)}
1522 ''
1523 + optionalString (def.vlan != [ ]) ''
1524 ${concatStringsSep "\n" (map (s: "VLAN=${s}") def.vlan)}
1525 ''
1526 + optionalString (def.macvlan != [ ]) ''
1527 ${concatStringsSep "\n" (map (s: "MACVLAN=${s}") def.macvlan)}
1528 ''
1529 + optionalString (def.vxlan != [ ]) ''
1530 ${concatStringsSep "\n" (map (s: "VXLAN=${s}") def.vxlan)}
1531 ''
1532 + optionalString (def.tunnel != [ ]) ''
1533 ${concatStringsSep "\n" (map (s: "Tunnel=${s}") def.tunnel)}
1534 ''
1535 + optionalString (def.xfrm != [ ]) ''
1536 ${concatStringsSep "\n" (map (s: "Xfrm=${s}") def.xfrm)}
1537 ''
1538 + ''
1539
1540 ''
1541 + flip concatMapStrings def.addresses (x: ''
1542 [Address]
1543 ${attrsToSection x.addressConfig}
1544 '')
1545 + flip concatMapStrings def.routingPolicyRules (x: ''
1546 [RoutingPolicyRule]
1547 ${attrsToSection x.routingPolicyRuleConfig}
1548 '')
1549 + flip concatMapStrings def.routes (x: ''
1550 [Route]
1551 ${attrsToSection x.routeConfig}
1552 '')
1553 + optionalString (def.dhcpV4Config != { }) ''
1554 [DHCPv4]
1555 ${attrsToSection def.dhcpV4Config}
1556 ''
1557 + optionalString (def.dhcpV6Config != { }) ''
1558 [DHCPv6]
1559 ${attrsToSection def.dhcpV6Config}
1560 ''
1561 + optionalString (def.dhcpV6PrefixDelegationConfig != { }) ''
1562 [DHCPv6PrefixDelegation]
1563 ${attrsToSection def.dhcpV6PrefixDelegationConfig}
1564 ''
1565 + optionalString (def.ipv6AcceptRAConfig != { }) ''
1566 [IPv6AcceptRA]
1567 ${attrsToSection def.ipv6AcceptRAConfig}
1568 ''
1569 + optionalString (def.dhcpServerConfig != { }) ''
1570 [DHCPServer]
1571 ${attrsToSection def.dhcpServerConfig}
1572 ''
1573 + optionalString (def.ipv6SendRAConfig != { }) ''
1574 [IPv6SendRA]
1575 ${attrsToSection def.ipv6SendRAConfig}
1576 ''
1577 + flip concatMapStrings def.ipv6Prefixes (x: ''
1578 [IPv6Prefix]
1579 ${attrsToSection x.ipv6PrefixConfig}
1580 '')
1581 + def.extraConfig;
1582 };
1583
1584 unitFiles = listToAttrs (map (name: {
1585 name = "systemd/network/${name}";
1586 value.source = "${cfg.units.${name}.unit}/${name}";
1587 }) (attrNames cfg.units));
1588in
1589
1590{
1591 disabledModules = [ "system/boot/networkd.nix" ];
1592
1593 options = {
1594
1595 systemd.network.enable = mkOption {
1596 default = false;
1597 type = types.bool;
1598 description = ''
1599 Whether to enable networkd or not.
1600 '';
1601 };
1602
1603 systemd.network.links = mkOption {
1604 default = {};
1605 type = with types; attrsOf (submodule [ { options = linkOptions; } ]);
1606 description = "Definition of systemd network links.";
1607 };
1608
1609 systemd.network.netdevs = mkOption {
1610 default = {};
1611 type = with types; attrsOf (submodule [ { options = netdevOptions; } ]);
1612 description = "Definition of systemd network devices.";
1613 };
1614
1615 systemd.network.networks = mkOption {
1616 default = {};
1617 type = with types; attrsOf (submodule [ { options = networkOptions; } networkConfig ]);
1618 description = "Definition of systemd networks.";
1619 };
1620
1621 systemd.network.units = mkOption {
1622 description = "Definition of networkd units.";
1623 default = {};
1624 internal = true;
1625 type = with types; attrsOf (submodule (
1626 { name, config, ... }:
1627 { options = mapAttrs (_: x: x // { internal = true; }) concreteUnitOptions;
1628 config = {
1629 unit = mkDefault (makeUnit name config);
1630 };
1631 }));
1632 };
1633
1634 };
1635
1636 config = mkMerge [
1637
1638 # .link units are honored by udev, no matter if systemd-networkd is enabled or not.
1639 {
1640 systemd.network.units = mapAttrs' (n: v: nameValuePair "${n}.link" (linkToUnit n v)) cfg.links;
1641 environment.etc = unitFiles;
1642 }
1643
1644 (mkIf config.systemd.network.enable {
1645
1646 users.users.systemd-network.group = "systemd-network";
1647
1648 systemd.additionalUpstreamSystemUnits = [
1649 "systemd-networkd-wait-online.service"
1650 "systemd-networkd.service"
1651 "systemd-networkd.socket"
1652 ];
1653
1654 systemd.network.units = mapAttrs' (n: v: nameValuePair "${n}.netdev" (netdevToUnit n v)) cfg.netdevs
1655 // mapAttrs' (n: v: nameValuePair "${n}.network" (networkToUnit n v)) cfg.networks;
1656
1657 # systemd-networkd is socket-activated by kernel netlink route change
1658 # messages. It is important to have systemd buffer those on behalf of
1659 # networkd.
1660 systemd.sockets.systemd-networkd.wantedBy = [ "sockets.target" ];
1661
1662 systemd.services.systemd-networkd = {
1663 wantedBy = [ "multi-user.target" ];
1664 aliases = [ "dbus-org.freedesktop.network1.service" ];
1665 restartTriggers = map (x: x.source) (attrValues unitFiles);
1666 };
1667
1668 systemd.services.systemd-networkd-wait-online = {
1669 wantedBy = [ "network-online.target" ];
1670 };
1671
1672 systemd.services."systemd-network-wait-online@" = {
1673 description = "Wait for Network Interface %I to be Configured";
1674 conflicts = [ "shutdown.target" ];
1675 requisite = [ "systemd-networkd.service" ];
1676 after = [ "systemd-networkd.service" ];
1677 serviceConfig = {
1678 Type = "oneshot";
1679 RemainAfterExit = true;
1680 ExecStart = "${config.systemd.package}/lib/systemd/systemd-networkd-wait-online -i %I";
1681 };
1682 };
1683
1684 services.resolved.enable = mkDefault true;
1685 })
1686 ];
1687}
diff --git a/modules/networkd/systemd-lib.nix b/modules/networkd/systemd-lib.nix
deleted file mode 100644
index c5b5b7cb..00000000
--- a/modules/networkd/systemd-lib.nix
+++ /dev/null
@@ -1,241 +0,0 @@
1{ config, lib, pkgs }:
2
3with lib;
4
5let
6 cfg = config.systemd;
7 lndir = "${pkgs.xorg.lndir}/bin/lndir";
8in rec {
9
10 shellEscape = s: (replaceChars [ "\\" ] [ "\\\\" ] s);
11
12 mkPathSafeName = lib.replaceChars ["@" ":" "\\" "[" "]"] ["-" "-" "-" "" ""];
13
14 makeUnit = name: unit:
15 if unit.enable then
16 pkgs.runCommand "unit-${mkPathSafeName name}"
17 { preferLocalBuild = true;
18 allowSubstitutes = false;
19 inherit (unit) text;
20 }
21 ''
22 mkdir -p $out
23 echo -n "$text" > $out/${shellEscape name}
24 ''
25 else
26 pkgs.runCommand "unit-${mkPathSafeName name}-disabled"
27 { preferLocalBuild = true;
28 allowSubstitutes = false;
29 }
30 ''
31 mkdir -p $out
32 ln -s /dev/null $out/${shellEscape name}
33 '';
34
35 boolValues = [true false "yes" "no"];
36
37 digits = map toString (range 0 9);
38
39 isByteFormat = s:
40 let
41 l = reverseList (stringToCharacters s);
42 suffix = head l;
43 nums = tail l;
44 in elem suffix (["K" "M" "G" "T"] ++ digits)
45 && all (num: elem num digits) nums;
46
47 assertByteFormat = name: group: attr:
48 optional (attr ? ${name} && ! isByteFormat attr.${name})
49 "Systemd ${group} field `${name}' must be in byte format [0-9]+[KMGT].";
50
51 hexChars = stringToCharacters "0123456789abcdefABCDEF";
52
53 isMacAddress = s: stringLength s == 17
54 && flip all (splitString ":" s) (bytes:
55 all (byte: elem byte hexChars) (stringToCharacters bytes)
56 );
57
58 assertMacAddress = name: group: attr:
59 optional (attr ? ${name} && ! isMacAddress attr.${name})
60 "Systemd ${group} field `${name}' must be a valid mac address.";
61
62 isPort = i: i >= 0 && i <= 65535;
63
64 assertPort = name: group: attr:
65 optional (attr ? ${name} && ! isPort attr.${name})
66 "Error on the systemd ${group} field `${name}': ${attr.name} is not a valid port number.";
67
68 assertValueOneOf = name: values: group: attr:
69 optional (attr ? ${name} && !elem attr.${name} values)
70 "Systemd ${group} field `${name}' cannot have value `${toString attr.${name}}'.";
71
72 assertHasField = name: group: attr:
73 optional (!(attr ? ${name}))
74 "Systemd ${group} field `${name}' must exist.";
75
76 assertRange = name: min: max: group: attr:
77 optional (attr ? ${name} && !(min <= attr.${name} && max >= attr.${name}))
78 "Systemd ${group} field `${name}' is outside the range [${toString min},${toString max}]";
79
80 assertMinimum = name: min: group: attr:
81 optional (attr ? ${name} && attr.${name} < min)
82 "Systemd ${group} field `${name}' must be greater than or equal to ${toString min}";
83
84 assertOnlyFields = fields: group: attr:
85 let badFields = filter (name: ! elem name fields) (attrNames attr); in
86 optional (badFields != [ ])
87 "Systemd ${group} has extra fields [${concatStringsSep " " badFields}].";
88
89 assertInt = name: group: attr:
90 optional (attr ? ${name} && !isInt attr.${name})
91 "Systemd ${group} field `${name}' is not an integer";
92
93 assertMaxLength = name: max: group: attr:
94 optional (attr ? ${name} && stringLength attr.${name} > max)
95 "Systemd ${group} field `${name}' is too long (max of ${max})";
96
97 checkUnitConfig = group: checks: attrs: let
98 # We're applied at the top-level type (attrsOf unitOption), so the actual
99 # unit options might contain attributes from mkOverride and mkIf that we need to
100 # convert into single values before checking them.
101 defs = mapAttrs (const (v:
102 if v._type or "" == "override" then v.content
103 else if v._type or "" == "if" then v.content
104 else v
105 )) attrs;
106 errors = concatMap (c: c group defs) checks;
107 in if errors == [] then true
108 else builtins.trace (concatStringsSep "\n" errors) false;
109
110 toOption = x:
111 if x == true then "true"
112 else if x == false then "false"
113 else toString x;
114
115 attrsToSection = as:
116 concatStrings (concatLists (mapAttrsToList (name: value:
117 map (x: ''
118 ${name}=${toOption x}
119 '')
120 (if isList value then value else [value]))
121 as));
122
123 generateUnits = generateUnits' true;
124
125 generateUnits' = allowCollisions: type: units: upstreamUnits: upstreamWants:
126 pkgs.runCommand "${type}-units"
127 { preferLocalBuild = true;
128 allowSubstitutes = false;
129 } ''
130 mkdir -p $out
131
132 # Copy the upstream systemd units we're interested in.
133 for i in ${toString upstreamUnits}; do
134 fn=${cfg.package}/example/systemd/${type}/$i
135 if ! [ -e $fn ]; then echo "missing $fn"; false; fi
136 if [ -L $fn ]; then
137 target="$(readlink "$fn")"
138 if [ ''${target:0:3} = ../ ]; then
139 ln -s "$(readlink -f "$fn")" $out/
140 else
141 cp -pd $fn $out/
142 fi
143 else
144 ln -s $fn $out/
145 fi
146 done
147
148 # Copy .wants links, but only those that point to units that
149 # we're interested in.
150 for i in ${toString upstreamWants}; do
151 fn=${cfg.package}/example/systemd/${type}/$i
152 if ! [ -e $fn ]; then echo "missing $fn"; false; fi
153 x=$out/$(basename $fn)
154 mkdir $x
155 for i in $fn/*; do
156 y=$x/$(basename $i)
157 cp -pd $i $y
158 if ! [ -e $y ]; then rm $y; fi
159 done
160 done
161
162 # Symlink all units provided listed in systemd.packages.
163 packages="${toString cfg.packages}"
164
165 # Filter duplicate directories
166 declare -A unique_packages
167 for k in $packages ; do unique_packages[$k]=1 ; done
168
169 for i in ''${!unique_packages[@]}; do
170 for fn in $i/etc/systemd/${type}/* $i/lib/systemd/${type}/*; do
171 if ! [[ "$fn" =~ .wants$ ]]; then
172 if [[ -d "$fn" ]]; then
173 targetDir="$out/$(basename "$fn")"
174 mkdir -p "$targetDir"
175 ${lndir} "$fn" "$targetDir"
176 else
177 ln -s $fn $out/
178 fi
179 fi
180 done
181 done
182
183 # Symlink all units defined by systemd.units. If these are also
184 # provided by systemd or systemd.packages, then add them as
185 # <unit-name>.d/overrides.conf, which makes them extend the
186 # upstream unit.
187 for i in ${toString (mapAttrsToList (n: v: v.unit) units)}; do
188 fn=$(basename $i/*)
189 if [ -e $out/$fn ]; then
190 if [ "$(readlink -f $i/$fn)" = /dev/null ]; then
191 ln -sfn /dev/null $out/$fn
192 else
193 ${if allowCollisions then ''
194 mkdir -p $out/$fn.d
195 ln -s $i/$fn $out/$fn.d/overrides.conf
196 '' else ''
197 echo "Found multiple derivations configuring $fn!"
198 exit 1
199 ''}
200 fi
201 else
202 ln -fs $i/$fn $out/
203 fi
204 done
205
206 # Create service aliases from aliases option.
207 ${concatStrings (mapAttrsToList (name: unit:
208 concatMapStrings (name2: ''
209 ln -sfn '${name}' $out/'${name2}'
210 '') unit.aliases) units)}
211
212 # Create .wants and .requires symlinks from the wantedBy and
213 # requiredBy options.
214 ${concatStrings (mapAttrsToList (name: unit:
215 concatMapStrings (name2: ''
216 mkdir -p $out/'${name2}.wants'
217 ln -sfn '../${name}' $out/'${name2}.wants'/
218 '') unit.wantedBy) units)}
219
220 ${concatStrings (mapAttrsToList (name: unit:
221 concatMapStrings (name2: ''
222 mkdir -p $out/'${name2}.requires'
223 ln -sfn '../${name}' $out/'${name2}.requires'/
224 '') unit.requiredBy) units)}
225
226 ${optionalString (type == "system") ''
227 # Stupid misc. symlinks.
228 ln -s ${cfg.defaultUnit} $out/default.target
229 ln -s ${cfg.ctrlAltDelUnit} $out/ctrl-alt-del.target
230 ln -s rescue.target $out/kbrequest.target
231
232 mkdir -p $out/getty.target.wants/
233 ln -s ../autovt@tty1.service $out/getty.target.wants/
234
235 ln -s ../local-fs.target ../remote-fs.target \
236 ../nss-lookup.target ../nss-user-lookup.target ../swap.target \
237 $out/multi-user.target.wants/
238 ''}
239 ''; # */
240
241}
diff --git a/modules/networkd/systemd-unit-options.nix b/modules/networkd/systemd-unit-options.nix
deleted file mode 100644
index 4154389b..00000000
--- a/modules/networkd/systemd-unit-options.nix
+++ /dev/null
@@ -1,536 +0,0 @@
1{ config, lib }:
2
3with lib;
4with import ./systemd-lib.nix { inherit config lib pkgs; };
5
6let
7 checkService = checkUnitConfig "Service" [
8 (assertValueOneOf "Type" [
9 "exec" "simple" "forking" "oneshot" "dbus" "notify" "idle"
10 ])
11 (assertValueOneOf "Restart" [
12 "no" "on-success" "on-failure" "on-abnormal" "on-abort" "always"
13 ])
14 ];
15
16in rec {
17
18 unitOption = mkOptionType {
19 name = "systemd option";
20 merge = loc: defs:
21 let
22 defs' = filterOverrides defs;
23 defs'' = getValues defs';
24 in
25 if isList (head defs'')
26 then concatLists defs''
27 else mergeEqualOption loc defs';
28 };
29
30 sharedOptions = {
31
32 enable = mkOption {
33 default = true;
34 type = types.bool;
35 description = ''
36 If set to false, this unit will be a symlink to
37 /dev/null. This is primarily useful to prevent specific
38 template instances
39 (e.g. <literal>serial-getty@ttyS0</literal>) from being
40 started. Note that <literal>enable=true</literal> does not
41 make a unit start by default at boot; if you want that, see
42 <literal>wantedBy</literal>.
43 '';
44 };
45
46 requiredBy = mkOption {
47 default = [];
48 type = types.listOf types.str;
49 description = ''
50 Units that require (i.e. depend on and need to go down with)
51 this unit. The discussion under <literal>wantedBy</literal>
52 applies here as well: inverse <literal>.requires</literal>
53 symlinks are established.
54 '';
55 };
56
57 wantedBy = mkOption {
58 default = [];
59 type = types.listOf types.str;
60 description = ''
61 Units that want (i.e. depend on) this unit. The standard way
62 to make a unit start by default at boot is to set this option
63 to <literal>[ "multi-user.target" ]</literal>. That's despite
64 the fact that the systemd.unit(5) manpage says this option
65 goes in the <literal>[Install]</literal> section that controls
66 the behaviour of <literal>systemctl enable</literal>. Since
67 such a process is stateful and thus contrary to the design of
68 NixOS, setting this option instead causes the equivalent
69 inverse <literal>.wants</literal> symlink to be present,
70 establishing the same desired relationship in a stateless way.
71 '';
72 };
73
74 aliases = mkOption {
75 default = [];
76 type = types.listOf types.str;
77 description = "Aliases of that unit.";
78 };
79
80 };
81
82 concreteUnitOptions = sharedOptions // {
83
84 text = mkOption {
85 type = types.nullOr types.str;
86 default = null;
87 description = "Text of this systemd unit.";
88 };
89
90 unit = mkOption {
91 internal = true;
92 description = "The generated unit.";
93 };
94
95 };
96
97 commonUnitOptions = sharedOptions // {
98
99 description = mkOption {
100 default = "";
101 type = types.str;
102 description = "Description of this unit used in systemd messages and progress indicators.";
103 };
104
105 documentation = mkOption {
106 default = [];
107 type = types.listOf types.str;
108 description = "A list of URIs referencing documentation for this unit or its configuration.";
109 };
110
111 requires = mkOption {
112 default = [];
113 type = types.listOf types.str;
114 description = ''
115 Start the specified units when this unit is started, and stop
116 this unit when the specified units are stopped or fail.
117 '';
118 };
119
120 wants = mkOption {
121 default = [];
122 type = types.listOf types.str;
123 description = ''
124 Start the specified units when this unit is started.
125 '';
126 };
127
128 after = mkOption {
129 default = [];
130 type = types.listOf types.str;
131 description = ''
132 If the specified units are started at the same time as
133 this unit, delay this unit until they have started.
134 '';
135 };
136
137 before = mkOption {
138 default = [];
139 type = types.listOf types.str;
140 description = ''
141 If the specified units are started at the same time as
142 this unit, delay them until this unit has started.
143 '';
144 };
145
146 bindsTo = mkOption {
147 default = [];
148 type = types.listOf types.str;
149 description = ''
150 Like ‘requires’, but in addition, if the specified units
151 unexpectedly disappear, this unit will be stopped as well.
152 '';
153 };
154
155 partOf = mkOption {
156 default = [];
157 type = types.listOf types.str;
158 description = ''
159 If the specified units are stopped or restarted, then this
160 unit is stopped or restarted as well.
161 '';
162 };
163
164 conflicts = mkOption {
165 default = [];
166 type = types.listOf types.str;
167 description = ''
168 If the specified units are started, then this unit is stopped
169 and vice versa.
170 '';
171 };
172
173 requisite = mkOption {
174 default = [];
175 type = types.listOf types.str;
176 description = ''
177 Similar to requires. However if the units listed are not started,
178 they will not be started and the transaction will fail.
179 '';
180 };
181
182 unitConfig = mkOption {
183 default = {};
184 example = { RequiresMountsFor = "/data"; };
185 type = types.attrsOf unitOption;
186 description = ''
187 Each attribute in this set specifies an option in the
188 <literal>[Unit]</literal> section of the unit. See
189 <citerefentry><refentrytitle>systemd.unit</refentrytitle>
190 <manvolnum>5</manvolnum></citerefentry> for details.
191 '';
192 };
193
194 restartTriggers = mkOption {
195 default = [];
196 type = types.listOf types.unspecified;
197 description = ''
198 An arbitrary list of items such as derivations. If any item
199 in the list changes between reconfigurations, the service will
200 be restarted.
201 '';
202 };
203
204 onFailure = mkOption {
205 default = [];
206 type = types.listOf types.str;
207 description = ''
208 A list of one or more units that are activated when
209 this unit enters the "failed" state.
210 '';
211 };
212
213 startLimitBurst = mkOption {
214 type = types.int;
215 description = ''
216 Configure unit start rate limiting. Units which are started
217 more than startLimitBurst times within an interval time
218 interval are not permitted to start any more.
219 '';
220 };
221
222 startLimitIntervalSec = mkOption {
223 type = types.int;
224 description = ''
225 Configure unit start rate limiting. Units which are started
226 more than startLimitBurst times within an interval time
227 interval are not permitted to start any more.
228 '';
229 };
230
231 };
232
233
234 serviceOptions = commonUnitOptions // {
235
236 environment = mkOption {
237 default = {};
238 type = with types; attrsOf (nullOr (oneOf [ str path package ]));
239 example = { PATH = "/foo/bar/bin"; LANG = "nl_NL.UTF-8"; };
240 description = "Environment variables passed to the service's processes.";
241 };
242
243 path = mkOption {
244 default = [];
245 type = with types; listOf (oneOf [ package str ]);
246 description = ''
247 Packages added to the service's <envar>PATH</envar>
248 environment variable. Both the <filename>bin</filename>
249 and <filename>sbin</filename> subdirectories of each
250 package are added.
251 '';
252 };
253
254 serviceConfig = mkOption {
255 default = {};
256 example =
257 { RestartSec = 5;
258 };
259 type = types.addCheck (types.attrsOf unitOption) checkService;
260 description = ''
261 Each attribute in this set specifies an option in the
262 <literal>[Service]</literal> section of the unit. See
263 <citerefentry><refentrytitle>systemd.service</refentrytitle>
264 <manvolnum>5</manvolnum></citerefentry> for details.
265 '';
266 };
267
268 script = mkOption {
269 type = types.lines;
270 default = "";
271 description = "Shell commands executed as the service's main process.";
272 };
273
274 scriptArgs = mkOption {
275 type = types.str;
276 default = "";
277 description = "Arguments passed to the main process script.";
278 };
279
280 preStart = mkOption {
281 type = types.lines;
282 default = "";
283 description = ''
284 Shell commands executed before the service's main process
285 is started.
286 '';
287 };
288
289 postStart = mkOption {
290 type = types.lines;
291 default = "";
292 description = ''
293 Shell commands executed after the service's main process
294 is started.
295 '';
296 };
297
298 reload = mkOption {
299 type = types.lines;
300 default = "";
301 description = ''
302 Shell commands executed when the service's main process
303 is reloaded.
304 '';
305 };
306
307 preStop = mkOption {
308 type = types.lines;
309 default = "";
310 description = ''
311 Shell commands executed to stop the service.
312 '';
313 };
314
315 postStop = mkOption {
316 type = types.lines;
317 default = "";
318 description = ''
319 Shell commands executed after the service's main process
320 has exited.
321 '';
322 };
323
324 restartIfChanged = mkOption {
325 type = types.bool;
326 default = true;
327 description = ''
328 Whether the service should be restarted during a NixOS
329 configuration switch if its definition has changed.
330 '';
331 };
332
333 reloadIfChanged = mkOption {
334 type = types.bool;
335 default = false;
336 description = ''
337 Whether the service should be reloaded during a NixOS
338 configuration switch if its definition has changed. If
339 enabled, the value of <option>restartIfChanged</option> is
340 ignored.
341 '';
342 };
343
344 stopIfChanged = mkOption {
345 type = types.bool;
346 default = true;
347 description = ''
348 If set, a changed unit is restarted by calling
349 <command>systemctl stop</command> in the old configuration,
350 then <command>systemctl start</command> in the new one.
351 Otherwise, it is restarted in a single step using
352 <command>systemctl restart</command> in the new configuration.
353 The latter is less correct because it runs the
354 <literal>ExecStop</literal> commands from the new
355 configuration.
356 '';
357 };
358
359 startAt = mkOption {
360 type = with types; either str (listOf str);
361 default = [];
362 example = "Sun 14:00:00";
363 description = ''
364 Automatically start this unit at the given date/time, which
365 must be in the format described in
366 <citerefentry><refentrytitle>systemd.time</refentrytitle>
367 <manvolnum>7</manvolnum></citerefentry>. This is equivalent
368 to adding a corresponding timer unit with
369 <option>OnCalendar</option> set to the value given here.
370 '';
371 apply = v: if isList v then v else [ v ];
372 };
373
374 };
375
376
377 socketOptions = commonUnitOptions // {
378
379 listenStreams = mkOption {
380 default = [];
381 type = types.listOf types.str;
382 example = [ "0.0.0.0:993" "/run/my-socket" ];
383 description = ''
384 For each item in this list, a <literal>ListenStream</literal>
385 option in the <literal>[Socket]</literal> section will be created.
386 '';
387 };
388
389 listenDatagrams = mkOption {
390 default = [];
391 type = types.listOf types.str;
392 example = [ "0.0.0.0:993" "/run/my-socket" ];
393 description = ''
394 For each item in this list, a <literal>ListenDatagram</literal>
395 option in the <literal>[Socket]</literal> section will be created.
396 '';
397 };
398
399 socketConfig = mkOption {
400 default = {};
401 example = { ListenStream = "/run/my-socket"; };
402 type = types.attrsOf unitOption;
403 description = ''
404 Each attribute in this set specifies an option in the
405 <literal>[Socket]</literal> section of the unit. See
406 <citerefentry><refentrytitle>systemd.socket</refentrytitle>
407 <manvolnum>5</manvolnum></citerefentry> for details.
408 '';
409 };
410
411 };
412
413
414 timerOptions = commonUnitOptions // {
415
416 timerConfig = mkOption {
417 default = {};
418 example = { OnCalendar = "Sun 14:00:00"; Unit = "foo.service"; };
419 type = types.attrsOf unitOption;
420 description = ''
421 Each attribute in this set specifies an option in the
422 <literal>[Timer]</literal> section of the unit. See
423 <citerefentry><refentrytitle>systemd.timer</refentrytitle>
424 <manvolnum>5</manvolnum></citerefentry> and
425 <citerefentry><refentrytitle>systemd.time</refentrytitle>
426 <manvolnum>7</manvolnum></citerefentry> for details.
427 '';
428 };
429
430 };
431
432
433 pathOptions = commonUnitOptions // {
434
435 pathConfig = mkOption {
436 default = {};
437 example = { PathChanged = "/some/path"; Unit = "changedpath.service"; };
438 type = types.attrsOf unitOption;
439 description = ''
440 Each attribute in this set specifies an option in the
441 <literal>[Path]</literal> section of the unit. See
442 <citerefentry><refentrytitle>systemd.path</refentrytitle>
443 <manvolnum>5</manvolnum></citerefentry> for details.
444 '';
445 };
446
447 };
448
449
450 mountOptions = commonUnitOptions // {
451
452 what = mkOption {
453 example = "/dev/sda1";
454 type = types.str;
455 description = "Absolute path of device node, file or other resource. (Mandatory)";
456 };
457
458 where = mkOption {
459 example = "/mnt";
460 type = types.str;
461 description = ''
462 Absolute path of a directory of the mount point.
463 Will be created if it doesn't exist. (Mandatory)
464 '';
465 };
466
467 type = mkOption {
468 default = "";
469 example = "ext4";
470 type = types.str;
471 description = "File system type.";
472 };
473
474 options = mkOption {
475 default = "";
476 example = "noatime";
477 type = types.commas;
478 description = "Options used to mount the file system.";
479 };
480
481 mountConfig = mkOption {
482 default = {};
483 example = { DirectoryMode = "0775"; };
484 type = types.attrsOf unitOption;
485 description = ''
486 Each attribute in this set specifies an option in the
487 <literal>[Mount]</literal> section of the unit. See
488 <citerefentry><refentrytitle>systemd.mount</refentrytitle>
489 <manvolnum>5</manvolnum></citerefentry> for details.
490 '';
491 };
492 };
493
494 automountOptions = commonUnitOptions // {
495
496 where = mkOption {
497 example = "/mnt";
498 type = types.str;
499 description = ''
500 Absolute path of a directory of the mount point.
501 Will be created if it doesn't exist. (Mandatory)
502 '';
503 };
504
505 automountConfig = mkOption {
506 default = {};
507 example = { DirectoryMode = "0775"; };
508 type = types.attrsOf unitOption;
509 description = ''
510 Each attribute in this set specifies an option in the
511 <literal>[Automount]</literal> section of the unit. See
512 <citerefentry><refentrytitle>systemd.automount</refentrytitle>
513 <manvolnum>5</manvolnum></citerefentry> for details.
514 '';
515 };
516 };
517
518 targetOptions = commonUnitOptions;
519
520 sliceOptions = commonUnitOptions // {
521
522 sliceConfig = mkOption {
523 default = {};
524 example = { MemoryMax = "2G"; };
525 type = types.attrsOf unitOption;
526 description = ''
527 Each attribute in this set specifies an option in the
528 <literal>[Slice]</literal> section of the unit. See
529 <citerefentry><refentrytitle>systemd.slice</refentrytitle>
530 <manvolnum>5</manvolnum></citerefentry> for details.
531 '';
532 };
533
534 };
535
536}
diff --git a/modules/yggdrasil-wg/default.nix b/modules/yggdrasil-wg/default.nix
index 55fb1e9d..1e52ba06 100644
--- a/modules/yggdrasil-wg/default.nix
+++ b/modules/yggdrasil-wg/default.nix
@@ -202,7 +202,7 @@ in {
202 Name = "yggdrasil"; 202 Name = "yggdrasil";
203 }; 203 };
204 address = batHostIPs.${hostName}; 204 address = batHostIPs.${hostName};
205 dns = ["[2a03:4000:52:ada:1:1::]"]; 205 dns = ["2a03:4000:52:ada:1:1::"];
206 domains = ["yggdrasil"]; 206 domains = ["yggdrasil"];
207 routes = [ 207 routes = [
208 { routeConfig = { 208 { routeConfig = {
@@ -222,7 +222,7 @@ in {
222 Table = "yggdrasil"; 222 Table = "yggdrasil";
223 }; 223 };
224 } 224 }
225 ] ++ (concatMap (router: map (rAddr: { routeConfig = { Destination = "::/0"; Gateway = stripSubnet rAddr; GatewayOnLink = true; Table = "yggdrasil"; }; }) batHostIPs.${router}) routers); 225 ] ++ (concatMap (router: map (rAddr: { routeConfig = { Destination = "::/0"; Gateway = stripSubnet rAddr; GatewayOnLink = true; Table = "yggdrasil"; }; }) batHostIPs.${router}) (filter (router: router != hostName) routers));
226 routingPolicyRules = map (addr: { routingPolicyRuleConfig = { Table = "yggdrasil"; From = stripSubnet addr; Priority = 1; }; }) batHostIPs.${hostName}; 226 routingPolicyRules = map (addr: { routingPolicyRuleConfig = { Table = "yggdrasil"; From = stripSubnet addr; Priority = 1; }; }) batHostIPs.${hostName};
227 linkConfig = { 227 linkConfig = {
228 MACAddress = "${batHostMACs.${hostName}}"; 228 MACAddress = "${batHostMACs.${hostName}}";
@@ -236,13 +236,8 @@ in {
236 }; 236 };
237 }; 237 };
238 } // listToAttrs (map familyToYggdrasilNetwork hostFamilies) // listToAttrs (concatMap (family: imap0 (linkToGreNetwork family) hostLinks.${family}) hostFamilies); 238 } // listToAttrs (map familyToYggdrasilNetwork hostFamilies) // listToAttrs (concatMap (family: imap0 (linkToGreNetwork family) hostLinks.${family}) hostFamilies);
239 };
240 239
241 environment.etc."systemd/networkd.conf" = mkIf inNetwork { 240 config.routeTables.yggdrasil = 1024;
242 text = ''
243 [Network]
244 RouteTable=yggdrasil:1024
245 '';
246 }; 241 };
247 242
248 sops.secrets = listToAttrs (map familyToSopsSecret hostFamilies); 243 sops.secrets = listToAttrs (map familyToSopsSecret hostFamilies);