@@ -11,6 +11,22 @@ let
1111
1212 systemd = cfg.package;
1313
14+ inherit (systemdUtils.lib)
15+ makeJobScript
16+ unitConfig
17+ serviceConfig
18+ mountConfig
19+ automountConfig
20+ commonUnitText
21+ targetToUnit
22+ serviceToUnit
23+ socketToUnit
24+ timerToUnit
25+ pathToUnit
26+ mountToUnit
27+ automountToUnit
28+ sliceToUnit;
29+
1430 upstreamSystemUnits =
1531 [ # Targets.
1632 "basic.target"
@@ -209,207 +225,6 @@ let
209225 "xdg-desktop-autostart.target"
210226 ];
211227
212− makeJobScript = name: text:
213− let
214− scriptName = replaceChars [ "\\" "@" ] [ "-" "_" ] (shellEscape name);
215− out = (pkgs.writeShellScriptBin scriptName ''
216− set -e
217− ${text}
218− '').overrideAttrs (_: {
219− # The derivation name is different from the script file name
220− # to keep the script file name short to avoid cluttering logs.
221− name = "unit-script-${scriptName}";
222− });
223− in "${out}/bin/${scriptName}";
224−
225− unitConfig = { config, options, ... }: {
226− config = {
227− unitConfig =
228− optionalAttrs (config.requires != [])
229− { Requires = toString config.requires; }
230− // optionalAttrs (config.wants != [])
231− { Wants = toString config.wants; }
232− // optionalAttrs (config.after != [])
233− { After = toString config.after; }
234− // optionalAttrs (config.before != [])
235− { Before = toString config.before; }
236− // optionalAttrs (config.bindsTo != [])
237− { BindsTo = toString config.bindsTo; }
238− // optionalAttrs (config.partOf != [])
239− { PartOf = toString config.partOf; }
240− // optionalAttrs (config.conflicts != [])
241− { Conflicts = toString config.conflicts; }
242− // optionalAttrs (config.requisite != [])
243− { Requisite = toString config.requisite; }
244− // optionalAttrs (config.restartTriggers != [])
245− { X-Restart-Triggers = toString config.restartTriggers; }
246− // optionalAttrs (config.reloadTriggers != [])
247− { X-Reload-Triggers = toString config.reloadTriggers; }
248− // optionalAttrs (config.description != "") {
249− Description = config.description; }
250− // optionalAttrs (config.documentation != []) {
251− Documentation = toString config.documentation; }
252− // optionalAttrs (config.onFailure != []) {
253− OnFailure = toString config.onFailure; }
254− // optionalAttrs (options.startLimitIntervalSec.isDefined) {
255− StartLimitIntervalSec = toString config.startLimitIntervalSec;
256− } // optionalAttrs (options.startLimitBurst.isDefined) {
257− StartLimitBurst = toString config.startLimitBurst;
258− };
259− };
260− };
261−
262− serviceConfig = { name, config, ... }: {
263− config = mkMerge
264− [ { # Default path for systemd services. Should be quite minimal.
265− path = mkAfter
266− [ pkgs.coreutils
267− pkgs.findutils
268− pkgs.gnugrep
269− pkgs.gnused
270− systemd
271− ];
272− environment.PATH = "${makeBinPath config.path}:${makeSearchPathOutput "bin" "sbin" config.path}";
273− }
274− (mkIf (config.preStart != "")
275− { serviceConfig.ExecStartPre =
276− [ (makeJobScript "${name}-pre-start" config.preStart) ];
277− })
278− (mkIf (config.script != "")
279− { serviceConfig.ExecStart =
280− makeJobScript "${name}-start" config.script + " " + config.scriptArgs;
281− })
282− (mkIf (config.postStart != "")
283− { serviceConfig.ExecStartPost =
284− [ (makeJobScript "${name}-post-start" config.postStart) ];
285− })
286− (mkIf (config.reload != "")
287− { serviceConfig.ExecReload =
288− makeJobScript "${name}-reload" config.reload;
289− })
290− (mkIf (config.preStop != "")
291− { serviceConfig.ExecStop =
292− makeJobScript "${name}-pre-stop" config.preStop;
293− })
294− (mkIf (config.postStop != "")
295− { serviceConfig.ExecStopPost =
296− makeJobScript "${name}-post-stop" config.postStop;
297− })
298− ];
299− };
300−
301− mountConfig = { config, ... }: {
302− config = {
303− mountConfig =
304− { What = config.what;
305− Where = config.where;
306− } // optionalAttrs (config.type != "") {
307− Type = config.type;
308− } // optionalAttrs (config.options != "") {
309− Options = config.options;
310− };
311− };
312− };
313−
314− automountConfig = { config, ... }: {
315− config = {
316− automountConfig =
317− { Where = config.where;
318− };
319− };
320− };
321−
322− commonUnitText = def: ''
323− [Unit]
324− ${attrsToSection def.unitConfig}
325− '';
326−
327− targetToUnit = name: def:
328− { inherit (def) aliases wantedBy requiredBy enable;
329− text =
330− ''
331− [Unit]
332− ${attrsToSection def.unitConfig}
333− '';
334− };
335−
336− serviceToUnit = name: def:
337− { inherit (def) aliases wantedBy requiredBy enable;
338− text = commonUnitText def +
339− ''
340− [Service]
341− ${let env = cfg.globalEnvironment // def.environment;
342− in concatMapStrings (n:
343− let s = optionalString (env.${n} != null)
344− "Environment=${builtins.toJSON "${n}=${env.${n}}"}\n";
345− # systemd max line length is now 1MiB
346− # https://github.com/systemd/systemd/commit/e6dde451a51dc5aaa7f4d98d39b8fe735f73d2af
347− 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)}
348− ${if def.reloadIfChanged then ''
349− X-ReloadIfChanged=true
350− '' else if !def.restartIfChanged then ''
351− X-RestartIfChanged=false
352− '' else ""}
353− ${optionalString (!def.stopIfChanged) "X-StopIfChanged=false"}
354− ${attrsToSection def.serviceConfig}
355− '';
356− };
357−
358− socketToUnit = name: def:
359− { inherit (def) aliases wantedBy requiredBy enable;
360− text = commonUnitText def +
361− ''
362− [Socket]
363− ${attrsToSection def.socketConfig}
364− ${concatStringsSep "\n" (map (s: "ListenStream=${s}") def.listenStreams)}
365− ${concatStringsSep "\n" (map (s: "ListenDatagram=${s}") def.listenDatagrams)}
366− '';
367− };
368−
369− timerToUnit = name: def:
370− { inherit (def) aliases wantedBy requiredBy enable;
371− text = commonUnitText def +
372− ''
373− [Timer]
374− ${attrsToSection def.timerConfig}
375− '';
376− };
377−
378− pathToUnit = name: def:
379− { inherit (def) aliases wantedBy requiredBy enable;
380− text = commonUnitText def +
381− ''
382− [Path]
383− ${attrsToSection def.pathConfig}
384− '';
385− };
386−
387− mountToUnit = name: def:
388− { inherit (def) aliases wantedBy requiredBy enable;
389− text = commonUnitText def +
390− ''
391− [Mount]
392− ${attrsToSection def.mountConfig}
393− '';
394− };
395−
396− automountToUnit = name: def:
397− { inherit (def) aliases wantedBy requiredBy enable;
398− text = commonUnitText def +
399− ''
400− [Automount]
401− ${attrsToSection def.automountConfig}
402− '';
403− };
404−
405− sliceToUnit = name: def:
406− { inherit (def) aliases wantedBy requiredBy enable;
407− text = commonUnitText def +
408− ''
409− [Slice]
410− ${attrsToSection def.sliceConfig}
411− '';
412− };
413228
414229 logindHandlerType = types.enum [
415230 "ignore" "poweroff" "reboot" "halt" "kexec" "suspend"