parent
af50b03f50
commit
88292fdf09
@ -1,290 +0,0 @@ |
||||
{ config, lib, pkgs, ... }: |
||||
|
||||
with lib; |
||||
with import ../boot/systemd-unit-options.nix { inherit config lib; }; |
||||
|
||||
let |
||||
|
||||
userExists = u: |
||||
(u == "") || any (uu: uu.name == u) (attrValues config.users.extraUsers); |
||||
|
||||
groupExists = g: |
||||
(g == "") || any (gg: gg.name == g) (attrValues config.users.extraGroups); |
||||
|
||||
makeJobScript = name: content: "${pkgs.writeScriptBin name content}/bin/${name}"; |
||||
|
||||
# From a job description, generate an systemd unit file. |
||||
makeUnit = job: |
||||
|
||||
let |
||||
hasMain = job.script != "" || job.exec != ""; |
||||
|
||||
env = job.environment; |
||||
|
||||
preStartScript = makeJobScript "${job.name}-pre-start" |
||||
'' |
||||
#! ${pkgs.stdenv.shell} -e |
||||
${job.preStart} |
||||
''; |
||||
|
||||
startScript = makeJobScript "${job.name}-start" |
||||
'' |
||||
#! ${pkgs.stdenv.shell} -e |
||||
${if job.script != "" then job.script else '' |
||||
exec ${job.exec} |
||||
''} |
||||
''; |
||||
|
||||
postStartScript = makeJobScript "${job.name}-post-start" |
||||
'' |
||||
#! ${pkgs.stdenv.shell} -e |
||||
${job.postStart} |
||||
''; |
||||
|
||||
preStopScript = makeJobScript "${job.name}-pre-stop" |
||||
'' |
||||
#! ${pkgs.stdenv.shell} -e |
||||
${job.preStop} |
||||
''; |
||||
|
||||
postStopScript = makeJobScript "${job.name}-post-stop" |
||||
'' |
||||
#! ${pkgs.stdenv.shell} -e |
||||
${job.postStop} |
||||
''; |
||||
in { |
||||
|
||||
inherit (job) description requires before partOf environment path restartIfChanged unitConfig; |
||||
|
||||
after = |
||||
(if job.startOn == "stopped udevtrigger" then [ "systemd-udev-settle.service" ] else |
||||
if job.startOn == "started udev" then [ "systemd-udev.service" ] else |
||||
if job.startOn == "started network-interfaces" then [ "network-interfaces.target" ] else |
||||
if job.startOn == "started networking" then [ "network.target" ] else |
||||
if job.startOn == "ip-up" then [] else |
||||
if job.startOn == "" || job.startOn == "startup" then [] else |
||||
builtins.trace "Warning: job ‘${job.name}’ has unknown startOn value ‘${job.startOn}’." [] |
||||
) ++ job.after; |
||||
|
||||
wants = |
||||
(if job.startOn == "stopped udevtrigger" then [ "systemd-udev-settle.service" ] else [] |
||||
) ++ job.wants; |
||||
|
||||
wantedBy = |
||||
(if job.startOn == "" then [] else |
||||
if job.startOn == "ip-up" then [ "ip-up.target" ] else |
||||
[ "multi-user.target" ]) ++ job.wantedBy; |
||||
|
||||
serviceConfig = |
||||
job.serviceConfig |
||||
// optionalAttrs (job.preStart != "" && (job.script != "" || job.exec != "")) |
||||
{ ExecStartPre = preStartScript; } |
||||
// optionalAttrs (job.preStart != "" && job.script == "" && job.exec == "") |
||||
{ ExecStart = preStartScript; } |
||||
// optionalAttrs (job.script != "" || job.exec != "") |
||||
{ ExecStart = startScript; } |
||||
// optionalAttrs (job.postStart != "") |
||||
{ ExecStartPost = postStartScript; } |
||||
// optionalAttrs (job.preStop != "") |
||||
{ ExecStop = preStopScript; } |
||||
// optionalAttrs (job.postStop != "") |
||||
{ ExecStopPost = postStopScript; } |
||||
// (if job.script == "" && job.exec == "" then { Type = "oneshot"; RemainAfterExit = true; } else |
||||
if job.daemonType == "fork" || job.daemonType == "daemon" then { Type = "forking"; GuessMainPID = true; } else |
||||
if job.daemonType == "none" then { } else |
||||
throw "invalid daemon type `${job.daemonType}'") |
||||
// optionalAttrs (!job.task && !(job.script == "" && job.exec == "") && job.respawn) |
||||
{ Restart = "always"; } |
||||
// optionalAttrs job.task |
||||
{ Type = "oneshot"; RemainAfterExit = false; }; |
||||
}; |
||||
|
||||
|
||||
jobOptions = serviceOptions // { |
||||
|
||||
name = mkOption { |
||||
# !!! The type should ensure that this could be a filename. |
||||
type = types.str; |
||||
example = "sshd"; |
||||
description = '' |
||||
Name of the job, mapped to the systemd unit |
||||
<literal><replaceable>name</replaceable>.service</literal>. |
||||
''; |
||||
}; |
||||
|
||||
startOn = mkOption { |
||||
#type = types.str; |
||||
default = ""; |
||||
description = '' |
||||
The Upstart event that triggers this job to be started. Some |
||||
are mapped to systemd dependencies; otherwise you will get a |
||||
warning. If empty, the job will not start automatically. |
||||
''; |
||||
}; |
||||
|
||||
stopOn = mkOption { |
||||
type = types.str; |
||||
default = "starting shutdown"; |
||||
description = '' |
||||
Ignored; this was the Upstart event that triggers this job to be stopped. |
||||
''; |
||||
}; |
||||
|
||||
postStart = mkOption { |
||||
type = types.lines; |
||||
default = ""; |
||||
description = '' |
||||
Shell commands executed after the job is started (i.e. after |
||||
the job's main process is started), but before the job is |
||||
considered “running”. |
||||
''; |
||||
}; |
||||
|
||||
preStop = mkOption { |
||||
type = types.lines; |
||||
default = ""; |
||||
description = '' |
||||
Shell commands executed before the job is stopped |
||||
(i.e. before systemd kills the job's main process). This can |
||||
be used to cleanly shut down a daemon. |
||||
''; |
||||
}; |
||||
|
||||
postStop = mkOption { |
||||
type = types.lines; |
||||
default = ""; |
||||
description = '' |
||||
Shell commands executed after the job has stopped |
||||
(i.e. after the job's main process has terminated). |
||||
''; |
||||
}; |
||||
|
||||
exec = mkOption { |
||||
type = types.str; |
||||
default = ""; |
||||
description = '' |
||||
Command to start the job's main process. If empty, the |
||||
job has no main process, but can still have pre/post-start |
||||
and pre/post-stop scripts, and is considered “running” |
||||
until it is stopped. |
||||
''; |
||||
}; |
||||
|
||||
respawn = mkOption { |
||||
type = types.bool; |
||||
default = true; |
||||
description = '' |
||||
Whether to restart the job automatically if its process |
||||
ends unexpectedly. |
||||
''; |
||||
}; |
||||
|
||||
task = mkOption { |
||||
type = types.bool; |
||||
default = false; |
||||
description = '' |
||||
Whether this job is a task rather than a service. Tasks |
||||
are executed only once, while services are restarted when |
||||
they exit. |
||||
''; |
||||
}; |
||||
|
||||
daemonType = mkOption { |
||||
type = types.str; |
||||
default = "none"; |
||||
description = '' |
||||
Determines how systemd detects when a daemon should be |
||||
considered “running”. The value <literal>none</literal> means |
||||
that the daemon is considered ready immediately. The value |
||||
<literal>fork</literal> means that the daemon will fork once. |
||||
The value <literal>daemon</literal> means that the daemon will |
||||
fork twice. The value <literal>stop</literal> means that the |
||||
daemon will raise the SIGSTOP signal to indicate readiness. |
||||
''; |
||||
}; |
||||
|
||||
setuid = mkOption { |
||||
type = types.addCheck types.str userExists; |
||||
default = ""; |
||||
description = '' |
||||
Run the daemon as a different user. |
||||
''; |
||||
}; |
||||
|
||||
setgid = mkOption { |
||||
type = types.addCheck types.str groupExists; |
||||
default = ""; |
||||
description = '' |
||||
Run the daemon as a different group. |
||||
''; |
||||
}; |
||||
|
||||
path = mkOption { |
||||
default = []; |
||||
description = '' |
||||
Packages added to the job's <envar>PATH</envar> environment variable. |
||||
Both the <filename>bin</filename> and <filename>sbin</filename> |
||||
subdirectories of each package are added. |
||||
''; |
||||
}; |
||||
|
||||
}; |
||||
|
||||
|
||||
upstartJob = { name, config, ... }: { |
||||
|
||||
options = { |
||||
|
||||
unit = mkOption { |
||||
default = makeUnit config; |
||||
description = "Generated definition of the systemd unit corresponding to this job."; |
||||
}; |
||||
|
||||
}; |
||||
|
||||
config = { |
||||
|
||||
# The default name is the name extracted from the attribute path. |
||||
name = mkDefault name; |
||||
|
||||
}; |
||||
|
||||
}; |
||||
|
||||
in |
||||
|
||||
{ |
||||
|
||||
###### interface |
||||
|
||||
options = { |
||||
|
||||
jobs = mkOption { |
||||
default = {}; |
||||
description = '' |
||||
This option is a legacy method to define system services, |
||||
dating from the era where NixOS used Upstart instead of |
||||
systemd. You should use <option>systemd.services</option> |
||||
instead. Services defined using <option>jobs</option> are |
||||
mapped automatically to <option>systemd.services</option>, but |
||||
may not work perfectly; in particular, most |
||||
<option>startOn</option> conditions are not supported. |
||||
''; |
||||
type = types.loaOf types.optionSet; |
||||
options = [ jobOptions upstartJob ]; |
||||
}; |
||||
|
||||
}; |
||||
|
||||
|
||||
###### implementation |
||||
|
||||
config = { |
||||
|
||||
systemd.services = |
||||
flip mapAttrs' config.jobs (name: job: |
||||
nameValuePair job.name job.unit); |
||||
|
||||
}; |
||||
|
||||
} |
Loading…
Reference in new issue