2011-01-09 23:00:41 +01:00
|
|
|
{ config, pkgs, ... }:
|
2008-11-18 19:00:09 +01:00
|
|
|
|
2009-07-15 17:24:11 +02:00
|
|
|
with pkgs.lib;
|
2008-12-07 13:27:46 +01:00
|
|
|
|
2009-07-15 17:24:11 +02:00
|
|
|
let
|
2009-07-15 13:38:17 +02:00
|
|
|
|
2010-02-15 16:55:54 +01:00
|
|
|
upstart = pkgs.upstart;
|
2009-11-06 10:36:35 +01:00
|
|
|
|
2012-03-04 13:58:06 +01: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 10:36:35 +01:00
|
|
|
|
2012-07-19 23:41:42 +02:00
|
|
|
makeJobScript = name: content: "${pkgs.writeScriptBin name content}/bin/${name}";
|
|
|
|
|
2012-06-16 06:19:43 +02:00
|
|
|
# From a job description, generate an systemd unit file.
|
|
|
|
makeUnit = job:
|
2009-07-15 17:24:11 +02:00
|
|
|
|
|
|
|
let
|
2010-06-11 23:44:06 +02:00
|
|
|
hasMain = job.script != "" || job.exec != "";
|
2009-07-15 17:24:11 +02:00
|
|
|
|
2011-01-09 23:00:41 +01:00
|
|
|
env = config.system.upstartEnvironment // job.environment;
|
|
|
|
|
2012-07-19 23:41:42 +02:00
|
|
|
preStartScript = makeJobScript "${job.name}-pre-start.sh"
|
2009-07-15 17:24:11 +02:00
|
|
|
''
|
2012-06-16 06:19:43 +02:00
|
|
|
#! ${pkgs.stdenv.shell} -e
|
|
|
|
${job.preStart}
|
|
|
|
'';
|
|
|
|
|
2012-07-19 23:41:42 +02:00
|
|
|
startScript = makeJobScript "${job.name}-start.sh"
|
2012-06-16 06:19:43 +02:00
|
|
|
''
|
|
|
|
#! ${pkgs.stdenv.shell} -e
|
|
|
|
${if job.script != "" then job.script else ''
|
|
|
|
exec ${job.exec}
|
|
|
|
''}
|
|
|
|
'';
|
|
|
|
|
2012-07-19 23:41:42 +02:00
|
|
|
postStartScript = makeJobScript "${job.name}-post-start.sh"
|
2012-06-16 06:19:43 +02:00
|
|
|
''
|
|
|
|
#! ${pkgs.stdenv.shell} -e
|
|
|
|
${job.postStart}
|
|
|
|
'';
|
|
|
|
|
2012-07-19 23:41:42 +02:00
|
|
|
preStopScript = makeJobScript "${job.name}-pre-stop.sh"
|
2012-06-16 06:19:43 +02:00
|
|
|
''
|
|
|
|
#! ${pkgs.stdenv.shell} -e
|
|
|
|
${job.preStop}
|
|
|
|
'';
|
|
|
|
|
2012-07-19 23:41:42 +02:00
|
|
|
postStopScript = makeJobScript "${job.name}-post-stop.sh"
|
2012-06-16 06:19:43 +02:00
|
|
|
''
|
|
|
|
#! ${pkgs.stdenv.shell} -e
|
|
|
|
${job.postStop}
|
|
|
|
'';
|
2012-06-18 05:31:21 +02:00
|
|
|
in {
|
2012-06-16 06:19:43 +02:00
|
|
|
|
2012-06-18 23:42:26 +02:00
|
|
|
inherit (job) description path environment;
|
|
|
|
|
|
|
|
after =
|
|
|
|
if job.startOn == "stopped udevtrigger" then [ "systemd-udev-settle.service" ] else
|
|
|
|
if job.startOn == "started udev" then [ "systemd-udev.service" ] else
|
|
|
|
[];
|
2012-06-16 06:19:43 +02:00
|
|
|
|
2012-06-18 23:42:26 +02:00
|
|
|
wantedBy = if job.startOn == "" then [ ] else [ "multi-user.target" ];
|
2011-09-14 20:20:50 +02:00
|
|
|
|
2012-06-18 23:42:26 +02:00
|
|
|
serviceConfig =
|
|
|
|
''
|
2012-06-16 06:19:43 +02:00
|
|
|
${optionalString (job.preStart != "" && (job.script != "" || job.exec != "")) ''
|
|
|
|
ExecStartPre=${preStartScript}
|
|
|
|
''}
|
|
|
|
|
|
|
|
${optionalString (job.preStart != "" && job.script == "" && job.exec == "") ''
|
|
|
|
ExecStart=${preStartScript}
|
|
|
|
''}
|
|
|
|
|
|
|
|
${optionalString (job.script != "" || job.exec != "") ''
|
|
|
|
ExecStart=${startScript}
|
|
|
|
''}
|
|
|
|
|
|
|
|
${optionalString (job.postStart != "") ''
|
|
|
|
ExecStartPost=${postStartScript}
|
|
|
|
''}
|
|
|
|
|
|
|
|
${optionalString (job.preStop != "") ''
|
|
|
|
ExecStop=${preStopScript}
|
|
|
|
''}
|
|
|
|
|
|
|
|
${optionalString (job.postStop != "") ''
|
|
|
|
ExecStopPost=${postStopScript}
|
|
|
|
''}
|
|
|
|
|
|
|
|
${if job.script == "" && job.exec == "" then "Type=oneshot\nRemainAfterExit=true" else
|
|
|
|
if job.daemonType == "fork" then "Type=forking\nGuessMainPID=true" else
|
|
|
|
if job.daemonType == "none" then "" else
|
|
|
|
throw "invalid daemon type `${job.daemonType}'"}
|
|
|
|
|
|
|
|
${optionalString (!job.task && job.respawn) "Restart=always"}
|
|
|
|
'';
|
2012-06-18 05:31:21 +02:00
|
|
|
};
|
|
|
|
|
2012-03-17 20:12:33 +01:00
|
|
|
|
2009-10-06 11:30:13 +02:00
|
|
|
jobOptions = {
|
2009-07-15 15:41:00 +02:00
|
|
|
|
2009-11-06 10:26:36 +01:00
|
|
|
name = mkOption {
|
|
|
|
# !!! The type should ensure that this could be a filename.
|
|
|
|
type = types.string;
|
|
|
|
example = "sshd";
|
|
|
|
description = ''
|
|
|
|
Name of the Upstart job.
|
|
|
|
'';
|
|
|
|
};
|
2009-09-04 17:27:52 +02:00
|
|
|
|
2009-11-06 10:26:36 +01:00
|
|
|
description = mkOption {
|
|
|
|
type = types.string;
|
2012-03-04 17:17:56 +01:00
|
|
|
default = "";
|
2009-11-06 10:26:36 +01:00
|
|
|
description = ''
|
|
|
|
A short description of this job.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
|
|
|
startOn = mkOption {
|
|
|
|
# !!! Re-enable this once we're on Upstart >= 0.6.
|
2011-09-14 20:20:50 +02:00
|
|
|
#type = types.string;
|
2009-11-06 10:26:36 +01:00
|
|
|
default = "";
|
|
|
|
description = ''
|
|
|
|
The Upstart event that triggers this job to be started.
|
|
|
|
If empty, the job will not start automatically.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
|
|
|
stopOn = mkOption {
|
|
|
|
type = types.string;
|
2010-06-02 18:04:08 +02:00
|
|
|
default = "starting shutdown";
|
2009-11-06 10:26:36 +01:00
|
|
|
description = ''
|
|
|
|
The Upstart event that triggers this job to be stopped.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
|
|
|
preStart = mkOption {
|
|
|
|
type = types.string;
|
|
|
|
default = "";
|
|
|
|
description = ''
|
|
|
|
Shell commands executed before the job is started
|
|
|
|
(i.e. before the job's main process is started).
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
2009-11-06 16:23:16 +01:00
|
|
|
postStart = mkOption {
|
|
|
|
type = types.string;
|
|
|
|
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 23:45:19 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
preStop = mkOption {
|
|
|
|
type = types.string;
|
|
|
|
default = "";
|
|
|
|
description = ''
|
|
|
|
Shell commands executed before the job is stopped
|
|
|
|
(i.e. before Upstart kills the job's main process). This can
|
|
|
|
be used to cleanly shut down a daemon.
|
|
|
|
'';
|
2009-11-06 16:23:16 +01:00
|
|
|
};
|
|
|
|
|
2009-11-06 10:26:36 +01:00
|
|
|
postStop = mkOption {
|
|
|
|
type = types.string;
|
|
|
|
default = "";
|
|
|
|
description = ''
|
|
|
|
Shell commands executed after the job has stopped
|
|
|
|
(i.e. after the job's main process has terminated).
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
|
|
|
exec = mkOption {
|
|
|
|
type = types.string;
|
|
|
|
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 16:23:16 +01:00
|
|
|
and pre/post-stop scripts, and is considered “running”
|
2009-11-06 10:26:36 +01:00
|
|
|
until it is stopped.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
|
|
|
script = mkOption {
|
|
|
|
type = types.string;
|
|
|
|
default = "";
|
|
|
|
description = ''
|
|
|
|
Shell commands executed as the job's main process. Can be
|
|
|
|
specified instead of the <varname>exec</varname> attribute.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
|
|
|
respawn = mkOption {
|
|
|
|
type = types.bool;
|
|
|
|
default = true;
|
|
|
|
description = ''
|
|
|
|
Whether to restart the job automatically if its process
|
|
|
|
ends unexpectedly.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
2012-03-18 03:10:39 +01:00
|
|
|
restartIfChanged = mkOption {
|
|
|
|
type = types.bool;
|
|
|
|
default = true;
|
|
|
|
description = ''
|
|
|
|
Whether the job should be restarted if it has changed after a
|
|
|
|
NixOS configuration switch.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
2009-11-06 10:26:36 +01:00
|
|
|
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.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
|
|
|
environment = mkOption {
|
|
|
|
type = types.attrs;
|
|
|
|
default = {};
|
|
|
|
example = { PATH = "/foo/bar/bin"; LANG = "nl_NL.UTF-8"; };
|
|
|
|
description = ''
|
|
|
|
Environment variables passed to the job's processes.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
2009-11-06 16:23:16 +01:00
|
|
|
daemonType = mkOption {
|
|
|
|
type = types.string;
|
|
|
|
default = "none";
|
|
|
|
description = ''
|
|
|
|
Determines how Upstart 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.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
2012-03-04 13:58:06 +01:00
|
|
|
setuid = mkOption {
|
|
|
|
type = types.string;
|
|
|
|
check = userExists;
|
|
|
|
default = "";
|
|
|
|
description = ''
|
|
|
|
Run the daemon as a different user.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
|
|
|
setgid = mkOption {
|
|
|
|
type = types.string;
|
|
|
|
check = groupExists;
|
|
|
|
default = "";
|
|
|
|
description = ''
|
|
|
|
Run the daemon as a different group.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
2009-11-06 10:26:36 +01:00
|
|
|
extraConfig = mkOption {
|
|
|
|
type = types.string;
|
|
|
|
default = "";
|
|
|
|
example = "limit nofile 4096 4096";
|
|
|
|
description = ''
|
|
|
|
Additional Upstart stanzas not otherwise supported.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
2010-09-14 13:22:17 +02:00
|
|
|
path = mkOption {
|
2012-06-18 23:42:26 +02:00
|
|
|
default = [];
|
2010-09-14 13:22:17 +02:00
|
|
|
description = ''
|
|
|
|
Packages added to the job's <envar>PATH</envar> environment variable.
|
2011-09-14 20:20:50 +02:00
|
|
|
Both the <filename>bin</filename> and <filename>sbin</filename>
|
2010-09-14 13:22:17 +02:00
|
|
|
subdirectories of each package are added.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
2012-03-18 18:48:19 +01:00
|
|
|
console = mkOption {
|
|
|
|
default = "";
|
|
|
|
example = "console";
|
|
|
|
description = ''
|
|
|
|
If set to <literal>output</literal>, job output is written to
|
|
|
|
the console. If it's <literal>owner</literal>, additionally
|
|
|
|
the job becomes owner of the console. It it's empty (the
|
|
|
|
default), output is written to
|
|
|
|
<filename>/var/log/upstart/<replaceable>jobname</replaceable></filename>
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
2009-11-06 10:26:36 +01:00
|
|
|
};
|
2009-10-05 20:31:27 +02:00
|
|
|
|
2011-09-14 20:20:50 +02:00
|
|
|
|
2009-10-06 11:30:13 +02:00
|
|
|
upstartJob = {name, config, ...}: {
|
2011-09-14 20:20:50 +02:00
|
|
|
|
2009-10-06 11:30:13 +02:00
|
|
|
options = {
|
2012-02-20 20:23:15 +01:00
|
|
|
|
2012-06-18 05:31:21 +02:00
|
|
|
unit = mkOption {
|
2012-06-16 06:19:43 +02:00
|
|
|
default = makeUnit config;
|
2012-06-18 05:31:21 +02:00
|
|
|
description = "Generated definition of the systemd unit corresponding to this job.";
|
2009-10-06 11:30:13 +02:00
|
|
|
};
|
2012-02-20 20:23:15 +01:00
|
|
|
|
2009-10-06 11:30:13 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
config = {
|
2012-02-20 20:23:15 +01:00
|
|
|
|
2009-10-06 11:30:13 +02:00
|
|
|
# The default name is the name extracted from the attribute path.
|
2012-03-19 19:07:28 +01:00
|
|
|
name = mkDefaultValue name;
|
2012-02-20 20:23:15 +01:00
|
|
|
|
|
|
|
# Default path for Upstart jobs. Should be quite minimal.
|
|
|
|
path =
|
|
|
|
[ pkgs.coreutils
|
|
|
|
pkgs.findutils
|
|
|
|
pkgs.gnugrep
|
|
|
|
pkgs.gnused
|
|
|
|
upstart
|
|
|
|
];
|
|
|
|
|
2009-10-06 11:30:13 +02:00
|
|
|
};
|
2011-09-14 20:20:50 +02:00
|
|
|
|
2009-10-06 11:30:13 +02:00
|
|
|
};
|
2009-10-05 20:31:27 +02:00
|
|
|
|
|
|
|
in
|
2011-09-14 20:20:50 +02:00
|
|
|
|
2009-10-05 20:31:27 +02:00
|
|
|
{
|
|
|
|
|
|
|
|
###### interface
|
2011-09-14 20:20:50 +02:00
|
|
|
|
2009-10-05 20:31:27 +02:00
|
|
|
options = {
|
|
|
|
|
2009-10-12 20:09:34 +02:00
|
|
|
jobs = mkOption {
|
2009-10-05 20:31:27 +02:00
|
|
|
default = {};
|
|
|
|
description = ''
|
|
|
|
This option defines the system jobs started and managed by the
|
|
|
|
Upstart daemon.
|
|
|
|
'';
|
2011-07-27 22:55:35 +02:00
|
|
|
type = types.loaOf types.optionSet;
|
2009-10-06 11:30:13 +02:00
|
|
|
options = [ jobOptions upstartJob ];
|
2009-10-05 20:31:27 +02:00
|
|
|
};
|
2011-09-14 20:20:50 +02:00
|
|
|
|
2011-01-09 23:00:41 +01:00
|
|
|
system.upstartEnvironment = mkOption {
|
|
|
|
type = types.attrs;
|
|
|
|
default = {};
|
|
|
|
example = { TZ = "CET"; };
|
|
|
|
description = ''
|
|
|
|
Environment variables passed to <emphasis>all</emphasis> Upstart jobs.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
2008-11-18 19:00:09 +01:00
|
|
|
};
|
|
|
|
|
2009-07-15 11:06:36 +02:00
|
|
|
|
|
|
|
###### implementation
|
2011-09-14 20:20:50 +02:00
|
|
|
|
2009-07-15 11:06:36 +02:00
|
|
|
config = {
|
|
|
|
|
2009-11-06 10:36:35 +01:00
|
|
|
system.build.upstart = upstart;
|
|
|
|
|
2012-06-18 23:42:26 +02:00
|
|
|
boot.systemd.services =
|
2012-06-16 06:19:43 +02:00
|
|
|
flip mapAttrs' config.jobs (name: job:
|
2012-06-18 05:31:21 +02:00
|
|
|
nameValuePair "${job.name}.service" job.unit);
|
2012-06-16 06:19:43 +02:00
|
|
|
|
2008-11-18 19:00:09 +01:00
|
|
|
};
|
2009-07-15 11:06:36 +02:00
|
|
|
|
2009-01-02 17:07:21 +01:00
|
|
|
}
|