Add 'nix-services/' from commit 'bbc5bf5bcf4466c7acd3ef978ae77daa8cae9bac'

git-subtree-dir: nix-services
git-subtree-mainline: 6f91df3199
git-subtree-split: bbc5bf5bcf
This commit is contained in:
Jaka Hudoklin 2014-03-14 16:43:29 +00:00
commit 237e857126
5 changed files with 282 additions and 0 deletions

75
nix-services/default.nix Normal file
View File

@ -0,0 +1,75 @@
{ pkgs ? import <nixpkgs> { system = "x86_64-linux"; }
, name
, configuration ? [<configuration>]
, baseImage ? "busybox"
}:
with pkgs.lib;
let
moduleList = [
./user.nix ./supervisord.nix ./systemd.nix ./environment.nix
<nixpkgs/nixos/modules/config/users-groups.nix>
<nixpkgs/nixos/modules/misc/ids.nix>
<nixpkgs/nixos/modules/misc/assertions.nix>
<nixpkgs/nixos/modules/services/databases/redis.nix>
<nixpkgs/nixos/modules/services/databases/mysql.nix>
<nixpkgs/nixos/modules/services/databases/postgresql.nix>
<nixpkgs/nixos/modules/services/search/elasticsearch.nix>
<nixpkgs/nixos/modules/services/monitoring/graphite.nix>
<nixpkgs/nixos/modules/services/monitoring/statsd.nix>
<nixpkgs/nixos/modules/services/amqp/rabbitmq.nix>
<nixpkgs/nixos/modules/services/databases/couchdb.nix>
];
config = (evalModules {
modules = configuration ++ moduleList;
args = { inherit pkgs; };
}).config;
systemd = import ./systemd.nix { inherit pkgs config; };
startServices = pkgs.writeScript "startServices" ''
#!/bin/sh
export STATEDIR="${"\$"}{STATEDIR-$(pwd)/var}"
export PATH="${pkgs.coreutils}/bin"
mkdir -p $STATEDIR/{run,log}
# Run start scripts first
${config.userNix.startScript}
# Run supervisord
${pkgs.pythonPackages.supervisor}/bin/supervisord -c ${config.supervisord.configFile} -j $STATEDIR/run/supervisord.pid -d $STATEDIR -q $STATEDIR/log/ -l $STATEDIR/log/supervisord.log
'';
stopServices = pkgs.writeScript "stopServices" ''
#!/bin/sh
${pkgs.pythonPackages.supervisor}/bin/supervisorctl -c ${config.supervisord.configFile} shutdown
'';
controlServices = pkgs.writeScript "controlServices" ''
#!/bin/sh
${pkgs.pythonPackages.supervisor}/bin/supervisorctl -c ${config.supervisord.configFile}
'';
servicesControl = pkgs.stdenv.mkDerivation {
name = "${name}-servicesControl";
src = ./.;
phases = [ "installPhase" ];
installPhase = ''
ensureDir $out/bin/
ln -s ${startServices} $out/bin/${name}-start-services
ln -s ${stopServices} $out/bin/${name}-stop-services
ln -s ${controlServices} $out/bin/${name}-control-services
'';
passthru.config = config;
};
in pkgs.buildEnv {
name = "${name}-services";
paths = [ servicesControl ] ++ config.environment.systemPackages;
}

View File

@ -0,0 +1,23 @@
{ config, pkgs, ... }:
with pkgs.lib;
{
options = {
environment.systemPackages = mkOption {
default = [];
description = "Packages to be put in the system profile.";
};
environment.umask = mkOption {
default = "002";
type = with types; string;
};
# HACK HACK
system.activationScripts.etc = mkOption {}; # Ignore
system.build.etc = mkOption {}; # Ignore
};
config = {
environment.systemPackages = with pkgs; [ coreutils ];
};
}

View File

