diff --git a/nixos/lib/systemd-unit-options.nix b/nixos/lib/systemd-unit-options.nix
index c9d424d39119..02e91fdf1e62 100644
--- a/nixos/lib/systemd-unit-options.nix
+++ b/nixos/lib/systemd-unit-options.nix
@@ -94,131 +94,133 @@ in rec {
};
- commonUnitOptions = { options = (sharedOptions // {
+ commonUnitOptions = {
+ options = sharedOptions // {
+
+ description = mkOption {
+ default = "";
+ type = types.singleLineStr;
+ description = "Description of this unit used in systemd messages and progress indicators.";
+ };
+
+ documentation = mkOption {
+ default = [];
+ type = types.listOf types.str;
+ description = "A list of URIs referencing documentation for this unit or its configuration.";
+ };
+
+ requires = mkOption {
+ default = [];
+ type = types.listOf unitNameType;
+ description = ''
+ Start the specified units when this unit is started, and stop
+ this unit when the specified units are stopped or fail.
+ '';
+ };
+
+ wants = mkOption {
+ default = [];
+ type = types.listOf unitNameType;
+ description = ''
+ Start the specified units when this unit is started.
+ '';
+ };
+
+ after = mkOption {
+ default = [];
+ type = types.listOf unitNameType;
+ description = ''
+ If the specified units are started at the same time as
+ this unit, delay this unit until they have started.
+ '';
+ };
+
+ before = mkOption {
+ default = [];
+ type = types.listOf unitNameType;
+ description = ''
+ If the specified units are started at the same time as
+ this unit, delay them until this unit has started.
+ '';
+ };
+
+ bindsTo = mkOption {
+ default = [];
+ type = types.listOf unitNameType;
+ description = ''
+ Like ‘requires’, but in addition, if the specified units
+ unexpectedly disappear, this unit will be stopped as well.
+ '';
+ };
+
+ partOf = mkOption {
+ default = [];
+ type = types.listOf unitNameType;
+ description = ''
+ If the specified units are stopped or restarted, then this
+ unit is stopped or restarted as well.
+ '';
+ };
+
+ conflicts = mkOption {
+ default = [];
+ type = types.listOf unitNameType;
+ description = ''
+ If the specified units are started, then this unit is stopped
+ and vice versa.
+ '';
+ };
+
+ requisite = mkOption {
+ default = [];
+ type = types.listOf unitNameType;
+ description = ''
+ Similar to requires. However if the units listed are not started,
+ they will not be started and the transaction will fail.
+ '';
+ };
+
+ unitConfig = mkOption {
+ default = {};
+ example = { RequiresMountsFor = "/data"; };
+ type = types.attrsOf unitOption;
+ description = ''
+ Each attribute in this set specifies an option in the
+ [Unit] section of the unit. See
+ systemd.unit
+ 5 for details.
+ '';
+ };
+
+ onFailure = mkOption {
+ default = [];
+ type = types.listOf unitNameType;
+ description = ''
+ A list of one or more units that are activated when
+ this unit enters the "failed" state.
+ '';
+ };
+
+ startLimitBurst = mkOption {
+ type = types.int;
+ description = ''
+ Configure unit start rate limiting. Units which are started
+ more than startLimitBurst times within an interval time
+ interval are not permitted to start any more.
+ '';
+ };
+
+ startLimitIntervalSec = mkOption {
+ type = types.int;
+ description = ''
+ Configure unit start rate limiting. Units which are started
+ more than startLimitBurst times within an interval time
+ interval are not permitted to start any more.
+ '';
+ };
- description = mkOption {
- default = "";
- type = types.singleLineStr;
- description = "Description of this unit used in systemd messages and progress indicators.";
};
-
- documentation = mkOption {
- default = [];
- type = types.listOf types.str;
- description = "A list of URIs referencing documentation for this unit or its configuration.";
- };
-
- requires = mkOption {
- default = [];
- type = types.listOf unitNameType;
- description = ''
- Start the specified units when this unit is started, and stop
- this unit when the specified units are stopped or fail.
- '';
- };
-
- wants = mkOption {
- default = [];
- type = types.listOf unitNameType;
- description = ''
- Start the specified units when this unit is started.
- '';
- };
-
- after = mkOption {
- default = [];
- type = types.listOf unitNameType;
- description = ''
- If the specified units are started at the same time as
- this unit, delay this unit until they have started.
- '';
- };
-
- before = mkOption {
- default = [];
- type = types.listOf unitNameType;
- description = ''
- If the specified units are started at the same time as
- this unit, delay them until this unit has started.
- '';
- };
-
- bindsTo = mkOption {
- default = [];
- type = types.listOf unitNameType;
- description = ''
- Like ‘requires’, but in addition, if the specified units
- unexpectedly disappear, this unit will be stopped as well.
- '';
- };
-
- partOf = mkOption {
- default = [];
- type = types.listOf unitNameType;
- description = ''
- If the specified units are stopped or restarted, then this
- unit is stopped or restarted as well.
- '';
- };
-
- conflicts = mkOption {
- default = [];
- type = types.listOf unitNameType;
- description = ''
- If the specified units are started, then this unit is stopped
- and vice versa.
- '';
- };
-
- requisite = mkOption {
- default = [];
- type = types.listOf unitNameType;
- description = ''
- Similar to requires. However if the units listed are not started,
- they will not be started and the transaction will fail.
- '';
- };
-
- unitConfig = mkOption {
- default = {};
- example = { RequiresMountsFor = "/data"; };
- type = types.attrsOf unitOption;
- description = ''
- Each attribute in this set specifies an option in the
- [Unit] section of the unit. See
- systemd.unit
- 5 for details.
- '';
- };
-
- onFailure = mkOption {
- default = [];
- type = types.listOf unitNameType;
- description = ''
- A list of one or more units that are activated when
- this unit enters the "failed" state.
- '';
- };
-
- startLimitBurst = mkOption {
- type = types.int;
- description = ''
- Configure unit start rate limiting. Units which are started
- more than startLimitBurst times within an interval time
- interval are not permitted to start any more.
- '';
- };
-
- startLimitIntervalSec = mkOption {
- type = types.int;
- description = ''
- Configure unit start rate limiting. Units which are started
- more than startLimitBurst times within an interval time
- interval are not permitted to start any more.
- '';
- };
-
- }); };
+ };
stage2CommonUnitOptions = {
imports = [
@@ -250,49 +252,41 @@ in rec {
};
stage1CommonUnitOptions = commonUnitOptions;
- serviceOptions = { options = {
-
- environment = mkOption {
- default = {};
- type = with types; attrsOf (nullOr (oneOf [ str path package ]));
- example = { PATH = "/foo/bar/bin"; LANG = "nl_NL.UTF-8"; };
- description = "Environment variables passed to the service's processes.";
- };
-
- path = mkOption {
- default = [];
- type = with types; listOf (oneOf [ package str ]);
- description = ''
- Packages added to the service's PATH
- environment variable. Both the bin
- and sbin subdirectories of each
- package are added.
- '';
- };
-
- serviceConfig = mkOption {
- default = {};
- example =
- { RestartSec = 5;
- };
- type = types.addCheck (types.attrsOf unitOption) checkService;
- description = ''
- Each attribute in this set specifies an option in the
- [Service] section of the unit. See
- systemd.service
- 5 for details.
- '';
- };
-
- }; };
-
- stage2ServiceOptions = { name, config, ... }: {
- imports = [
- stage2CommonUnitOptions
- serviceOptions
- ];
-
+ serviceOptions = { name, config, ... }: {
options = {
+
+ environment = mkOption {
+ default = {};
+ type = with types; attrsOf (nullOr (oneOf [ str path package ]));
+ example = { PATH = "/foo/bar/bin"; LANG = "nl_NL.UTF-8"; };
+ description = "Environment variables passed to the service's processes.";
+ };
+
+ path = mkOption {
+ default = [];
+ type = with types; listOf (oneOf [ package str ]);
+ description = ''
+ Packages added to the service's PATH
+ environment variable. Both the bin
+ and sbin subdirectories of each
+ package are added.
+ '';
+ };
+
+ serviceConfig = mkOption {
+ default = {};
+ example =
+ { RestartSec = 5;
+ };
+ type = types.addCheck (types.attrsOf unitOption) checkService;
+ description = ''
+ Each attribute in this set specifies an option in the
+ [Service] section of the unit. See
+ systemd.service
+ 5 for details.
+ '';
+ };
+
script = mkOption {
type = types.lines;
default = "";
@@ -349,6 +343,51 @@ in rec {
'';
};
+ jobScripts = mkOption {
+ type = with types; coercedTo path singleton (listOf path);
+ internal = true;
+ description = "A list of all job script derivations of this unit.";
+ default = [];
+ };
+
+ };
+
+ config = mkMerge [
+ (mkIf (config.preStart != "") rec {
+ jobScripts = makeJobScript "${name}-pre-start" config.preStart;
+ serviceConfig.ExecStartPre = [ jobScripts ];
+ })
+ (mkIf (config.script != "") rec {
+ jobScripts = makeJobScript "${name}-start" config.script;
+ serviceConfig.ExecStart = jobScripts + " " + config.scriptArgs;
+ })
+ (mkIf (config.postStart != "") rec {
+ jobScripts = (makeJobScript "${name}-post-start" config.postStart);
+ serviceConfig.ExecStartPost = [ jobScripts ];
+ })
+ (mkIf (config.reload != "") rec {
+ jobScripts = makeJobScript "${name}-reload" config.reload;
+ serviceConfig.ExecReload = jobScripts;
+ })
+ (mkIf (config.preStop != "") rec {
+ jobScripts = makeJobScript "${name}-pre-stop" config.preStop;
+ serviceConfig.ExecStop = jobScripts;
+ })
+ (mkIf (config.postStop != "") rec {
+ jobScripts = makeJobScript "${name}-post-stop" config.postStop;
+ serviceConfig.ExecStopPost = jobScripts;
+ })
+ ];
+
+ };
+
+ stage2ServiceOptions = {
+ imports = [
+ stage2CommonUnitOptions
+ serviceOptions
+ ];
+
+ options = {
restartIfChanged = mkOption {
type = types.bool;
default = true;
@@ -404,33 +443,6 @@ in rec {
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 = {
@@ -441,41 +453,43 @@ in rec {
};
- socketOptions = { options = {
+ socketOptions = {
+ options = {
- listenStreams = mkOption {
- default = [];
- type = types.listOf types.str;
- example = [ "0.0.0.0:993" "/run/my-socket" ];
- description = ''
- For each item in this list, a ListenStream
- option in the [Socket] section will be created.
- '';
+ listenStreams = mkOption {
+ default = [];
+ type = types.listOf types.str;
+ example = [ "0.0.0.0:993" "/run/my-socket" ];
+ description = ''
+ For each item in this list, a ListenStream
+ option in the [Socket] section will be created.
+ '';
+ };
+
+ listenDatagrams = mkOption {
+ default = [];
+ type = types.listOf types.str;
+ example = [ "0.0.0.0:993" "/run/my-socket" ];
+ description = ''
+ For each item in this list, a ListenDatagram
+ option in the [Socket] section will be created.
+ '';
+ };
+
+ socketConfig = mkOption {
+ default = {};
+ example = { ListenStream = "/run/my-socket"; };
+ type = types.attrsOf unitOption;
+ description = ''
+ Each attribute in this set specifies an option in the
+ [Socket] section of the unit. See
+ systemd.socket
+ 5 for details.
+ '';
+ };
};
- listenDatagrams = mkOption {
- default = [];
- type = types.listOf types.str;
- example = [ "0.0.0.0:993" "/run/my-socket" ];
- description = ''
- For each item in this list, a ListenDatagram
- option in the [Socket] section will be created.
- '';
- };
-
- socketConfig = mkOption {
- default = {};
- example = { ListenStream = "/run/my-socket"; };
- type = types.attrsOf unitOption;
- description = ''
- Each attribute in this set specifies an option in the
- [Socket] section of the unit. See
- systemd.socket
- 5 for details.
- '';
- };
-
- }; };
+ };
stage2SocketOptions = {
imports = [
@@ -492,23 +506,25 @@ in rec {
};
- timerOptions = { options = {
+ timerOptions = {
+ options = {
+
+ timerConfig = mkOption {
+ default = {};
+ example = { OnCalendar = "Sun 14:00:00"; Unit = "foo.service"; };
+ type = types.attrsOf unitOption;
+ description = ''
+ Each attribute in this set specifies an option in the
+ [Timer] section of the unit. See
+ systemd.timer
+ 5 and
+ systemd.time
+ 7 for details.
+ '';
+ };
- timerConfig = mkOption {
- default = {};
- example = { OnCalendar = "Sun 14:00:00"; Unit = "foo.service"; };
- type = types.attrsOf unitOption;
- description = ''
- Each attribute in this set specifies an option in the
- [Timer] section of the unit. See
- systemd.timer
- 5 and
- systemd.time
- 7 for details.
- '';
};
-
- }; };
+ };
stage2TimerOptions = {
imports = [
@@ -525,21 +541,23 @@ in rec {
};
- pathOptions = { options = {
+ pathOptions = {
+ options = {
+
+ pathConfig = mkOption {
+ default = {};
+ example = { PathChanged = "/some/path"; Unit = "changedpath.service"; };
+ type = types.attrsOf unitOption;
+ description = ''
+ Each attribute in this set specifies an option in the
+ [Path] section of the unit. See
+ systemd.path
+ 5 for details.
+ '';
+ };
- pathConfig = mkOption {
- default = {};
- example = { PathChanged = "/some/path"; Unit = "changedpath.service"; };
- type = types.attrsOf unitOption;
- description = ''
- Each attribute in this set specifies an option in the
- [Path] section of the unit. See
- systemd.path
- 5 for details.
- '';
};
-
- }; };
+ };
stage2PathOptions = {
imports = [
@@ -556,49 +574,52 @@ in rec {
};
- mountOptions = { options = {
+ mountOptions = {
+ options = {
- what = mkOption {
- example = "/dev/sda1";
- type = types.str;
- description = "Absolute path of device node, file or other resource. (Mandatory)";
- };
+ what = mkOption {
+ example = "/dev/sda1";
+ type = types.str;
+ description = "Absolute path of device node, file or other resource. (Mandatory)";
+ };
- where = mkOption {
- example = "/mnt";
- type = types.str;
- description = ''
- Absolute path of a directory of the mount point.
- Will be created if it doesn't exist. (Mandatory)
- '';
- };
+ where = mkOption {
+ example = "/mnt";
+ type = types.str;
+ description = ''
+ Absolute path of a directory of the mount point.
+ Will be created if it doesn't exist. (Mandatory)
+ '';
+ };
- type = mkOption {
- default = "";
- example = "ext4";
- type = types.str;
- description = "File system type.";
- };
+ type = mkOption {
+ default = "";
+ example = "ext4";
+ type = types.str;
+ description = "File system type.";
+ };
- options = mkOption {
- default = "";
- example = "noatime";
- type = types.commas;
- description = "Options used to mount the file system.";
- };
+ options = mkOption {
+ default = "";
+ example = "noatime";
+ type = types.commas;
+ description = "Options used to mount the file system.";
+ };
+
+ mountConfig = mkOption {
+ default = {};
+ example = { DirectoryMode = "0775"; };
+ type = types.attrsOf unitOption;
+ description = ''
+ Each attribute in this set specifies an option in the
+ [Mount] section of the unit. See
+ systemd.mount
+ 5 for details.
+ '';
+ };
- mountConfig = mkOption {
- default = {};
- example = { DirectoryMode = "0775"; };
- type = types.attrsOf unitOption;
- description = ''
- Each attribute in this set specifies an option in the
- [Mount] section of the unit. See
- systemd.mount
- 5 for details.
- '';
};
- }; };
+ };
stage2MountOptions = {
imports = [
@@ -614,29 +635,32 @@ in rec {
];
};
- automountOptions = { options = {
+ automountOptions = {
+ options = {
- where = mkOption {
- example = "/mnt";
- type = types.str;
- description = ''
- Absolute path of a directory of the mount point.
- Will be created if it doesn't exist. (Mandatory)
- '';
- };
+ where = mkOption {
+ example = "/mnt";
+ type = types.str;
+ description = ''
+ Absolute path of a directory of the mount point.
+ Will be created if it doesn't exist. (Mandatory)
+ '';
+ };
+
+ automountConfig = mkOption {
+ default = {};
+ example = { DirectoryMode = "0775"; };
+ type = types.attrsOf unitOption;
+ description = ''
+ Each attribute in this set specifies an option in the
+ [Automount] section of the unit. See
+ systemd.automount
+ 5 for details.
+ '';
+ };
- automountConfig = mkOption {
- default = {};
- example = { DirectoryMode = "0775"; };
- type = types.attrsOf unitOption;
- description = ''
- Each attribute in this set specifies an option in the
- [Automount] section of the unit. See
- systemd.automount
- 5 for details.
- '';
};
- }; };
+ };
stage2AutomountOptions = {
imports = [
@@ -652,21 +676,23 @@ in rec {
];
};
- sliceOptions = { options = {
+ sliceOptions = {
+ options = {
+
+ sliceConfig = mkOption {
+ default = {};
+ example = { MemoryMax = "2G"; };
+ type = types.attrsOf unitOption;
+ description = ''
+ Each attribute in this set specifies an option in the
+ [Slice] section of the unit. See
+ systemd.slice
+ 5 for details.
+ '';
+ };
- sliceConfig = mkOption {
- default = {};
- example = { MemoryMax = "2G"; };
- type = types.attrsOf unitOption;
- description = ''
- Each attribute in this set specifies an option in the
- [Slice] section of the unit. See
- systemd.slice
- 5 for details.
- '';
};
-
- }; };
+ };
stage2SliceOptions = {
imports = [
diff --git a/nixos/modules/system/boot/systemd/initrd.nix b/nixos/modules/system/boot/systemd/initrd.nix
index 30bdc9a3422c..36a14d7a8256 100644
--- a/nixos/modules/system/boot/systemd/initrd.nix
+++ b/nixos/modules/system/boot/systemd/initrd.nix
@@ -96,6 +96,7 @@ let
enabledUpstreamUnits = filter (n: ! elem n cfg.suppressedUnits) upstreamUnits;
enabledUnits = filterAttrs (n: v: ! elem n cfg.suppressedUnits) cfg.units;
+ jobScripts = concatLists (mapAttrsToList (_: unit: unit.jobScripts or []) (filterAttrs (_: v: v.enable) cfg.services));
stage1Units = generateUnits {
type = "initrd";
@@ -378,7 +379,7 @@ in {
# so NSS can look up usernames
"${pkgs.glibc}/lib/libnss_files.so"
- ];
+ ] ++ jobScripts;
targets.initrd.aliases = ["default.target"];
units =