2014-04-14 14:26:48 +00:00
|
|
|
|
{ config, lib, pkgs, ... }:
|
2008-11-18 18:00:09 +00:00
|
|
|
|
|
2014-04-14 14:26:48 +00:00
|
|
|
|
with lib;
|
|
|
|
|
with import ../boot/systemd-unit-options.nix { inherit config lib; };
|
2008-12-07 12:27:46 +00:00
|
|
|
|
|
2009-07-15 15:24:11 +00:00
|
|
|
|
let
|
2009-07-15 11:38:17 +00:00
|
|
|
|
|
2012-03-04 12:58:06 +00:00
|
|
|
|
userExists = u:
|
|
|
|
|
(u == "") || any (uu: uu.name == u) (attrValues config.users.extraUsers);
|
|
|
|
|
|
|
|
|
|
groupExists = g:
|
|
|
|
|
(g == "") || any (gg: gg.name == g) (attrValues config.users.extraGroups);
|
2009-11-06 09:36:35 +00:00
|
|
|
|
|
2012-07-19 21:41:42 +00:00
|
|
|
|
makeJobScript = name: content: "${pkgs.writeScriptBin name content}/bin/${name}";
|
|
|
|
|
|
2012-06-16 04:19:43 +00:00
|
|
|
|
# From a job description, generate an systemd unit file.
|
|
|
|
|
makeUnit = job:
|
2009-07-15 15:24:11 +00:00
|
|
|
|
|
|
|
|
|
let
|
2010-06-11 21:44:06 +00:00
|
|
|
|
hasMain = job.script != "" || job.exec != "";
|
2009-07-15 15:24:11 +00:00
|
|
|
|
|
2012-10-30 16:27:14 +00:00
|
|
|
|
env = job.environment;
|
2011-01-09 22:00:41 +00:00
|
|
|
|
|
2012-10-15 20:01:30 +00:00
|
|
|
|
preStartScript = makeJobScript "${job.name}-pre-start"
|
2009-07-15 15:24:11 +00:00
|
|
|
|
''
|
2012-06-16 04:19:43 +00:00
|
|
|
|
#! ${pkgs.stdenv.shell} -e
|
|
|
|
|
${job.preStart}
|
|
|
|
|
'';
|
|
|
|
|
|
2012-10-15 20:01:30 +00:00
|
|
|
|
startScript = makeJobScript "${job.name}-start"
|
2012-06-16 04:19:43 +00:00
|
|
|
|
''
|
|
|
|
|
#! ${pkgs.stdenv.shell} -e
|
|
|
|
|
${if job.script != "" then job.script else ''
|
|
|
|
|
exec ${job.exec}
|
|
|
|
|
''}
|
|
|
|
|
'';
|
|
|
|
|
|
2012-10-15 20:01:30 +00:00
|
|
|
|
postStartScript = makeJobScript "${job.name}-post-start"
|
2012-06-16 04:19:43 +00:00
|
|
|
|
''
|
|
|
|
|
#! ${pkgs.stdenv.shell} -e
|
|
|
|
|
${job.postStart}
|
|
|
|
|
'';
|
|
|
|
|
|
2012-10-15 20:01:30 +00:00
|
|
|
|
preStopScript = makeJobScript "${job.name}-pre-stop"
|
2012-06-16 04:19:43 +00:00
|
|
|
|
''
|
|
|
|
|
#! ${pkgs.stdenv.shell} -e
|
|
|
|
|
${job.preStop}
|
|
|
|
|
'';
|
|
|
|
|
|
2012-10-15 20:01:30 +00:00
|
|
|
|
postStopScript = makeJobScript "${job.name}-post-stop"
|
2012-06-16 04:19:43 +00:00
|
|
|
|
''
|
|
|
|
|
#! ${pkgs.stdenv.shell} -e
|
|
|
|
|
${job.postStop}
|
|
|
|
|
'';
|
2012-06-18 03:31:21 +00:00
|
|
|
|
in {
|
2012-06-16 04:19:43 +00:00
|
|
|
|
|
2012-10-02 14:32:29 +00:00
|
|
|
|
inherit (job) description requires before partOf environment path restartIfChanged unitConfig;
|
2012-06-18 21:42:26 +00:00
|
|
|
|
|
|
|
|
|
after =
|
2012-08-06 16:26:52 +00:00
|
|
|
|
(if job.startOn == "stopped udevtrigger" then [ "systemd-udev-settle.service" ] else
|
|
|
|
|
if job.startOn == "started udev" then [ "systemd-udev.service" ] else
|
2012-10-11 20:18:48 +00:00
|
|
|
|
if job.startOn == "started network-interfaces" then [ "network-interfaces.target" ] else
|
2012-08-20 15:21:11 +00:00
|
|
|
|
if job.startOn == "started networking" then [ "network.target" ] else
|
2012-08-15 19:36:54 +00:00
|
|
|
|
if job.startOn == "ip-up" then [] else
|
|
|
|
|
if job.startOn == "" || job.startOn == "startup" then [] else
|
2012-08-14 21:30:11 +00:00
|
|
|
|
builtins.trace "Warning: job ‘${job.name}’ has unknown startOn value ‘${job.startOn}’." []
|
|
|
|
|
) ++ job.after;
|
2012-06-16 04:19:43 +00:00
|
|
|
|
|
2012-10-02 14:32:29 +00:00
|
|
|
|
wants =
|
2012-10-02 14:26:55 +00:00
|
|
|
|
(if job.startOn == "stopped udevtrigger" then [ "systemd-udev-settle.service" ] else []
|
2012-10-02 14:32:29 +00:00
|
|
|
|
) ++ job.wants;
|
2012-10-02 14:26:55 +00:00
|
|
|
|
|
2012-08-06 16:26:52 +00:00
|
|
|
|
wantedBy =
|
2012-08-15 19:36:54 +00:00
|
|
|
|
(if job.startOn == "" then [] else
|
|
|
|
|
if job.startOn == "ip-up" then [ "ip-up.target" ] else
|
|
|
|
|
[ "multi-user.target" ]) ++ job.wantedBy;
|
2011-09-14 18:20:50 +00:00
|
|
|
|
|
2012-06-18 21:42:26 +00:00
|
|
|
|
serviceConfig =
|
2012-10-01 20:27:42 +00:00
|
|
|
|
job.serviceConfig
|
|
|
|
|
// optionalAttrs (job.preStart != "" && (job.script != "" || job.exec != ""))
|
|
|
|
|
{ ExecStartPre = preStartScript; }
|
2012-10-01 22:20:22 +00:00
|
|
|
|
// optionalAttrs (job.preStart != "" && job.script == "" && job.exec == "")
|
|
|
|
|
{ ExecStart = preStartScript; }
|
2012-10-01 20:27:42 +00:00
|
|
|
|
// 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
|
2012-10-26 14:21:01 +00:00
|
|
|
|
if job.daemonType == "fork" || job.daemonType == "daemon" then { Type = "forking"; GuessMainPID = true; } else
|
2012-10-01 20:27:42 +00:00
|
|
|
|
if job.daemonType == "none" then { } else
|
|
|
|
|
throw "invalid daemon type `${job.daemonType}'")
|
2014-04-10 15:16:30 +00:00
|
|
|
|
// optionalAttrs (!job.task && !(job.script == "" && job.exec == "") && job.respawn)
|
2012-10-23 12:30:50 +00:00
|
|
|
|
{ Restart = "always"; }
|
|
|
|
|
// optionalAttrs job.task
|
|
|
|
|
{ Type = "oneshot"; RemainAfterExit = false; };
|
2012-06-18 03:31:21 +00:00
|
|
|
|
};
|
|
|
|
|
|
2012-03-17 19:12:33 +00:00
|
|
|
|
|
2012-08-06 15:45:59 +00:00
|
|
|
|
jobOptions = serviceOptions // {
|
2009-07-15 13:41:00 +00:00
|
|
|
|
|
2009-11-06 09:26:36 +00:00
|
|
|
|
name = mkOption {
|
|
|
|
|
# !!! The type should ensure that this could be a filename.
|
2013-10-30 14:33:20 +00:00
|
|
|
|
type = types.str;
|
2009-11-06 09:26:36 +00:00
|
|
|
|
example = "sshd";
|
|
|
|
|
description = ''
|
2013-10-31 12:26:06 +00:00
|
|
|
|
Name of the job, mapped to the systemd unit
|
|
|
|
|
<literal><replaceable>name</replaceable>.service</literal>.
|
2009-11-06 09:26:36 +00:00
|
|
|
|
'';
|
|
|
|
|
};
|
2009-09-04 15:27:52 +00:00
|
|
|
|
|
2009-11-06 09:26:36 +00:00
|
|
|
|
startOn = mkOption {
|
2013-10-30 14:33:20 +00:00
|
|
|
|
#type = types.str;
|
2009-11-06 09:26:36 +00:00
|
|
|
|
default = "";
|
|
|
|
|
description = ''
|
2013-10-31 12:26:06 +00:00
|
|
|
|
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.
|
2009-11-06 09:26:36 +00:00
|
|
|
|
'';
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
stopOn = mkOption {
|
2013-10-30 14:33:20 +00:00
|
|
|
|
type = types.str;
|
2010-06-02 16:04:08 +00:00
|
|
|
|
default = "starting shutdown";
|
2009-11-06 09:26:36 +00:00
|
|
|
|
description = ''
|
2013-10-31 12:26:06 +00:00
|
|
|
|
Ignored; this was the Upstart event that triggers this job to be stopped.
|
2009-11-06 09:26:36 +00:00
|
|
|
|
'';
|
|
|
|
|
};
|
|
|
|
|
|
2009-11-06 15:23:16 +00:00
|
|
|
|
postStart = mkOption {
|
2013-10-30 14:33:20 +00:00
|
|
|
|
type = types.lines;
|
2009-11-06 15:23:16 +00:00
|
|
|
|
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”.
|
|
|
|
|
'';
|
2009-11-06 22:45:19 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
preStop = mkOption {
|
2013-10-30 14:33:20 +00:00
|
|
|
|
type = types.lines;
|
2009-11-06 22:45:19 +00:00
|
|
|
|
default = "";
|
|
|
|
|
description = ''
|
|
|
|
|
Shell commands executed before the job is stopped
|
2013-10-31 12:26:06 +00:00
|
|
|
|
(i.e. before systemd kills the job's main process). This can
|
2009-11-06 22:45:19 +00:00
|
|
|
|
be used to cleanly shut down a daemon.
|
|
|
|
|
'';
|
2009-11-06 15:23:16 +00:00
|
|
|
|
};
|
|
|
|
|
|
2009-11-06 09:26:36 +00:00
|
|
|
|
postStop = mkOption {
|
2013-10-30 14:33:20 +00:00
|
|
|
|
type = types.lines;
|
2009-11-06 09:26:36 +00:00
|
|
|
|
default = "";
|
|
|
|
|
description = ''
|
|
|
|
|
Shell commands executed after the job has stopped
|
|
|
|
|
(i.e. after the job's main process has terminated).
|
|
|
|
|
'';
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
exec = mkOption {
|
2013-10-30 14:33:20 +00:00
|
|
|
|
type = types.str;
|
2009-11-06 09:26:36 +00:00
|
|
|
|
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
|
2009-11-06 15:23:16 +00:00
|
|
|
|
and pre/post-stop scripts, and is considered “running”
|
2009-11-06 09:26:36 +00:00
|
|
|
|
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.
|
|
|
|
|
'';
|
|
|
|
|
};
|
|
|
|
|
|
2009-11-06 15:23:16 +00:00
|
|
|
|
daemonType = mkOption {
|
2013-10-30 14:33:20 +00:00
|
|
|
|
type = types.str;
|
2009-11-06 15:23:16 +00:00
|
|
|
|
default = "none";
|
|
|
|
|
description = ''
|
2013-10-31 12:26:06 +00:00
|
|
|
|
Determines how systemd detects when a daemon should be
|
2009-11-06 15:23:16 +00:00
|
|
|
|
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.
|
|
|
|
|
'';
|
|
|
|
|
};
|
|
|
|
|
|
2012-03-04 12:58:06 +00:00
|
|
|
|
setuid = mkOption {
|
2013-10-30 14:33:20 +00:00
|
|
|
|
type = types.addCheck types.str userExists;
|
2012-03-04 12:58:06 +00:00
|
|
|
|
default = "";
|
|
|
|
|
description = ''
|
|
|
|
|
Run the daemon as a different user.
|
|
|
|
|
'';
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
setgid = mkOption {
|
2013-10-30 14:33:20 +00:00
|
|
|
|
type = types.addCheck types.str groupExists;
|
2012-03-04 12:58:06 +00:00
|
|
|
|
default = "";
|
|
|
|
|
description = ''
|
|
|
|
|
Run the daemon as a different group.
|
|
|
|
|
'';
|
|
|
|
|
};
|
|
|
|
|
|
2010-09-14 11:22:17 +00:00
|
|
|
|
path = mkOption {
|
2012-06-18 21:42:26 +00:00
|
|
|
|
default = [];
|
2010-09-14 11:22:17 +00:00
|
|
|
|
description = ''
|
|
|
|
|
Packages added to the job's <envar>PATH</envar> environment variable.
|
2011-09-14 18:20:50 +00:00
|
|
|
|
Both the <filename>bin</filename> and <filename>sbin</filename>
|
2010-09-14 11:22:17 +00:00
|
|
|
|
subdirectories of each package are added.
|
|
|
|
|
'';
|
|
|
|
|
};
|
|
|
|
|
|
2009-11-06 09:26:36 +00:00
|
|
|
|
};
|
2009-10-05 18:31:27 +00:00
|
|
|
|
|
2011-09-14 18:20:50 +00:00
|
|
|
|
|
2012-08-06 15:45:59 +00:00
|
|
|
|
upstartJob = { name, config, ... }: {
|
2011-09-14 18:20:50 +00:00
|
|
|
|
|
2009-10-06 09:30:13 +00:00
|
|
|
|
options = {
|
2012-08-06 15:45:59 +00:00
|
|
|
|
|
2012-06-18 03:31:21 +00:00
|
|
|
|
unit = mkOption {
|
2012-06-16 04:19:43 +00:00
|
|
|
|
default = makeUnit config;
|
2012-06-18 03:31:21 +00:00
|
|
|
|
description = "Generated definition of the systemd unit corresponding to this job.";
|
2009-10-06 09:30:13 +00:00
|
|
|
|
};
|
2012-08-06 15:45:59 +00:00
|
|
|
|
|
2009-10-06 09:30:13 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
config = {
|
2012-08-06 15:45:59 +00:00
|
|
|
|
|
2009-10-06 09:30:13 +00:00
|
|
|
|
# The default name is the name extracted from the attribute path.
|
2013-10-27 23:07:27 +00:00
|
|
|
|
name = mkDefault name;
|
2012-08-06 15:45:59 +00:00
|
|
|
|
|
2009-10-06 09:30:13 +00:00
|
|
|
|
};
|
2011-09-14 18:20:50 +00:00
|
|
|
|
|
2009-10-06 09:30:13 +00:00
|
|
|
|
};
|
2009-10-05 18:31:27 +00:00
|
|
|
|
|
|
|
|
|
in
|
2011-09-14 18:20:50 +00:00
|
|
|
|
|
2009-10-05 18:31:27 +00:00
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
###### interface
|
2011-09-14 18:20:50 +00:00
|
|
|
|
|
2009-10-05 18:31:27 +00:00
|
|
|
|
options = {
|
|
|
|
|
|
2009-10-12 18:09:34 +00:00
|
|
|
|
jobs = mkOption {
|
2009-10-05 18:31:27 +00:00
|
|
|
|
default = {};
|
|
|
|
|
description = ''
|
2013-10-31 12:26:06 +00:00
|
|
|
|
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.
|
2009-10-05 18:31:27 +00:00
|
|
|
|
'';
|
2011-07-27 20:55:35 +00:00
|
|
|
|
type = types.loaOf types.optionSet;
|
2009-10-06 09:30:13 +00:00
|
|
|
|
options = [ jobOptions upstartJob ];
|
2009-10-05 18:31:27 +00:00
|
|
|
|
};
|
2011-09-14 18:20:50 +00:00
|
|
|
|
|
2008-11-18 18:00:09 +00:00
|
|
|
|
};
|
|
|
|
|
|
2009-07-15 09:06:36 +00:00
|
|
|
|
|
|
|
|
|
###### implementation
|
2011-09-14 18:20:50 +00:00
|
|
|
|
|
2009-07-15 09:06:36 +00:00
|
|
|
|
config = {
|
|
|
|
|
|
2013-01-16 11:33:18 +00:00
|
|
|
|
systemd.services =
|
2012-06-16 04:19:43 +00:00
|
|
|
|
flip mapAttrs' config.jobs (name: job:
|
2012-08-23 14:25:27 +00:00
|
|
|
|
nameValuePair job.name job.unit);
|
2012-08-06 15:45:59 +00:00
|
|
|
|
|
2008-11-18 18:00:09 +00:00
|
|
|
|
};
|
2009-07-15 09:06:36 +00:00
|
|
|
|
|
2009-01-02 16:07:21 +00:00
|
|
|
|
}
|