@ -0,0 +1,102 @@
{ config, pkgs, ... }:
with pkgs.lib;
let
serviceOpts = { name, config, ...}: {
options = {
command = mkOption {
description = "The command to execute";
};
directory = mkOption {
default = "/";
description = "Current directory when running the command";
};
environment = mkOption {
default = {};
example = {
PATH = "/some/path";
};
};
path = mkOption {
default = [];
description = "Current directory when running the command";
};
stopsignal = mkOption {
default = "TERM";
};
startsecs = mkOption {
default = 1;
example = 0;
};
pidfile = mkOption {
default = null;
};
};
};
services = config.supervisord.services;
in {
options = {
supervisord = {
enable = mkOption {
default = true;
type = types.bool;
};
services = mkOption {
default = {};
type = types.loaOf types.optionSet;
description = ''
Supervisord services to start
'';
options = [ serviceOpts ];
};
tailLogs = mkOption {
default = false;
type = types.bool;
description = ''
Whether or not to tail all logs to standard out.
'';
};
configFile = mkOption {};
};
};
config = mkIf config.supervisord.enable {
supervisord.configFile = pkgs.writeText "supervisord.conf" ''
[supervisord]
[supervisorctl]
serverurl = http://localhost:64125
[inet_http_server]
port = 127.0.0.1:64125
[rpcinterface:supervisor]
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface
${concatMapStrings (name:
let
cfg = getAttr name services;
in
''
[program:${name}]
command=${if cfg.pidfile == null then cfg.command else "${pkgs.pythonPackages.supervisor}/bin/pidproxy ${cfg.pidfile} ${cfg.command}"}
environment=${concatStrings
(mapAttrsToList (name: value: "${name}=\"${value}\",") (
cfg.environment // { PATH = concatStringsSep ":"
[("%(ENV_PATH)s") (cfg.path) (maybeAttr "PATH" "" cfg.environment)];
}
)
)}
directory=${cfg.directory}
redirect_stderr=true
startsecs=${toString cfg.startsecs}
stopsignal=${cfg.stopsignal}
stopasgroup=true
''
) (attrNames services)
}
'';
};
}

65
nix-services/systemd.nix Normal file
View File

@ -0,0 +1,65 @@
{ pkgs, config, ... }:
with pkgs.lib;
with import <nixpkgs/nixos/modules/system/boot/systemd-unit-options.nix> { inherit config pkgs; };
let
services = config.systemd.services;
isOneShot = cfg: hasAttr "Type" cfg.serviceConfig && cfg.serviceConfig.Type == "oneshot";
runServices = filterAttrs (name: cfg: !(isOneShot cfg)) services;
oneShotServices = filterAttrs (name: cfg: isOneShot cfg) services;
filterCommand = cmd:
let
filtered = substring 1 (stringLength cmd -2) cmd;
splitted = pkgs.lib.splitString (" " + substring 0 0 filtered) filtered;
in if eqStrings (substring 0 1 cmd) "@" then
traceVal (head splitted) + concatStringsSep " " (drop 2 splitted)
else cmd;
configToCommand = name: cfg: ''
#!/bin/sh -e
${if hasAttr "preStart" cfg then cfg.preStart else ""}
${if hasAttr "ExecStart" cfg.serviceConfig then
filterCommand cfg.serviceConfig.ExecStart
else if hasAttr "script" cfg then
cfg.script
else
""
}
${if hasAttr "postStart" cfg then cfg.postStart else ""}
'';
in {
options = {
systemd.services = mkOption {
default = {};
type = types.attrsOf types.optionSet;
options = [ serviceOptions ];
}; # TODO make more specific
};
config = {
userNix.startScripts."1-systemd-oneshot" = concatMapStrings (name: "${configToCommand name (getAttr name oneShotServices)}\n") (attrNames oneShotServices);
supervisord.services = listToAttrs (map (name:
let
cfg = getAttr name services;
in
{
name = name;
value = {
command = pkgs.writeScript "${name}-run" (configToCommand name cfg);
environment = cfg.environment;
path = cfg.path;
stopsignal = if hasAttr "KillSignal" cfg.serviceConfig then
substring 3 (stringLength cfg.serviceConfig.KillSignal) cfg.serviceConfig.KillSignal
else "TERM";
pidfile = if hasAttr "PIDFile" cfg.serviceConfig then cfg.serviceConfig.PIDFile else null;
};
}
) (attrNames (filterAttrs (n: v: v.enable) runServices)));
};
}

17
nix-services/user.nix Normal file
View File

@ -0,0 +1,17 @@
{ config, pkgs, ... }:
with pkgs.lib;
{
options = {
userNix.startScripts = mkOption {
default = {};
description = "Scripts (as text) to be run during build, executed alphabetically";
};
userNix.startScript = mkOption {};
};
config = {
userNix.startScript = concatStrings (attrValues config.userNix.startScripts);
};
}