1{ 2 config, 3 lib, 4 pkgs, 5 utils, 6 ... 7}: 8 9with utils.systemdUtils.unitOptions; 10with utils.systemdUtils.lib; 11with lib; 12 13let 14 cfg = config.systemd.nspawn; 15 16 checkExec = checkUnitConfig "Exec" [ 17 (assertOnlyFields [ 18 "Boot" 19 "ProcessTwo" 20 "Parameters" 21 "Environment" 22 "User" 23 "WorkingDirectory" 24 "PivotRoot" 25 "Capability" 26 "DropCapability" 27 "NoNewPrivileges" 28 "KillSignal" 29 "Personality" 30 "MachineID" 31 "PrivateUsers" 32 "NotifyReady" 33 "SystemCallFilter" 34 "LimitCPU" 35 "LimitFSIZE" 36 "LimitDATA" 37 "LimitSTACK" 38 "LimitCORE" 39 "LimitRSS" 40 "LimitNOFILE" 41 "LimitAS" 42 "LimitNPROC" 43 "LimitMEMLOCK" 44 "LimitLOCKS" 45 "LimitSIGPENDING" 46 "LimitMSGQUEUE" 47 "LimitNICE" 48 "LimitRTPRIO" 49 "LimitRTTIME" 50 "OOMScoreAdjust" 51 "CPUAffinity" 52 "Hostname" 53 "ResolvConf" 54 "Timezone" 55 "LinkJournal" 56 "Ephemeral" 57 "AmbientCapability" 58 ]) 59 (assertValueOneOf "Boot" boolValues) 60 (assertValueOneOf "ProcessTwo" boolValues) 61 (assertValueOneOf "NotifyReady" boolValues) 62 ]; 63 64 checkFiles = checkUnitConfig "Files" [ 65 (assertOnlyFields [ 66 "ReadOnly" 67 "Volatile" 68 "Bind" 69 "BindReadOnly" 70 "TemporaryFileSystem" 71 "Overlay" 72 "OverlayReadOnly" 73 "PrivateUsersChown" 74 "BindUser" 75 "Inaccessible" 76 "PrivateUsersOwnership" 77 ]) 78 (assertValueOneOf "ReadOnly" boolValues) 79 (assertValueOneOf "Volatile" (boolValues ++ [ "state" ])) 80 (assertValueOneOf "PrivateUsersChown" boolValues) 81 (assertValueOneOf "PrivateUsersOwnership" [ 82 "off" 83 "chown" 84 "map" 85 "auto" 86 ]) 87 ]; 88 89 checkNetwork = checkUnitConfig "Network" [ 90 (assertOnlyFields [ 91 "Private" 92 "VirtualEthernet" 93 "VirtualEthernetExtra" 94 "Interface" 95 "MACVLAN" 96 "IPVLAN" 97 "Bridge" 98 "Zone" 99 "Port" 100 ]) 101 (assertValueOneOf "Private" boolValues) 102 (assertValueOneOf "VirtualEthernet" boolValues) 103 ]; 104 105 instanceOptions = { 106 options = (getAttrs [ "enable" ] sharedOptions) // { 107 execConfig = mkOption { 108 default = { }; 109 example = { 110 Parameters = "/bin/sh"; 111 }; 112 type = types.addCheck (types.attrsOf unitOption) checkExec; 113 description = '' 114 Each attribute in this set specifies an option in the 115 `[Exec]` section of this unit. See 116 {manpage}`systemd.nspawn(5)` for details. 117 ''; 118 }; 119 120 filesConfig = mkOption { 121 default = { }; 122 example = { 123 Bind = [ "/home/alice" ]; 124 }; 125 type = types.addCheck (types.attrsOf unitOption) checkFiles; 126 description = '' 127 Each attribute in this set specifies an option in the 128 `[Files]` section of this unit. See 129 {manpage}`systemd.nspawn(5)` for details. 130 ''; 131 }; 132 133 networkConfig = mkOption { 134 default = { }; 135 example = { 136 Private = false; 137 }; 138 type = types.addCheck (types.attrsOf unitOption) checkNetwork; 139 description = '' 140 Each attribute in this set specifies an option in the 141 `[Network]` section of this unit. See 142 {manpage}`systemd.nspawn(5)` for details. 143 ''; 144 }; 145 }; 146 147 }; 148 149 instanceToUnit = 150 name: def: 151 let 152 base = { 153 text = '' 154 [Exec] 155 ${attrsToSection def.execConfig} 156 157 [Files] 158 ${attrsToSection def.filesConfig} 159 160 [Network] 161 ${attrsToSection def.networkConfig} 162 ''; 163 } 164 // def; 165 in 166 base // { unit = makeUnit name base; }; 167 168in 169{ 170 171 options = { 172 173 systemd.nspawn = mkOption { 174 default = { }; 175 type = with types; attrsOf (submodule instanceOptions); 176 description = "Definition of systemd-nspawn configurations."; 177 }; 178 179 }; 180 181 config = 182 let 183 units = mapAttrs' ( 184 n: v: 185 let 186 nspawnFile = "${n}.nspawn"; 187 in 188 nameValuePair nspawnFile (instanceToUnit nspawnFile v) 189 ) cfg; 190 in 191 mkMerge [ 192 (mkIf (cfg != { }) { 193 environment.etc."systemd/nspawn".source = mkIf (cfg != { }) (generateUnits { 194 allowCollisions = false; 195 type = "nspawn"; 196 inherit units; 197 upstreamUnits = [ ]; 198 upstreamWants = [ ]; 199 }); 200 }) 201 { 202 systemd.targets.multi-user.wants = [ "machines.target" ]; 203 systemd.services."systemd-nspawn@".environment = { 204 SYSTEMD_NSPAWN_UNIFIED_HIERARCHY = mkDefault "1"; 205 }; 206 } 207 ]; 208}