depot/third_party/nixpkgs/nixos/modules/system/boot/systemd/nspawn.nix

131 lines
4 KiB
Nix
Raw Normal View History

{ config, lib, pkgs, utils, ...}:
with utils.systemdUtils.unitOptions;
with utils.systemdUtils.lib;
with lib;
let
cfg = config.systemd.nspawn;
checkExec = checkUnitConfig "Exec" [
(assertOnlyFields [
"Boot" "ProcessTwo" "Parameters" "Environment" "User" "WorkingDirectory"
"PivotRoot" "Capability" "DropCapability" "NoNewPrivileges" "KillSignal"
"Personality" "MachineId" "PrivateUsers" "NotifyReady" "SystemCallFilter"
"LimitCPU" "LimitFSIZE" "LimitDATA" "LimitSTACK" "LimitCORE" "LimitRSS"
"LimitNOFILE" "LimitAS" "LimitNPROC" "LimitMEMLOCK" "LimitLOCKS"
"LimitSIGPENDING" "LimitMSGQUEUE" "LimitNICE" "LimitRTPRIO" "LimitRTTIME"
"OOMScoreAdjust" "CPUAffinity" "Hostname" "ResolvConf" "Timezone"
"LinkJournal" "Ephemeral" "AmbientCapability"
])
(assertValueOneOf "Boot" boolValues)
(assertValueOneOf "ProcessTwo" boolValues)
(assertValueOneOf "NotifyReady" boolValues)
];
checkFiles = checkUnitConfig "Files" [
(assertOnlyFields [
"ReadOnly" "Volatile" "Bind" "BindReadOnly" "TemporaryFileSystem"
"Overlay" "OverlayReadOnly" "PrivateUsersChown" "BindUser"
"Inaccessible" "PrivateUserOwnership"
])
(assertValueOneOf "ReadOnly" boolValues)
(assertValueOneOf "Volatile" (boolValues ++ [ "state" ]))
(assertValueOneOf "PrivateUsersChown" boolValues)
(assertValueOneOf "PrivateUserOwnership" [ "off" "chown" "map" "auto" ])
];
checkNetwork = checkUnitConfig "Network" [
(assertOnlyFields [
"Private" "VirtualEthernet" "VirtualEthernetExtra" "Interface" "MACVLAN"
"IPVLAN" "Bridge" "Zone" "Port"
])
(assertValueOneOf "Private" boolValues)
(assertValueOneOf "VirtualEthernet" boolValues)
];
instanceOptions = {
options = sharedOptions // {
execConfig = mkOption {
default = {};
example = { Parameters = "/bin/sh"; };
type = types.addCheck (types.attrsOf unitOption) checkExec;
description = lib.mdDoc ''
Each attribute in this set specifies an option in the
`[Exec]` section of this unit. See
{manpage}`systemd.nspawn(5)` for details.
'';
};
filesConfig = mkOption {
default = {};
example = { Bind = [ "/home/alice" ]; };
type = types.addCheck (types.attrsOf unitOption) checkFiles;
description = lib.mdDoc ''
Each attribute in this set specifies an option in the
`[Files]` section of this unit. See
{manpage}`systemd.nspawn(5)` for details.
'';
};
networkConfig = mkOption {
default = {};
example = { Private = false; };
type = types.addCheck (types.attrsOf unitOption) checkNetwork;
description = lib.mdDoc ''
Each attribute in this set specifies an option in the
`[Network]` section of this unit. See
{manpage}`systemd.nspawn(5)` for details.
'';
};
};
};
instanceToUnit = name: def:
let base = {
text = ''
[Exec]
${attrsToSection def.execConfig}
[Files]
${attrsToSection def.filesConfig}
[Network]
${attrsToSection def.networkConfig}
'';
} // def;
in base // { unit = makeUnit name base; };
in {
options = {
systemd.nspawn = mkOption {
default = {};
type = with types; attrsOf (submodule instanceOptions);
description = lib.mdDoc "Definition of systemd-nspawn configurations.";
};
};
config =
let
units = mapAttrs' (n: v: let nspawnFile = "${n}.nspawn"; in nameValuePair nspawnFile (instanceToUnit nspawnFile v)) cfg;
in
mkMerge [
(mkIf (cfg != {}) {
environment.etc."systemd/nspawn".source = mkIf (cfg != {}) (generateUnits {
allowCollisions = false;
type = "nspawn";
inherit units;
upstreamUnits = [];
upstreamWants = [];
});
})
{
systemd.targets.multi-user.wants = [ "machines.target" ];
}
];
}