systemd.nspawn: add definition (#18320)

this adds the option to manage systemd.nspawn files via
config.systemd.nspawn. The files are placed in "/etc/systemd/nspawn".

authored by Alexander Ried and committed by Franz Pletz ce7739a4 e67e18a5

+122
+1
nixos/modules/module-list.nix
··· 559 559 ./system/boot/stage-1.nix 560 560 ./system/boot/stage-2.nix 561 561 ./system/boot/systemd.nix 562 + ./system/boot/systemd-nspawn.nix 562 563 ./system/boot/timesyncd.nix 563 564 ./system/boot/tmp.nix 564 565 ./system/etc/etc.nix
+121
nixos/modules/system/boot/systemd-nspawn.nix
··· 1 + { config, lib , pkgs, ...}: 2 + 3 + with lib; 4 + with import ./systemd-unit-options.nix { inherit config lib; }; 5 + with import ./systemd-lib.nix { inherit config lib pkgs; }; 6 + 7 + let 8 + cfg = config.systemd.nspawn; 9 + assertions = [ 10 + # boot = true -> processtwo != true 11 + ]; 12 + 13 + checkExec = checkUnitConfig "Exec" [ 14 + (assertOnlyFields [ 15 + "Boot" "ProcessTwo" "Parameters" "Environment" "User" "WorkingDirectory" 16 + "Capability" "DropCapability" "KillSignal" "Personality" "MachineId" 17 + "PrivateUsers" 18 + ]) 19 + (assertValueOneOf "Boot" boolValues) 20 + (assertValueOneOf "ProcessTwo" boolValues) 21 + (assertValueOneOf "PrivateUsers" (boolValues ++ [ "pick" ])) 22 + ]; 23 + 24 + checkFiles = checkUnitConfig "Files" [ 25 + (assertOnlyFields [ 26 + "ReadOnly" "Volatile" "Bind" "BindReadOnly" "TemporaryFileSystems" 27 + "PrivateUsersChown" 28 + ]) 29 + (assertValueOneOf "ReadOnly" boolValues) 30 + (assertValueOneOf "Volatile" (boolValues ++ [ "state" ])) 31 + (assertValueOneOf "PrivateUsersChown" boolValues) 32 + ]; 33 + 34 + checkNetwork = checkUnitConfig "Network" [ 35 + (assertOnlyFields [ 36 + "Private" "VirtualEthernet" "VirtualEthernetExtra" "Interface" "MACVLAN" 37 + "IPVLAN" "Bridge" "Zone" "Port" 38 + ]) 39 + (assertValueOneOf "Private" boolValues) 40 + (assertValueOneOf "VirtualEthernet" boolValues) 41 + ]; 42 + 43 + instanceOptions = { 44 + 45 + execConfig = mkOption { 46 + default = {}; 47 + example = { Parameters = "/bin/sh"; }; 48 + type = types.addCheck (types.attrsOf unitOption) checkExec; 49 + description = '' 50 + Each attribute in this set specifies an option in the 51 + <literal>[Exec]</literal> section of this unit. See 52 + <citerefentry><refentrytitle>systemd.nspawn</refentrytitle> 53 + <manvolnum>5</manvolnum></citerefentry> for details. 54 + ''; 55 + }; 56 + 57 + filesConfig = mkOption { 58 + default = {}; 59 + example = { Bind = [ "/home/alice" ]; }; 60 + type = types.addCheck (types.attrsOf unitOption) checkFiles; 61 + description = '' 62 + Each attribute in this set specifies an option in the 63 + <literal>[Files]</literal> section of this unit. See 64 + <citerefentry><refentrytitle>systemd.nspawn</refentrytitle> 65 + <manvolnum>5</manvolnum></citerefentry> for details. 66 + ''; 67 + }; 68 + 69 + networkConfig = mkOption { 70 + default = {}; 71 + example = { Private = false; }; 72 + type = types.addCheck (types.attrsOf unitOption) checkNetwork; 73 + description = '' 74 + Each attribute in this set specifies an option in the 75 + <literal>[Network]</literal> section of this unit. See 76 + <citerefentry><refentrytitle>systemd.nspawn</refentrytitle> 77 + <manvolnum>5</manvolnum></citerefentry> for details. 78 + ''; 79 + }; 80 + 81 + }; 82 + 83 + instanceToUnit = name: def: 84 + { text = '' 85 + [Exec] 86 + ${attrsToSection def.execConfig} 87 + 88 + [Files] 89 + ${attrsToSection def.filesConfig} 90 + 91 + [Network] 92 + ${attrsToSection def.networkConfig} 93 + ''; 94 + }; 95 + 96 + in { 97 + 98 + options = { 99 + 100 + systemd.nspawn = mkOption { 101 + default = {}; 102 + type = types.attrsOf types.optionSet; 103 + options = [ instanceOptions ]; 104 + description = "Definition of systemd-nspawn configurations."; 105 + }; 106 + 107 + }; 108 + 109 + config = 110 + let 111 + units = mapAttrs' (n: v: nameValuePair "${n}.nspawn" (instanceToUnit n v)) cfg.instances; 112 + in mkIf (cfg != {}) { 113 + 114 + environment.etc."systemd/nspawn".source = generateUnits "nspawn" units [] []; 115 + 116 + systemd.services."systemd-nspawn@" = { 117 + wantedBy = [ "machine.target" ]; 118 + }; 119 + }; 120 + 121 + }