diff --git a/nixos/lib/systemd-lib.nix b/nixos/lib/systemd-lib.nix
index dbf8d2db5b62..589f1e2c7185 100644
--- a/nixos/lib/systemd-lib.nix
+++ b/nixos/lib/systemd-lib.nix
@@ -273,9 +273,9 @@ in rec {
{ Conflicts = toString config.conflicts; }
// optionalAttrs (config.requisite != [])
{ Requisite = toString config.requisite; }
- // optionalAttrs (config.restartTriggers != [])
+ // optionalAttrs (config ? restartTriggers && config.restartTriggers != [])
{ X-Restart-Triggers = toString config.restartTriggers; }
- // optionalAttrs (config.reloadTriggers != [])
+ // optionalAttrs (config ? reloadTriggers && config.reloadTriggers != [])
{ X-Reload-Triggers = toString config.reloadTriggers; }
// optionalAttrs (config.description != "") {
Description = config.description; }
@@ -291,36 +291,8 @@ in rec {
};
};
- serviceConfig = { name, config, ... }: {
- config = mkMerge
- [ {
- environment.PATH = mkIf (config.path != []) "${makeBinPath config.path}:${makeSearchPathOutput "bin" "sbin" config.path}";
- }
- (mkIf (config ? preStart && config.preStart != "")
- { serviceConfig.ExecStartPre =
- [ (makeJobScript "${name}-pre-start" config.preStart) ];
- })
- (mkIf (config ? script && config.script != "")
- { serviceConfig.ExecStart =
- makeJobScript "${name}-start" config.script + " " + config.scriptArgs;
- })
- (mkIf (config ? postStart && config.postStart != "")
- { serviceConfig.ExecStartPost =
- [ (makeJobScript "${name}-post-start" config.postStart) ];
- })
- (mkIf (config ? reload && config.reload != "")
- { serviceConfig.ExecReload =
- makeJobScript "${name}-reload" config.reload;
- })
- (mkIf (config ? preStop && config.preStop != "")
- { serviceConfig.ExecStop =
- makeJobScript "${name}-pre-stop" config.preStop;
- })
- (mkIf (config ? postStart && config.postStop != "")
- { serviceConfig.ExecStopPost =
- makeJobScript "${name}-post-stop" config.postStop;
- })
- ];
+ serviceConfig = { config, ... }: {
+ config.environment.PATH = mkIf (config.path != []) "${makeBinPath config.path}:${makeSearchPathOutput "bin" "sbin" config.path}";
};
stage2ServiceConfig = {
@@ -384,12 +356,12 @@ in rec {
# systemd max line length is now 1MiB
# https://github.com/systemd/systemd/commit/e6dde451a51dc5aaa7f4d98d39b8fe735f73d2af
in if stringLength s >= 1048576 then throw "The value of the environment variable ‘${n}’ in systemd service ‘${name}.service’ is too long." else s) (attrNames env)}
- ${if def.reloadIfChanged then ''
+ ${if def ? reloadIfChanged && def.reloadIfChanged then ''
X-ReloadIfChanged=true
- '' else if !def.restartIfChanged then ''
+ '' else if (def ? restartIfChanged && !def.restartIfChanged) then ''
X-RestartIfChanged=false
'' else ""}
- ${optionalString (!def.stopIfChanged) "X-StopIfChanged=false"}
+ ${optionalString (def ? stopIfChanged && !def.stopIfChanged) "X-StopIfChanged=false"}
${attrsToSection def.serviceConfig}
'';
};
diff --git a/nixos/lib/systemd-types.nix b/nixos/lib/systemd-types.nix
index e7d504e586be..71962fab2e17 100644
--- a/nixos/lib/systemd-types.nix
+++ b/nixos/lib/systemd-types.nix
@@ -11,20 +11,27 @@ rec {
config = { unit = mkDefault (systemdUtils.lib.makeUnit name config); };
}));
- services = with types; attrsOf (submodule [ { options = serviceOptions; } unitConfig stage2ServiceConfig ]);
- initrdServices = with types; attrsOf (submodule [ { options = serviceOptions; } unitConfig stage1ServiceConfig ]);
+ services = with types; attrsOf (submodule [ stage2ServiceOptions unitConfig stage2ServiceConfig ]);
+ initrdServices = with types; attrsOf (submodule [ stage1ServiceOptions unitConfig stage1ServiceConfig ]);
- targets = with types; attrsOf (submodule [ { options = targetOptions; } unitConfig ]);
+ targets = with types; attrsOf (submodule [ stage2CommonUnitOptions unitConfig ]);
+ initrdTargets = with types; attrsOf (submodule [ stage1CommonUnitOptions unitConfig ]);
- sockets = with types; attrsOf (submodule [ { options = socketOptions; } unitConfig ]);
+ sockets = with types; attrsOf (submodule [ stage2SocketOptions unitConfig ]);
+ initrdSockets = with types; attrsOf (submodule [ stage1SocketOptions unitConfig ]);
- timers = with types; attrsOf (submodule [ { options = timerOptions; } unitConfig ]);
+ timers = with types; attrsOf (submodule [ stage2TimerOptions unitConfig ]);
+ initrdTimers = with types; attrsOf (submodule [ stage1TimerOptions unitConfig ]);
- paths = with types; attrsOf (submodule [ { options = pathOptions; } unitConfig ]);
+ paths = with types; attrsOf (submodule [ stage2PathOptions unitConfig ]);
+ initrdPaths = with types; attrsOf (submodule [ stage1PathOptions unitConfig ]);
- slices = with types; attrsOf (submodule [ { options = sliceOptions; } unitConfig ]);
+ slices = with types; attrsOf (submodule [ stage2SliceOptions unitConfig ]);
+ initrdSlices = with types; attrsOf (submodule [ stage1SliceOptions unitConfig ]);
- mounts = with types; listOf (submodule [ { options = mountOptions; } unitConfig mountConfig ]);
+ mounts = with types; listOf (submodule [ stage2MountOptions unitConfig mountConfig ]);
+ initrdMounts = with types; listOf (submodule [ stage1MountOptions unitConfig mountConfig ]);
- automounts = with types; listOf (submodule [ { options = automountOptions; } unitConfig automountConfig ]);
+ automounts = with types; listOf (submodule [ stage2AutomountOptions unitConfig automountConfig ]);
+ initrdAutomounts = with types; attrsOf (submodule [ stage1AutomountOptions unitConfig automountConfig ]);
}
diff --git a/nixos/lib/systemd-unit-options.nix b/nixos/lib/systemd-unit-options.nix
index 8029ba0e3f6c..c9d424d39119 100644
--- a/nixos/lib/systemd-unit-options.nix
+++ b/nixos/lib/systemd-unit-options.nix
@@ -94,7 +94,7 @@ in rec {
};
- commonUnitOptions = sharedOptions // {
+ commonUnitOptions = { options = (sharedOptions // {
description = mkOption {
default = "";
@@ -191,27 +191,6 @@ in rec {
'';
};
- restartTriggers = mkOption {
- default = [];
- type = types.listOf types.unspecified;
- description = ''
- An arbitrary list of items such as derivations. If any item
- in the list changes between reconfigurations, the service will
- be restarted.
- '';
- };
-
- reloadTriggers = mkOption {
- default = [];
- type = types.listOf unitOption;
- description = ''
- An arbitrary list of items such as derivations. If any item
- in the list changes between reconfigurations, the service will
- be reloaded. If anything but a reload trigger changes in the
- unit file, the unit will be restarted instead.
- '';
- };
-
onFailure = mkOption {
default = [];
type = types.listOf unitNameType;
@@ -239,10 +218,39 @@ in rec {
'';
};
+ }); };
+
+ stage2CommonUnitOptions = {
+ imports = [
+ commonUnitOptions
+ ];
+
+ options = {
+ restartTriggers = mkOption {
+ default = [];
+ type = types.listOf types.unspecified;
+ description = ''
+ An arbitrary list of items such as derivations. If any item
+ in the list changes between reconfigurations, the service will
+ be restarted.
+ '';
+ };
+
+ reloadTriggers = mkOption {
+ default = [];
+ type = types.listOf unitOption;
+ description = ''
+ An arbitrary list of items such as derivations. If any item
+ in the list changes between reconfigurations, the service will
+ be reloaded. If anything but a reload trigger changes in the
+ unit file, the unit will be restarted instead.
+ '';
+ };
+ };
};
+ stage1CommonUnitOptions = commonUnitOptions;
-
- serviceOptions = commonUnitOptions // {
+ serviceOptions = { options = {
environment = mkOption {
default = {};
@@ -276,121 +284,164 @@ in rec {
'';
};
- script = mkOption {
- type = types.lines;
- default = "";
- description = "Shell commands executed as the service's main process.";
+ }; };
+
+ stage2ServiceOptions = { name, config, ... }: {
+ imports = [
+ stage2CommonUnitOptions
+ serviceOptions
+ ];
+
+ options = {
+ script = mkOption {
+ type = types.lines;
+ default = "";
+ description = "Shell commands executed as the service's main process.";
+ };
+
+ scriptArgs = mkOption {
+ type = types.str;
+ default = "";
+ description = "Arguments passed to the main process script.";
+ };
+
+ preStart = mkOption {
+ type = types.lines;
+ default = "";
+ description = ''
+ Shell commands executed before the service's main process
+ is started.
+ '';
+ };
+
+ postStart = mkOption {
+ type = types.lines;
+ default = "";
+ description = ''
+ Shell commands executed after the service's main process
+ is started.
+ '';
+ };
+
+ reload = mkOption {
+ type = types.lines;
+ default = "";
+ description = ''
+ Shell commands executed when the service's main process
+ is reloaded.
+ '';
+ };
+
+ preStop = mkOption {
+ type = types.lines;
+ default = "";
+ description = ''
+ Shell commands executed to stop the service.
+ '';
+ };
+
+ postStop = mkOption {
+ type = types.lines;
+ default = "";
+ description = ''
+ Shell commands executed after the service's main process
+ has exited.
+ '';
+ };
+
+ restartIfChanged = mkOption {
+ type = types.bool;
+ default = true;
+ description = ''
+ Whether the service should be restarted during a NixOS
+ configuration switch if its definition has changed.
+ '';
+ };
+
+ reloadIfChanged = mkOption {
+ type = types.bool;
+ default = false;
+ description = ''
+ Whether the service should be reloaded during a NixOS
+ configuration switch if its definition has changed. If
+ enabled, the value of is
+ ignored.
+
+ This option should not be used anymore in favor of
+ which allows more granular
+ control of when a service is reloaded and when a service
+ is restarted.
+ '';
+ };
+
+ stopIfChanged = mkOption {
+ type = types.bool;
+ default = true;
+ description = ''
+ If set, a changed unit is restarted by calling
+ systemctl stop in the old configuration,
+ then systemctl start in the new one.
+ Otherwise, it is restarted in a single step using
+ systemctl restart in the new configuration.
+ The latter is less correct because it runs the
+ ExecStop commands from the new
+ configuration.
+ '';
+ };
+
+ startAt = mkOption {
+ type = with types; either str (listOf str);
+ default = [];
+ example = "Sun 14:00:00";
+ description = ''
+ Automatically start this unit at the given date/time, which
+ must be in the format described in
+ systemd.time
+ 7. This is equivalent
+ to adding a corresponding timer unit with
+ set to the value given here.
+ '';
+ apply = v: if isList v then v else [ v ];
+ };
};
- scriptArgs = mkOption {
- type = types.str;
- default = "";
- description = "Arguments passed to the main process script.";
- };
-
- preStart = mkOption {
- type = types.lines;
- default = "";
- description = ''
- Shell commands executed before the service's main process
- is started.
- '';
- };
-
- postStart = mkOption {
- type = types.lines;
- default = "";
- description = ''
- Shell commands executed after the service's main process
- is started.
- '';
- };
-
- reload = mkOption {
- type = types.lines;
- default = "";
- description = ''
- Shell commands executed when the service's main process
- is reloaded.
- '';
- };
-
- preStop = mkOption {
- type = types.lines;
- default = "";
- description = ''
- Shell commands executed to stop the service.
- '';
- };
-
- postStop = mkOption {
- type = types.lines;
- default = "";
- description = ''
- Shell commands executed after the service's main process
- has exited.
- '';
- };
-
- restartIfChanged = mkOption {
- type = types.bool;
- default = true;
- description = ''
- Whether the service should be restarted during a NixOS
- configuration switch if its definition has changed.
- '';
- };
-
- reloadIfChanged = mkOption {
- type = types.bool;
- default = false;
- description = ''
- Whether the service should be reloaded during a NixOS
- configuration switch if its definition has changed. If
- enabled, the value of is
- ignored.
-
- This option should not be used anymore in favor of
- which allows more granular
- control of when a service is reloaded and when a service
- is restarted.
- '';
- };
-
- stopIfChanged = mkOption {
- type = types.bool;
- default = true;
- description = ''
- If set, a changed unit is restarted by calling
- systemctl stop in the old configuration,
- then systemctl start in the new one.
- Otherwise, it is restarted in a single step using
- systemctl restart in the new configuration.
- The latter is less correct because it runs the
- ExecStop commands from the new
- configuration.
- '';
- };
-
- startAt = mkOption {
- type = with types; either str (listOf str);
- default = [];
- example = "Sun 14:00:00";
- description = ''
- Automatically start this unit at the given date/time, which
- must be in the format described in
- systemd.time
- 7. This is equivalent
- to adding a corresponding timer unit with
- set to the value given here.
- '';
- apply = v: if isList v then v else [ v ];
- };
+ config = mkMerge
+ [ (mkIf (config.preStart != "")
+ { serviceConfig.ExecStartPre =
+ [ (makeJobScript "${name}-pre-start" config.preStart) ];
+ })
+ (mkIf (config.script != "")
+ { serviceConfig.ExecStart =
+ makeJobScript "${name}-start" config.script + " " + config.scriptArgs;
+ })
+ (mkIf (config.postStart != "")
+ { serviceConfig.ExecStartPost =
+ [ (makeJobScript "${name}-post-start" config.postStart) ];
+ })
+ (mkIf (config.reload != "")
+ { serviceConfig.ExecReload =
+ makeJobScript "${name}-reload" config.reload;
+ })
+ (mkIf (config.preStop != "")
+ { serviceConfig.ExecStop =
+ makeJobScript "${name}-pre-stop" config.preStop;
+ })
+ (mkIf (config.postStop != "")
+ { serviceConfig.ExecStopPost =
+ makeJobScript "${name}-post-stop" config.postStop;
+ })
+ ];
+ };
+ stage1ServiceOptions = {
+ imports = [
+ stage1CommonUnitOptions
+ serviceOptions
+ ];
};
- socketOptions = commonUnitOptions // {
+ socketOptions = { options = {
listenStreams = mkOption {
default = [];
@@ -424,10 +475,24 @@ in rec {
'';
};
+ }; };
+
+ stage2SocketOptions = {
+ imports = [
+ stage2CommonUnitOptions
+ socketOptions
+ ];
+ };
+
+ stage1SocketOptions = {
+ imports = [
+ stage1CommonUnitOptions
+ socketOptions
+ ];
};
- timerOptions = commonUnitOptions // {
+ timerOptions = { options = {
timerConfig = mkOption {
default = {};
@@ -443,10 +508,24 @@ in rec {
'';
};
+ }; };
+
+ stage2TimerOptions = {
+ imports = [
+ stage2CommonUnitOptions
+ timerOptions
+ ];
+ };
+
+ stage1TimerOptions = {
+ imports = [
+ stage1CommonUnitOptions
+ timerOptions
+ ];
};
- pathOptions = commonUnitOptions // {
+ pathOptions = { options = {
pathConfig = mkOption {
default = {};
@@ -460,10 +539,24 @@ in rec {
'';
};
+ }; };
+
+ stage2PathOptions = {
+ imports = [
+ stage2CommonUnitOptions
+ pathOptions
+ ];
+ };
+
+ stage1PathOptions = {
+ imports = [
+ stage1CommonUnitOptions
+ pathOptions
+ ];
};
- mountOptions = commonUnitOptions // {
+ mountOptions = { options = {
what = mkOption {
example = "/dev/sda1";
@@ -505,9 +598,23 @@ in rec {
5 for details.
'';
};
+ }; };
+
+ stage2MountOptions = {
+ imports = [
+ stage2CommonUnitOptions
+ mountOptions
+ ];
};
- automountOptions = commonUnitOptions // {
+ stage1MountOptions = {
+ imports = [
+ stage1CommonUnitOptions
+ mountOptions
+ ];
+ };
+
+ automountOptions = { options = {
where = mkOption {
example = "/mnt";
@@ -529,11 +636,23 @@ in rec {
5 for details.
'';
};
+ }; };
+
+ stage2AutomountOptions = {
+ imports = [
+ stage2CommonUnitOptions
+ automountOptions
+ ];
};
- targetOptions = commonUnitOptions;
+ stage1AutomountOptions = {
+ imports = [
+ stage1CommonUnitOptions
+ automountOptions
+ ];
+ };
- sliceOptions = commonUnitOptions // {
+ sliceOptions = { options = {
sliceConfig = mkOption {
default = {};
@@ -547,6 +666,20 @@ in rec {
'';
};
+ }; };
+
+ stage2SliceOptions = {
+ imports = [
+ stage2CommonUnitOptions
+ sliceOptions
+ ];
+ };
+
+ stage1SliceOptions = {
+ imports = [
+ stage1CommonUnitOptions
+ sliceOptions
+ ];
};
}
diff --git a/nixos/modules/system/boot/systemd/initrd.nix b/nixos/modules/system/boot/systemd/initrd.nix
index 0e73e02066d4..cfe539f76ddc 100644
--- a/nixos/modules/system/boot/systemd/initrd.nix
+++ b/nixos/modules/system/boot/systemd/initrd.nix
@@ -231,7 +231,7 @@ in {
targets = mkOption {
default = {};
visible = false;
- type = systemdUtils.types.targets;
+ type = systemdUtils.types.initrdTargets;
description = "Definition of systemd target units.";
};
@@ -244,28 +244,28 @@ in {
sockets = mkOption {
default = {};
- type = systemdUtils.types.sockets;
+ type = systemdUtils.types.initrdSockets;
visible = false;
description = "Definition of systemd socket units.";
};
timers = mkOption {
default = {};
- type = systemdUtils.types.timers;
+ type = systemdUtils.types.initrdTimers;
visible = false;
description = "Definition of systemd timer units.";
};
paths = mkOption {
default = {};
- type = systemdUtils.types.paths;
+ type = systemdUtils.types.initrdPaths;
visible = false;
description = "Definition of systemd path units.";
};
mounts = mkOption {
default = [];
- type = systemdUtils.types.mounts;
+ type = systemdUtils.types.initrdMounts;
visible = false;
description = ''
Definition of systemd mount units.