* Converted modules that were still using the old (concrete syntax)

style of declaring Upstart jobs.  While at it, converted them to the
  current NixOS module style and improved some option descriptions.
  Hopefully I didn't break too much :-)

svn path=/nixos/trunk/; revision=17761
This commit is contained in:
Eelco Dolstra 2009-10-12 16:36:19 +00:00
parent 4a78ef25e7
commit e91d882a94
42 changed files with 3298 additions and 3520 deletions

View File

@ -1,89 +1,88 @@
{pkgs, config, ...}: { config, pkgs, ... }:
with pkgs.lib;
###### interface
let let
inherit (pkgs.lib) mkOption mkIf;
uid = config.ids.uids.pulseaudio; uid = config.ids.uids.pulseaudio;
gid = config.ids.gids.pulseaudio; gid = config.ids.gids.pulseaudio;
options = {
services = {
pulseaudio = {
enable = mkOption {
default = false;
description = ''
Whether to enable the PulseAudio system-wide audio server.
Note that the documentation recommends running PulseAudio
daemons per-user rather than system-wide on desktop machines.
'';
};
logLevel = mkOption {
default = "notice";
example = "debug";
description = ''
A string denoting the log level: one of
<literal>error</literal>, <literal>warn</literal>,
<literal>notice</literal>, <literal>info</literal>,
or <literal>debug</literal>.
'';
};
};
};
};
in in
###### implementation {
###### interface
mkIf config.services.pulseaudio.enable { options = {
require = [
options services.pulseaudio = {
];
enable = mkOption {
default = false;
description = ''
Whether to enable the PulseAudio system-wide audio server.
Note that the documentation recommends running PulseAudio
daemons per-user rather than system-wide on desktop machines.
'';
};
environment = { logLevel = mkOption {
systemPackages = [pkgs.pulseaudio]; default = "notice";
example = "debug";
description = ''
A string denoting the log level: one of
<literal>error</literal>, <literal>warn</literal>,
<literal>notice</literal>, <literal>info</literal>,
or <literal>debug</literal>.
'';
};
};
}; };
users = { ###### implementation
extraUsers = [
config = mkIf config.services.pulseaudio.enable {
environment.systemPackages = [ pkgs.pulseaudio ];
users.extraUsers = singleton
{ name = "pulse"; { name = "pulse";
# For some reason, PulseAudio wants UID == GID. # For some reason, PulseAudio wants UID == GID.
uid = assert uid == gid; uid; uid = assert uid == gid; uid;
group = "pulse"; group = "pulse";
description = "PulseAudio system-wide daemon"; description = "PulseAudio system-wide daemon";
home = "/var/run/pulse"; home = "/var/run/pulse";
} };
];
extraGroups = [ users.extraGroups = singleton
{ name = "pulse"; { name = "pulse";
inherit gid; inherit gid;
} };
];
}; jobAttrs.pulseaudio =
{ description = "PulseAudio system-wide server";
services = {
extraJobs = [{ startOn = "startup";
name = "pulseaudio"; stopOn = "shutdown";
job = '' preStart =
description "PulseAudio system-wide server" ''
test -d /var/run/pulse || \
start on startup ( mkdir -p --mode 755 /var/run/pulse && \
stop on shutdown chown pulse:pulse /var/run/pulse )
'';
start script
test -d /var/run/pulse || \ exec =
( mkdir -p --mode 755 /var/run/pulse && \ ''
chown pulse:pulse /var/run/pulse ) ${pkgs.pulseaudio}/bin/pulseaudio \
end script --system --daemonize \
--log-level="${config.services.pulseaudio.logLevel}"
respawn ${pkgs.pulseaudio}/bin/pulseaudio \ '';
--system --daemonize \ };
--log-level="${config.services.pulseaudio.logLevel}"
'';
}];
}; };
} }

View File

@ -1,8 +1,8 @@
{pkgs, config, ...}: { config, pkgs, ... }:
###### implementation ###### implementation
let let
inherit (pkgs.lib);
klogdCmd = "${pkgs.sysklogd}/sbin/klogd -c 1 -2 -k $(dirname $(readlink -f /var/run/booted-system/kernel))/System.map"; klogdCmd = "${pkgs.sysklogd}/sbin/klogd -c 1 -2 -k $(dirname $(readlink -f /var/run/booted-system/kernel))/System.map";
@ -10,24 +10,20 @@ in
{ {
services = { jobAttrs.klogd =
extraJobs = [{ { description = "Kernel log daemon";
name = "klogd";
job = ''
description "Kernel log daemon"
start on syslogd
stop on shutdown
start script startOn = "syslogd";
stopOn = "shutdown";
preStart =
''
# !!! this hangs for some reason (it blocks reading from # !!! this hangs for some reason (it blocks reading from
# /proc/kmsg). # /proc/kmsg).
#${klogdCmd} -o #${klogdCmd} -o
end script '';
respawn ${klogdCmd} -n exec = "${klogdCmd} -n";
''; };
}];
};
} }

View File

@ -1,8 +1,9 @@
{pkgs, config, ...}: { config, pkgs, ... }:
with pkgs.lib; with pkgs.lib;
let let
startingDependency = if config.services.gw6c.enable then "gw6c" else "network-interfaces"; startingDependency = if config.services.gw6c.enable then "gw6c" else "network-interfaces";
cfg = config.services.dovecot; cfg = config.services.dovecot;
@ -112,23 +113,18 @@ in
gid = config.ids.gids.dovecot; gid = config.ids.gids.dovecot;
}; };
services.extraJobs = singleton jobAttrs.dovecot =
{ name = "dovecot"; { description = "Dovecot IMAP/POP3 server";
job = startOn = "${startingDependency}/started";
preStart =
'' ''
description "Dovecot IMAP/POP3 server" ${pkgs.coreutils}/bin/mkdir -p /var/run/dovecot /var/run/dovecot/login
${pkgs.coreutils}/bin/chown -R ${cfg.user}.${cfg.group} /var/run/dovecot
start on ${startingDependency}/started
stop on never
start script
${pkgs.coreutils}/bin/mkdir -p /var/run/dovecot /var/run/dovecot/login
${pkgs.coreutils}/bin/chown -R ${cfg.user}.${cfg.group} /var/run/dovecot
end script
respawn ${pkgs.dovecot}/sbin/dovecot -F -c ${confFile}
''; '';
exec = "${pkgs.dovecot}/sbin/dovecot -F -c ${confFile}";
}; };
}; };

View File

@ -1,155 +1,9 @@
{pkgs, config, ...}: { config, pkgs, ... }:
###### interface with pkgs.lib;
let
inherit (pkgs.lib) mkOption mkIf;
options = {
services = {
postfix = {
enable = mkOption {
default = false;
description ="
Whether to run the Postfix mail server.
";
};
user = mkOption {
default = "postfix";
description = "
How to call postfix user (must be used only for postfix).
";
};
group = mkOption {
default = "postfix";
description = "
How to call postfix group (must be used only for postfix).
";
};
setgidGroup = mkOption {
default = "postdrop";
description = "
How to call postfix setgid group (for postdrop). Should
be uniquely used group.
";
};
networks = mkOption {
default = null;
example = ["192.168.0.1/24"];
description = "
Net masks for trusted - allowed to relay mail to third parties -
hosts. Leave empty to use mynetworks_style configuration or use
default (localhost-only).
";
};
networksStyle = mkOption {
default = "";
description = "
Name of standard way of trusted network specification to use,
leave blank if you specify it explicitly or if you want to use
default (localhost-only).
";
};
hostname = mkOption {
default = "";
description ="
Hostname to use. Leave blank to use just the hostname of machine.
It should be FQDN.
";
};
domain = mkOption {
default = "";
description ="
Domain to use. Leave blank to use hostname minus first component.
";
};
origin = mkOption {
default = "";
description ="
Origin to use in outgoing e-mail. Leave blank to use hostname.
";
};
destination = mkOption {
default = null;
example = ["localhost"];
description = "
Full (!) list of domains we deliver locally. Leave blank for
acceptable Postfix default.
";
};
relayDomains = mkOption {
default = null;
example = ["localdomain"];
description = "
List of domains we agree to relay to. Default is the same as
destination.
";
};
relayHost = mkOption {
default = "";
description = "
Mail relay for outbound mail.
";
};
lookupMX = mkOption {
default = false;
description = "
Whether relay specified is just domain whose MX must be used.
";
};
postmasterAlias = mkOption {
default = "root";
description = "
Who should receive postmaster e-mail.
";
};
rootAlias = mkOption {
default = "";
description = "
Who should receive root e-mail. Blank for no redirection.
";
};
extraAliases = mkOption {
default = "";
description = "
Additional entries to put verbatim into aliases file.
";
};
sslCert = mkOption {
default = "";
description = "
SSL certificate to use.
";
};
sslCACert = mkOption {
default = "";
description = "
SSL certificate of CA.
";
};
sslKey = mkOption {
default = "";
description ="
SSL key to use.
";
};
recipientDelimiter = mkOption {
default = "";
example = "+";
description = "
Delimiter for address extension: so mail to user+test can be handled by ~user/.forward+test
";
};
};
};
};
in
###### implementation
let let
startingDependency = if config.services.gw6c.enable then "gw6c" else "network-interfaces"; startingDependency = if config.services.gw6c.enable then "gw6c" else "network-interfaces";
cfg = config.services.postfix; cfg = config.services.postfix;
@ -157,94 +11,86 @@ let
group = cfg.group; group = cfg.group;
setgidGroup = cfg.setgidGroup; setgidGroup = cfg.setgidGroup;
optionalString = pkgs.lib.optionalString;
concatStringsSep = pkgs.lib.concatStringsSep;
mainCf = mainCf =
'' ''
queue_directory = /var/postfix/queue queue_directory = /var/postfix/queue
command_directory = ${pkgs.postfix}/sbin command_directory = ${pkgs.postfix}/sbin
daemon_directory = ${pkgs.postfix}/libexec/postfix daemon_directory = ${pkgs.postfix}/libexec/postfix
mail_owner = ${user} mail_owner = ${user}
default_privs = nobody default_privs = nobody
'' ''
+ optionalString (config.services.gw6c.enable || config.networking.nativeIPv6) ('' + optionalString (config.services.gw6c.enable || config.networking.nativeIPv6) (''
inet_protocols = all inet_protocols = all
'')
+
(if cfg.networks!=null then
(''
mynetworks = ${concatStringsSep ", " cfg.networks}
'')
else if (cfg.networksStyle != "") then
(''
mynetworks_style = ${cfg.networksStyle}
'') '')
else + (if cfg.networks != null then
# Postfix default is subnet, but let's play safe ''
('' mynetworks = ${concatStringsSep ", " cfg.networks}
mynetworks_style = host ''
'') else if cfg.networksStyle != "" then
) ''
+ optionalString (cfg.hostname != "") ('' mynetworks_style = ${cfg.networksStyle}
myhostname = ${cfg.hostname} ''
'') else
+ optionalString (cfg.domain != "") ('' # Postfix default is subnet, but let's play safe
mydomain = ${cfg.domain} ''
'') mynetworks_style = host
+ optionalString (cfg.origin != "") ('' '')
myorigin = ${cfg.origin} + optionalString (cfg.hostname != "") ''
'') myhostname = ${cfg.hostname}
+ optionalString (cfg.destination != null) ('' ''
mydestination = ${concatStringsSep ", " cfg.destination} + optionalString (cfg.domain != "") ''
'') mydomain = ${cfg.domain}
+ optionalString (cfg.relayDomains != null) ('' ''
relay_domains = ${concatStringsSep ", " cfg.relayDomains} + optionalString (cfg.origin != "") ''
'') myorigin = ${cfg.origin}
+ '' ''
local_recipient_maps = + optionalString (cfg.destination != null) ''
'' mydestination = ${concatStringsSep ", " cfg.destination}
+ ('' ''
relayhost = ${if cfg.lookupMX || cfg.relayHost == "" then + optionalString (cfg.relayDomains != null) ''
cfg.relayHost relay_domains = ${concatStringsSep ", " cfg.relayDomains}
else ''
"[" + cfg.relayHost + "]"} + ''
'') local_recipient_maps =
+ (''
alias_maps = hash:/var/postfix/conf/aliases relayhost = ${if cfg.lookupMX || cfg.relayHost == "" then
cfg.relayHost
else
"[" + cfg.relayHost + "]"}
alias_maps = hash:/var/postfix/conf/aliases
mail_spool_directory = /var/spool/mail/ mail_spool_directory = /var/spool/mail/
setgid_group = ${setgidGroup} setgid_group = ${setgidGroup}
'') ''
+ optionalString (cfg.sslCert != "") ('' + optionalString (cfg.sslCert != "") ''
smtp_tls_CAfile = ${cfg.sslCACert} smtp_tls_CAfile = ${cfg.sslCACert}
smtp_tls_cert_file = ${cfg.sslCert} smtp_tls_cert_file = ${cfg.sslCert}
smtp_tls_key_file = ${cfg.sslKey} smtp_tls_key_file = ${cfg.sslKey}
smtp_use_tls = yes smtp_use_tls = yes
smtpd_tls_CAfile = ${cfg.sslCACert} smtpd_tls_CAfile = ${cfg.sslCACert}
smtpd_tls_cert_file = ${cfg.sslCert} smtpd_tls_cert_file = ${cfg.sslCert}
smtpd_tls_key_file = ${cfg.sslKey} smtpd_tls_key_file = ${cfg.sslKey}
smtpd_use_tls = yes smtpd_use_tls = yes
recipientDelimiter = ${cfg.recipientDelimiter} recipientDelimiter = ${cfg.recipientDelimiter}
'') '';
;
aliases = aliases =
(optionalString (cfg.postmasterAlias != "") ('' optionalString (cfg.postmasterAlias != "") ''
postmaster: ${cfg.postmasterAlias} postmaster: ${cfg.postmasterAlias}
'')) ''
+ + optionalString (cfg.rootAlias != "") ''
(optionalString (cfg.rootAlias != "") (''
root: ${cfg.rootAlias} root: ${cfg.rootAlias}
'')) ''
+ cfg.extraAliases + cfg.extraAliases
; ;
@ -253,54 +99,194 @@ let
in in
mkIf config.services.postfix.enable { {
require = [
options ###### interface
];
options = {
services.postfix = {
enable = mkOption {
default = false;
description = "Whether to run the Postfix mail server.";
};
user = mkOption {
default = "postfix";
description = "What to call the Postfix user (must be used only for postfix).";
};
group = mkOption {
default = "postfix";
description = "What to call the Postfix group (must be used only for postfix).";
};
setgidGroup = mkOption {
default = "postdrop";
description = "
How to call postfix setgid group (for postdrop). Should
be uniquely used group.
";
};
networks = mkOption {
default = null;
example = ["192.168.0.1/24"];
description = "
Net masks for trusted - allowed to relay mail to third parties -
hosts. Leave empty to use mynetworks_style configuration or use
default (localhost-only).
";
};
networksStyle = mkOption {
default = "";
description = "
Name of standard way of trusted network specification to use,
leave blank if you specify it explicitly or if you want to use
default (localhost-only).
";
};
hostname = mkOption {
default = "";
description ="
Hostname to use. Leave blank to use just the hostname of machine.
It should be FQDN.
";
};
domain = mkOption {
default = "";
description ="
Domain to use. Leave blank to use hostname minus first component.
";
};
origin = mkOption {
default = "";
description ="
Origin to use in outgoing e-mail. Leave blank to use hostname.
";
};
destination = mkOption {
default = null;
example = ["localhost"];
description = "
Full (!) list of domains we deliver locally. Leave blank for
acceptable Postfix default.
";
};
relayDomains = mkOption {
default = null;
example = ["localdomain"];
description = "
List of domains we agree to relay to. Default is the same as
destination.
";
};
relayHost = mkOption {
default = "";
description = "
Mail relay for outbound mail.
";
};
lookupMX = mkOption {
default = false;
description = "
Whether relay specified is just domain whose MX must be used.
";
};
postmasterAlias = mkOption {
default = "root";
description = "Who should receive postmaster e-mail.";
};
rootAlias = mkOption {
default = "";
description = "
Who should receive root e-mail. Blank for no redirection.
";
};
extraAliases = mkOption {
default = "";
description = "
Additional entries to put verbatim into aliases file.
";
};
sslCert = mkOption {
default = "";
description = "SSL certificate to use.";
};
sslCACert = mkOption {
default = "";
description = "SSL certificate of CA.";
};
sslKey = mkOption {
default = "";
description = "SSL key to use.";
};
recipientDelimiter = mkOption {
default = "";
example = "+";
description = "
Delimiter for address extension: so mail to user+test can be handled by ~user/.forward+test
";
};
};
environment = {
etc = [{
source = "/var/postfix/conf";
target = "postfix";
}];
}; };
users = {
extraUsers = [ ###### implementation
config = mkIf config.services.postfix.enable {
environment.etc = singleton
{ source = "/var/postfix/conf";
target = "postfix";
};
users.extraUsers = singleton
{ name = user; { name = user;
description = "Postfix mail server user"; description = "Postfix mail server user";
uid = config.ids.uids.postfix; uid = config.ids.uids.postfix;
group = group; group = group;
} };
];
extraGroups = [
{ name = group;
gid = config.ids.gids.postfix;
}
{ name = setgidGroup;
gid = config.ids.gids.postdrop;
}
];
};
services = {
extraJobs = [{
name = "postfix";
users.extraGroups =
[ { name = group;
gid = config.ids.gids.postfix;
}
{ name = setgidGroup;
gid = config.ids.gids.postdrop;
}
];
jobAttrs.postfix =
# I copy _lots_ of shipped configuration filed # I copy _lots_ of shipped configuration filed
# that can be left as is. I am afraid the exact # that can be left as is. I am afraid the exact
# will list slightly change in next Postfix # will list slightly change in next Postfix
# release, so listing them all one-by-one in an # release, so listing them all one-by-one in an
# accurate way is unlikely to be better. # accurate way is unlikely to be better.
job = '' { description = "Postfix mail server";
description "Postfix mail server job"
start on ${startingDependency}/started startOn = "${startingDependency}/started";
stop on never
script script =
''
if ! [ -d /var/spool/postfix ]; then if ! [ -d /var/spool/postfix ]; then
${pkgs.coreutils}/bin/mkdir -p /var/spool/mail /var/postfix/conf /var/postfix/queue ${pkgs.coreutils}/bin/mkdir -p /var/spool/mail /var/postfix/conf /var/postfix/queue
fi fi
@ -318,10 +304,11 @@ mkIf config.services.postfix.enable {
${pkgs.postfix}/sbin/postalias -c /var/postfix/conf /var/postfix/conf/aliases ${pkgs.postfix}/sbin/postalias -c /var/postfix/conf /var/postfix/conf/aliases
${pkgs.postfix}/sbin/postfix -c /var/postfix/conf start ${pkgs.postfix}/sbin/postfix -c /var/postfix/conf start
end script ''; # */
'';
};
}];
}; };
} }

View File

@ -1,107 +1,99 @@
{pkgs, config, ...}: { config, pkgs, ... }:
with pkgs.lib;
###### interface
let let
inherit (pkgs.lib) mkOption mkIf;
options = { cfg = config.services.autofs;
services = {
autofs = {
enable = mkOption {
default = false;
description = "
automatically mount and unmount filesystems
";
};
autoMaster = mkOption {
example = ''
autoMaster = let
mapConf = pkgs.writeText "auto" '''
kernel -ro,soft,intr ftp.kernel.org:/pub/linux
boot -fstype=ext2 :/dev/hda1
windoze -fstype=smbfs ://windoze/c
removable -fstype=ext2 :/dev/hdd
cd -fstype=iso9660,ro :/dev/hdc
floppy -fstype=auto :/dev/fd0
server -rw,hard,intr / -ro myserver.me.org:/ \
/usr myserver.me.org:/usr \
/home myserver.me.org:/home
''';
in '''
/auto file:''${mapConf}
'''
'';
description = "
file contents of /etc/auto.master. See man auto.master
see
man auto.master and man 5 autofs
";
};
timeout = mkOption {
default = 600;
description = "Set the global minimum timeout, in seconds, until directories are unmounted";
};
debug = mkOption {
default = false;
description = "pass -d to automount and write log to /var/log/autofs";
};
};
};
};
###### implementation
inherit (pkgs) lib writeTextopenssh autofs5;
cfg = (config.services.autofs);
modprobe = config.system.sbin.modprobe;
in in
mkIf cfg.enable { {
require = [ ###### interface
options
];
environment = { options = {
etc =
[ { services.autofs = {
target = "auto.master";
enable = mkOption {
default = false;
description = "
automatically mount and unmount filesystems
";
};
autoMaster = mkOption {
example = ''
autoMaster = let
mapConf = pkgs.writeText "auto" '''
kernel -ro,soft,intr ftp.kernel.org:/pub/linux
boot -fstype=ext2 :/dev/hda1
windoze -fstype=smbfs ://windoze/c
removable -fstype=ext2 :/dev/hdd
cd -fstype=iso9660,ro :/dev/hdc
floppy -fstype=auto :/dev/fd0
server -rw,hard,intr / -ro myserver.me.org:/ \
/usr myserver.me.org:/usr \
/home myserver.me.org:/home
''';
in '''
/auto file:''${mapConf}
'''
'';
description = "
file contents of /etc/auto.master. See man auto.master
see
man auto.master and man 5 autofs
";
};
timeout = mkOption {
default = 600;
description = "Set the global minimum timeout, in seconds, until directories are unmounted";
};
debug = mkOption {
default = false;
description = "pass -d to automount and write log to /var/log/autofs";
};
};
};
###### implementation
config = mkIf cfg.enable {
environment.etc = singleton
{ target = "auto.master";
source = pkgs.writeText "auto.master" cfg.autoMaster; source = pkgs.writeText "auto.master" cfg.autoMaster;
}]; };
};
jobAttrs.autofs =
services = { { description = "Filesystem automounter";
extraJobs = [
{ startOn = "network-interfaces/started";
name = "autofs"; stopOn = "network-interfaces/stop";
# kernel module autofs supports kernel protocol v3 environment =
# kernel module autofs4 supports kernel protocol v3, v4, v5 { PATH = "${pkgs.nfsUtils}/sbin:${config.system.sbin.modprobe}/sbin";
job = '' };
description "automatically mount filesystems"
preStart =
start on network-interfaces/started ''
stop on network-interfaces/stop modprobe autofs4 || true
'';
PATH=${pkgs.nfsUtils}/sbin:${modprobe}/sbin
script =
start script ''
modprobe autofs4 || true ${if cfg.debug then "exec &> /var/log/autofs" else ""}
end script ${pkgs.autofs5}/sbin/automount -f -t ${builtins.toString cfg.timeout} ${if cfg.debug then "-d" else ""} "${pkgs.writeText "auto.master" cfg.autoMaster}"
'';
script };
${if cfg.debug then "exec &> /var/log/autofs" else ""}
${pkgs.autofs5}/sbin/automount -f -t ${builtins.toString cfg.timeout} ${if cfg.debug then "-d" else ""} "${pkgs.writeText "auto.master" cfg.autoMaster}"
end script
'';
}
];
}; };
} }

View File

@ -1,62 +1,57 @@
# Disnix server # Disnix server
{config, pkgs, ...}: { config, pkgs, ... }:
with pkgs.lib;
###### interface
let let
inherit (pkgs.lib) mkOption;
cfg = config.services.disnix;
in
{
###### interface
options = { options = {
services = {
disnix = {
enable = mkOption {
default = false;
description = "Whether to enable Disnix";
};
};
};
};
in
###### implementation
let
cfg = config.services.disnix;
inherit (pkgs.lib) mkIf;
job = {
name = "disnix";
job = ''
description "Disnix server"
start on dbus
stop on shutdown
script
export ACTIVATION_SCRIPTS=${pkgs.disnix_activation_scripts}/libexec/disnix/activation-scripts
export PATH=${pkgs.nixUnstable}/bin
export HOME=/root
${pkgs.disnix}/bin/disnix-service
end script
'';
};
in
mkIf cfg.enable {
require = [
#../upstart-jobs/default.nix
#../upstart-jobs/dbus.nix # services.dbus.*
options
];
environment.systemPackages = [ pkgs.disnix ]; services.disnix = {
enable = mkOption {
default = false;
description = "Whether to enable Disnix";
};
services = {
extraJobs = [job];
dbus = {
enable = true;
packages = [ pkgs.disnix ];
}; };
}; };
###### implementation
config = mkIf cfg.enable {
environment.systemPackages = [ pkgs.disnix ];
services.dbus.enable = true;
services.dbus.packages = [ pkgs.disnix ];
jobAttrs.disnix =
{ description = "Disnix server";
startOn = "dbus";
stopOn = "shutdown";
script =
''
export ACTIVATION_SCRIPTS=${pkgs.disnix_activation_scripts}/libexec/disnix/activation-scripts
export PATH=${pkgs.nixUnstable}/bin
export HOME=/root
${pkgs.disnix}/bin/disnix-service
'';
};
};
} }

View File

@ -1,108 +1,105 @@
{pkgs, config, ...}: { config, pkgs, ... }:
with pkgs.lib;
###### interface
let let
inherit (pkgs.lib) mkOption mkIf;
uid = config.ids.uids.gpsd; uid = config.ids.uids.gpsd;
gid = config.ids.gids.gpsd; gid = config.ids.gids.gpsd;
cfg = config.services.gpsd;
options = {
services = {
gpsd = {
enable = mkOption {
default = false;
description = ''
Whether to enable `gpsd', a GPS service daemon.
'';
};
device = mkOption {
default = "/dev/ttyUSB0";
description = ''
A device may be a local serial device for GPS input, or a URL of the form:
<literal>[{dgpsip|ntrip}://][user:passwd@]host[:port][/stream]</literal>
in which case it specifies an input source for DGPS or ntrip data.
'';
};
readonly = mkOption {
default = true;
description = ''
Whether to enable the broken-device-safety, otherwise
known as read-only mode. Some popular bluetooth and USB
receivers lock up or become totally inaccessible when
probed or reconfigured. This switch prevents gpsd from
writing to a receiver. This means that gpsd cannot
configure the receiver for optimal performance, but it
also means that gpsd cannot break the receiver. A better
solution would be for Bluetooth to not be so fragile. A
platform independent method to identify
serial-over-Bluetooth devices would also be nice.
'';
};
port = mkOption {
default = 2947;
description = ''
The port where to listen for TCP connections.
'';
};
debugLevel = mkOption {
default = 0;
description = ''
The debugging level.
'';
};
};
};
};
in in
###### implementation {
mkIf config.services.gpsd.enable {
require = [ ###### interface
options
]; options = {
users = { services.gpsd = {
extraUsers = [
enable = mkOption {
default = false;
description = ''
Whether to enable `gpsd', a GPS service daemon.
'';
};
device = mkOption {
default = "/dev/ttyUSB0";
description = ''
A device may be a local serial device for GPS input, or a URL of the form:
<literal>[{dgpsip|ntrip}://][user:passwd@]host[:port][/stream]</literal>
in which case it specifies an input source for DGPS or ntrip data.
'';
};
readonly = mkOption {
default = true;
description = ''
Whether to enable the broken-device-safety, otherwise
known as read-only mode. Some popular bluetooth and USB
receivers lock up or become totally inaccessible when
probed or reconfigured. This switch prevents gpsd from
writing to a receiver. This means that gpsd cannot
configure the receiver for optimal performance, but it
also means that gpsd cannot break the receiver. A better
solution would be for Bluetooth to not be so fragile. A
platform independent method to identify
serial-over-Bluetooth devices would also be nice.
'';
};
port = mkOption {
default = 2947;
description = ''
The port where to listen for TCP connections.
'';
};
debugLevel = mkOption {
default = 0;
description = ''
The debugging level.
'';
};
};
};
###### implementation
config = mkIf cfg.enable {
users.extraUsers = singleton
{ name = "gpsd"; { name = "gpsd";
inherit uid; inherit uid;
description = "gpsd daemon user"; description = "gpsd daemon user";
home = "/var/empty"; home = "/var/empty";
} };
];
extraGroups = [ users.extraGroups = singleton
{ name = "gpsd"; { name = "gpsd";
inherit gid; inherit gid;
} };
];
};
services = jobAttrs.gpsd =
let cfg = config.services.gpsd; in { { description = "GPSD daemon";
extraJobs = [{
name = "gpsd";
job = startOn = "network-interfaces/started";
let gpsd = pkgs.gpsd; stopOn = "network-interfaces/stop";
in ''
description "GPSD daemon"
start on network-interfaces/started exec =
stop on network-interfaces/stop ''
respawn ${pkgs.gpsd}/sbin/gpsd -D "${toString cfg.debugLevel}" \
respawn ${gpsd}/sbin/gpsd -D "${toString cfg.debugLevel}" \ -S "${toString cfg.port}" \
-S "${toString cfg.port}" \ ${if cfg.readonly then "-b" else ""} \
${if cfg.readonly then "-b" else ""} \
"${cfg.device}" "${cfg.device}"
''; '';
}];
}; };
};
} }

View File

@ -3,12 +3,12 @@
# of the virtual consoles. The latter is useful for the installation # of the virtual consoles. The latter is useful for the installation
# CD. # CD.
{pkgs, config, options, ...}: { config, pkgs, options, ... }:
with pkgs.lib;
let let
inherit (pkgs.lib) mkOption mkIf types;
cfg = config.services.nixosManual; cfg = config.services.nixosManual;
manual = import ../../../doc/manual { manual = import ../../../doc/manual {
@ -72,18 +72,22 @@ in
boot.extraTTYs = mkIf cfg.showManual [cfg.ttyNumber]; boot.extraTTYs = mkIf cfg.showManual [cfg.ttyNumber];
services.extraJobs = mkIf cfg.showManual (pkgs.lib.singleton jobAttrs = mkIf cfg.showManual
{ name = "nixos-manual"; { nixosManual =
{ name = "nixos-manual";
job = '' description = "NixOS manual";
description "NixOS manual"
start on udev startOn = "udev";
stop on shutdown stopOn = "shutdown";
respawn ${cfg.browser} ${manual}/share/doc/nixos/manual.html \
< /dev/tty${toString cfg.ttyNumber} > /dev/tty${toString cfg.ttyNumber} 2>&1 exec =
''; ''
}); ${cfg.browser} ${manual}/share/doc/nixos/manual.html \
< /dev/tty${toString cfg.ttyNumber} > /dev/tty${toString cfg.ttyNumber} 2>&1
'';
};
};
services.ttyBackgrounds.specificThemes = mkIf cfg.showManual services.ttyBackgrounds.specificThemes = mkIf cfg.showManual
[ { tty = cfg.ttyNumber; [ { tty = cfg.ttyNumber;

View File

@ -1,106 +1,108 @@
{ config, pkgs, ... }:
{pkgs, config, ...}: with pkgs.lib;
###### interface
let let
inherit (pkgs.lib) mkOption mkIf;
options = { cfgC = config.services.synergy.client;
services = { cfgS = config.services.synergy.server;
synergy = {
client = {
enable = mkOption {
default = false;
description = "
Whether to enable the synergy client (receive keyboard and mouse events from a synergy server)
";
};
screenName = mkOption {
default = "";
description = "
use screen-name instead the hostname to identify
ourselfs to the server.
";
};
};
server = {
enable = mkOption {
default = false;
description = "
Whether to enable the synergy server (send keyboard and mouse events)
";
};
configFile = mkOption {
default = "/etc/synergy-server.conf";
description = "
The synergy server configuration file. open upstart-jobs/synergy.nix to see an example
";
};
screenName = mkOption {
default = "";
description = "
use screen-name instead the hostname to identify
this screen in the configuration.
";
};
address = mkOption {
default = "";
description = "listen for clients on the given address";
};
};
};
};
};
###### implementation
inherit (pkgs.lib) optional;
cfgC = (config.services.synergy.client);
cfgS = (config.services.synergy.server);
clientJob = {
name = "synergy-client";
job = ''
description "synergy client"
start on started network-interfaces
stop on stopping network-interfaces
respawn ${pkgs.synergy}/bin/synergyc ${if cfgS.screenName == "" then "" else "-n ${cfgS.screenName}" }
'';
};
serverJob = {
name = "synergy-server";
job = ''
description "synergy server"
start on started network-interfaces
stop on stopping network-interfaces
respawn ${pkgs.synergy}/bin/synergys -c ${cfgS.configFile} \
-f ${if cfgS.address == "" then "" else "-a ${cfgS.address}"} \
${if cfgS.screenName == "" then "" else "-n ${cfgS.screenName}" }
'';
};
in in
{ {
require = [ ###### interface
options
]; options = {
services.synergy = {
# !!! All these option descriptions needs to be cleaned up.
client = {
enable = mkOption {
default = false;
description = "
Whether to enable the synergy client (receive keyboard and mouse events from a synergy server)
";
};
screenName = mkOption {
default = "";
description = "
use screen-name instead the hostname to identify
ourselfs to the server.
";
};
};
server = {
enable = mkOption {
default = false;
description = "
Whether to enable the synergy server (send keyboard and mouse events)
";
};
configFile = mkOption {
default = "/etc/synergy-server.conf";
description = "
The synergy server configuration file. open upstart-jobs/synergy.nix to see an example
";
};
screenName = mkOption {
default = "";
description = "
use screen-name instead the hostname to identify
this screen in the configuration.
";
};
address = mkOption {
default = "";
description = "listen for clients on the given address";
};
};
};
services = {
extraJobs = (optional cfgS.enable serverJob)
++ (optional cfgC.enable clientJob);
}; };
###### implementation
config = {
jobAttrs =
optionalAttrs cfgC.enable
{ synergyClient =
{ name = "synergy-client";
description = "Synergy client";
startOn = "network-interfaces/started";
stopOn = "network-interfaces/stopped";
exec = "${pkgs.synergy}/bin/synergyc ${if cfgS.screenName == "" then "" else "-n ${cfgS.screenName}" }";
};
}
// optionalAttrs cfgS.enable
{ synergyServer =
{ name = "synergy-server";
description = "Synergy server";
startOn = "network-interfaces/started";
stopOn = "network-interfaces/stopped";
exec =
''
respawn ${pkgs.synergy}/bin/synergys -c ${cfgS.configFile} \
-f ${if cfgS.address == "" then "" else "-a ${cfgS.address}"} \
${if cfgS.screenName == "" then "" else "-n ${cfgS.screenName}" }
'';
};
};
};
} }
/* SYNERGY SERVER example configuration file /* SYNERGY SERVER example configuration file

View File

@ -1,65 +1,11 @@
# Nagios system/network monitoring daemon. # Nagios system/network monitoring daemon.
{config, pkgs, ...}: { config, pkgs, ... }:
with pkgs.lib;
###### interface
let let
inherit (pkgs.lib) mkOption;
options = {
services = {
nagios = {
enable = mkOption {
default = false;
description = "
Whether to use <link
xlink:href='http://www.nagios.org/'>Nagios</link> to monitor
your system or network.
";
};
objectDefs = mkOption {
description = "
A list of Nagios object configuration files that must define
the hosts, host groups, services and contacts for the
network that you want Nagios to monitor.
";
};
plugins = mkOption {
default = [pkgs.nagiosPluginsOfficial pkgs.ssmtp];
description = "
Packages to be added to the Nagios <envar>PATH</envar>.
Typically used to add plugins, but can be anything.
";
};
enableWebInterface = mkOption {
default = false;
description = "
Whether to enable the Nagios web interface. You should also
enable Apache (<option>services.httpd.enable</option>).
";
};
urlPath = mkOption {
default = "/nagios";
description = "
The URL path under which the Nagios web interface appears.
That is, you can access the Nagios web interface through
<literal>http://<replaceable>server</replaceable>/<replaceable>urlPath</replaceable></literal>.
";
};
};
};
};
in
###### implementation
let
cfg = config.services.nagios; cfg = config.services.nagios;
inherit (pkgs.lib) mkIf mkThenElse;
nagiosUser = "nagios"; nagiosUser = "nagios";
nagiosGroup = "nogroup"; nagiosGroup = "nogroup";
@ -67,146 +13,184 @@ let
nagiosState = "/var/lib/nagios"; nagiosState = "/var/lib/nagios";
nagiosLogDir = "/var/log/nagios"; nagiosLogDir = "/var/log/nagios";
nagiosObjectDefs = [ nagiosObjectDefs =
./timeperiods.cfg [ ./timeperiods.cfg
./host-templates.cfg ./host-templates.cfg
./service-templates.cfg ./service-templates.cfg
./commands.cfg ./commands.cfg
] ++ cfg.objectDefs; ] ++ cfg.objectDefs;
nagiosObjectDefsDir = pkgs.runCommand "nagios-objects" {inherit nagiosObjectDefs;} nagiosObjectDefsDir = pkgs.runCommand "nagios-objects" {inherit nagiosObjectDefs;}
"ensureDir $out; ln -s $nagiosObjectDefs $out/"; "ensureDir $out; ln -s $nagiosObjectDefs $out/";
nagiosCfgFile = pkgs.writeText "nagios.cfg" " nagiosCfgFile = pkgs.writeText "nagios.cfg"
''
# Paths for state and logs. # Paths for state and logs.
log_file=${nagiosLogDir}/current log_file=${nagiosLogDir}/current
log_archive_path=${nagiosLogDir}/archive log_archive_path=${nagiosLogDir}/archive
status_file=${nagiosState}/status.dat status_file=${nagiosState}/status.dat
object_cache_file=${nagiosState}/objects.cache object_cache_file=${nagiosState}/objects.cache
comment_file=${nagiosState}/comment.dat comment_file=${nagiosState}/comment.dat
downtime_file=${nagiosState}/downtime.dat downtime_file=${nagiosState}/downtime.dat
temp_file=${nagiosState}/nagios.tmp temp_file=${nagiosState}/nagios.tmp
lock_file=/var/run/nagios.lock # Not used I think. lock_file=/var/run/nagios.lock # Not used I think.
state_retention_file=${nagiosState}/retention.dat state_retention_file=${nagiosState}/retention.dat
# Configuration files. # Configuration files.
#resource_file=resource.cfg #resource_file=resource.cfg
cfg_dir=${nagiosObjectDefsDir} cfg_dir=${nagiosObjectDefsDir}
# Uid/gid that the daemon runs under. # Uid/gid that the daemon runs under.
nagios_user=${nagiosUser} nagios_user=${nagiosUser}
nagios_group=${nagiosGroup} nagios_group=${nagiosGroup}
# Misc. options. # Misc. options.
illegal_macro_output_chars=`~$&|'\"<> illegal_macro_output_chars=`~$&|'"<>
retain_state_information=1 retain_state_information=1
''; # "
";
# Plain configuration for the Nagios web-interface with no # Plain configuration for the Nagios web-interface with no
# authentication. # authentication.
nagiosCGICfgFile = pkgs.writeText "nagios.cgi.conf" " nagiosCGICfgFile = pkgs.writeText "nagios.cgi.conf"
main_config_file=${nagiosCfgFile} ''
use_authentication=0 main_config_file=${nagiosCfgFile}
url_html_path=/nagios use_authentication=0
"; url_html_path=/nagios
'';
urlPath = cfg.urlPath; urlPath = cfg.urlPath;
extraHttpdConfig = " extraHttpdConfig =
ScriptAlias ${urlPath}/cgi-bin ${pkgs.nagios}/sbin ''
ScriptAlias ${urlPath}/cgi-bin ${pkgs.nagios}/sbin
<Directory \"${pkgs.nagios}/sbin\"> <Directory "${pkgs.nagios}/sbin">
Options ExecCGI Options ExecCGI
AllowOverride None AllowOverride None
Order allow,deny Order allow,deny
Allow from all Allow from all
SetEnv NAGIOS_CGI_CONFIG ${nagiosCGICfgFile} SetEnv NAGIOS_CGI_CONFIG ${nagiosCGICfgFile}
</Directory> </Directory>
Alias ${urlPath} ${pkgs.nagios}/share Alias ${urlPath} ${pkgs.nagios}/share
<Directory \"${pkgs.nagios}/share\"> <Directory "${pkgs.nagios}/share">
Options None Options None
AllowOverride None AllowOverride None
Order allow,deny Order allow,deny
Allow from all Allow from all
</Directory> </Directory>
"; '';
user = {
name = nagiosUser;
uid = config.ids.uids.nagios;
description = "Nagios monitoring daemon";
home = nagiosState;
};
job = {
name = "nagios";
# Run `nagios -v' to check the validity of the configuration file so
# that a nixos-rebuild fails *before* we kill the running Nagios
# daemon.
buildHook = "${pkgs.nagios}/bin/nagios -v ${nagiosCfgFile}";
job = "
description \"Nagios monitoring daemon\"
start on network-interfaces/started
stop on network-interfaces/stop
start script
mkdir -m 0755 -p ${nagiosState} ${nagiosLogDir}
chown ${nagiosUser} ${nagiosState} ${nagiosLogDir}
end script
respawn
script
for i in ${toString config.services.nagios.plugins}; do
export PATH=$i/bin:$i/sbin:$i/libexec:$PATH
done
exec ${pkgs.nagios}/bin/nagios ${nagiosCfgFile}
end script
";
};
in in
{
###### interface
mkIf cfg.enable { options = {
require = [
# ../../upstart-jobs/default.nix # config.services.extraJobs services.nagios = {
# ../../system/user.nix # users = { .. }
# ? # config.environment.etc enable = mkOption {
# ? # config.environment.extraPackages default = false;
# ../../upstart-jobs/httpd.nix # config.services.httpd description = "
options Whether to use <link
]; xlink:href='http://www.nagios.org/'>Nagios</link> to monitor
your system or network.
";
};
objectDefs = mkOption {
description = "
A list of Nagios object configuration files that must define
the hosts, host groups, services and contacts for the
network that you want Nagios to monitor.
";
};
plugins = mkOption {
default = [pkgs.nagiosPluginsOfficial pkgs.ssmtp];
description = "
Packages to be added to the Nagios <envar>PATH</envar>.
Typically used to add plugins, but can be anything.
";
};
enableWebInterface = mkOption {
default = false;
description = "
Whether to enable the Nagios web interface. You should also
enable Apache (<option>services.httpd.enable</option>).
";
};
urlPath = mkOption {
default = "/nagios";
description = "
The URL path under which the Nagios web interface appears.
That is, you can access the Nagios web interface through
<literal>http://<replaceable>server</replaceable>/<replaceable>urlPath</replaceable></literal>.
";
};
};
};
###### implementation
config = mkIf cfg.enable {
users.extraUsers = singleton
{ name = nagiosUser;
uid = config.ids.uids.nagios;
description = "Nagios monitoring daemon";
home = nagiosState;
};
environment = {
# This isn't needed, it's just so that the user can type "nagiostats # This isn't needed, it's just so that the user can type "nagiostats
# -c /etc/nagios.cfg". # -c /etc/nagios.cfg".
etc = [ environment.etc = singleton
{ source = nagiosCfgFile; { source = nagiosCfgFile;
target = "nagios.cfg"; target = "nagios.cfg";
} };
];
systemPackages = [pkgs.nagios]; environment.systemPackages = [ pkgs.nagios ];
};
users = { jobAttrs.nagios =
extraUsers = [user]; { # Run `nagios -v' to check the validity of the configuration file so
}; # that a nixos-rebuild fails *before* we kill the running Nagios
# daemon.
buildHook = "${pkgs.nagios}/bin/nagios -v ${nagiosCfgFile}";
services = { description = "Nagios monitoring daemon";
extraJobs = [job];
httpd = mkIf cfg.enableWebInterface { startOn = "network-interfaces/started";
stopOn = "network-interfaces/stop";
preStart =
''
mkdir -m 0755 -p ${nagiosState} ${nagiosLogDir}
chown ${nagiosUser} ${nagiosState} ${nagiosLogDir}
'';
script =
''
for i in ${toString config.services.nagios.plugins}; do
export PATH=$i/bin:$i/sbin:$i/libexec:$PATH
done
exec ${pkgs.nagios}/bin/nagios ${nagiosCfgFile}
'';
};
services.httpd = mkIf cfg.enableWebInterface {
extraConfig = mkThenElse { extraConfig = mkThenElse {
thenPart = extraHttpdConfig; thenPart = extraHttpdConfig;
elsePart = ""; elsePart = "";
}; };
}; };
}; };
} }

View File

@ -1,35 +1,8 @@
# Zabbix agent daemon. # Zabbix agent daemon.
{config, pkgs, ...}: { config, pkgs, ... }:
###### interface with pkgs.lib;
let
inherit (pkgs.lib) mkOption;
options = {
services = {
zabbixAgent = {
enable = mkOption {
default = false;
description = "
Whether to run the Zabbix monitoring agent on this machine.
It will send monitoring data to a Zabbix server.
";
};
server = mkOption {
default = "127.0.0.1";
description = ''
The IP address or hostname of the Zabbix server to connect to.
'';
};
};
};
};
in
###### implementation
let let
cfg = config.services.zabbixAgent; cfg = config.services.zabbixAgent;
@ -40,69 +13,87 @@ let
pidFile = "${stateDir}/zabbix_agentd.pid"; pidFile = "${stateDir}/zabbix_agentd.pid";
configFile = pkgs.writeText "zabbix_agentd.conf" '' configFile = pkgs.writeText "zabbix_agentd.conf"
Server = ${cfg.server} ''
Server = ${cfg.server}
LogFile = ${logDir}/zabbix_agentd LogFile = ${logDir}/zabbix_agentd
PidFile = ${pidFile} PidFile = ${pidFile}
StartAgents = 5 StartAgents = 5
'';
user = {
name = "zabbix";
uid = config.ids.uids.zabbix;
description = "Zabbix daemon user";
};
job = {
name = "zabbix-agent";
job = ''
start on network-interfaces/started
stop on network-interfaces/stop
description "Zabbix agent daemon"
start script
mkdir -m 0755 -p ${stateDir} ${logDir}
chown zabbix ${stateDir} ${logDir}
export PATH=${pkgs.nettools}/bin:$PATH
${pkgs.zabbixAgent}/sbin/zabbix_agentd --config ${configFile}
end script
respawn sleep 100000
stop script
# !!! this seems to leave processes behind.
#pid=$(cat ${pidFile})
#if test -n "$pid"; then
# kill $pid
#fi
# So instead kill the agent in a brutal fashion.
while ${pkgs.procps}/bin/pkill -u zabbix zabbix_agentd; do true; done
end script
''; '';
};
ifEnable = pkgs.lib.ifEnable cfg.enable;
in in
{ {
require = [
# ../upstart-jobs/default.nix
# ../system/user.nix # users = { .. }
options
];
services = { ###### interface
extraJobs = ifEnable [job];
options = {
services.zabbixAgent = {
enable = mkOption {
default = false;
description = ''
Whether to run the Zabbix monitoring agent on this machine.
It will send monitoring data to a Zabbix server.
'';
};
server = mkOption {
default = "127.0.0.1";
description = ''
The IP address or hostname of the Zabbix server to connect to.
'';
};
};
};
###### implementation
config = mkIf cfg.enable {
users.extraUsers = singleton
{ name = "zabbix";
uid = config.ids.uids.zabbix;
description = "Zabbix daemon user";
};
jobAttrs.zabbix_agent =
{ #name = "zabbix-agent"; !!! mkIf bug
description = "Zabbix agent daemon";
startOn = "network-interfaces/started";
stopOn = "network-interfaces/stop";
preStart =
''
mkdir -m 0755 -p ${stateDir} ${logDir}
chown zabbix ${stateDir} ${logDir}
export PATH=${pkgs.nettools}/bin:$PATH
${pkgs.zabbixAgent}/sbin/zabbix_agentd --config ${configFile}
'';
postStop =
''
# !!! this seems to leave processes behind.
#pid=$(cat ${pidFile})
#if test -n "$pid"; then
# kill $pid
#fi
# So instead kill the agent in a brutal fashion.
while ${pkgs.procps}/bin/pkill -u zabbix zabbix_agentd; do true; done
'';
};
}; };
users = {
extraUsers = ifEnable [user];
};
} }

View File

@ -1,25 +1,8 @@
# Zabbix server daemon. # Zabbix server daemon.
{config, pkgs, ...}: { config, pkgs, ... }:
###### interface with pkgs.lib;
let
inherit (pkgs.lib) mkOption;
options = {
services = {
zabbixServer = {
enable = mkOption {
default = false;
description = "
Whether to run the Zabbix server on this machine.
";
};
};
};
};
in
###### implementation
let let
stateDir = "/var/run/zabbix"; stateDir = "/var/run/zabbix";
@ -30,72 +13,76 @@ let
pidFile = "${stateDir}/zabbix_server.pid"; pidFile = "${stateDir}/zabbix_server.pid";
configFile = pkgs.writeText "zabbix_server.conf" '' configFile = pkgs.writeText "zabbix_server.conf"
LogFile = ${logDir}/zabbix_server ''
LogFile = ${logDir}/zabbix_server
PidFile = ${pidFile} PidFile = ${pidFile}
DBName = zabbix DBName = zabbix
DBUser = zabbix DBUser = zabbix
'';
user = {
name = "zabbix";
uid = config.ids.uids.zabbix;
description = "Zabbix daemon user";
};
job = {
name = "zabbix-server";
job = ''
description "Zabbix server daemon"
start on postgresql/started
stop on shutdown
start script
mkdir -m 0755 -p ${stateDir} ${logDir} ${libDir}
chown zabbix ${stateDir} ${logDir} ${libDir}
if ! test -e "${libDir}/db-created"; then
${pkgs.postgresql}/bin/createuser --no-superuser --no-createdb --no-createrole zabbix || true
${pkgs.postgresql}/bin/createdb --owner zabbix zabbix || true
cat ${pkgs.zabbixServer}/share/zabbix/db/schema/postgresql.sql | ${pkgs.su}/bin/su -s "$SHELL" zabbix -c 'psql zabbix'
cat ${pkgs.zabbixServer}/share/zabbix/db/data/data.sql | ${pkgs.su}/bin/su -s "$SHELL" zabbix -c 'psql zabbix'
cat ${pkgs.zabbixServer}/share/zabbix/db/data/images_pgsql.sql | ${pkgs.su}/bin/su -s "$SHELL" zabbix -c 'psql zabbix'
touch "${libDir}/db-created"
fi
export PATH=${pkgs.nettools}/bin:$PATH
${pkgs.zabbixServer}/sbin/zabbix_server --config ${configFile}
end script
respawn sleep 100000
stop script
while ${pkgs.procps}/bin/pkill -u zabbix zabbix_server; do true; done
end script
''; '';
};
ifEnable = pkgs.lib.ifEnable config.services.zabbixServer.enable;
in in
{ {
require = [
# ../upstart-jobs/default.nix
# ../system/user.nix # users = { .. }
options
];
services = { ###### interface
extraJobs = ifEnable [job];
options = {
services.zabbixServer.enable = mkOption {
default = false;
description = ''
Whether to run the Zabbix server on this machine.
'';
};
}; };
users = { ###### implementation
extraUsers = ifEnable [user];
config = mkIf config.services.zabbixServer.enable {
users.extraUsers = singleton
{ name = "zabbix";
uid = config.ids.uids.zabbix;
description = "Zabbix daemon user";
};
jobAttrs.zabbix_server =
{ #name = "zabbix-server"; !!! mkIf bug
description = "Zabbix server daemon";
startOn = "postgresql";
stopOn = "shutdown";
preStart =
''
mkdir -m 0755 -p ${stateDir} ${logDir} ${libDir}
chown zabbix ${stateDir} ${logDir} ${libDir}
if ! test -e "${libDir}/db-created"; then
${pkgs.postgresql}/bin/createuser --no-superuser --no-createdb --no-createrole zabbix || true
${pkgs.postgresql}/bin/createdb --owner zabbix zabbix || true
cat ${pkgs.zabbixServer}/share/zabbix/db/schema/postgresql.sql | ${pkgs.su}/bin/su -s "$SHELL" zabbix -c 'psql zabbix'
cat ${pkgs.zabbixServer}/share/zabbix/db/data/data.sql | ${pkgs.su}/bin/su -s "$SHELL" zabbix -c 'psql zabbix'
cat ${pkgs.zabbixServer}/share/zabbix/db/data/images_pgsql.sql | ${pkgs.su}/bin/su -s "$SHELL" zabbix -c 'psql zabbix'
touch "${libDir}/db-created"
fi
export PATH=${pkgs.nettools}/bin:$PATH
${pkgs.zabbixServer}/sbin/zabbix_server --config ${configFile}
'';
postStop =
''
while ${pkgs.procps}/bin/pkill -u zabbix zabbix_server; do true; done
'';
};
}; };
} }

View File

@ -1,154 +1,149 @@
{ config, pkgs, ... }:
{pkgs, config, ...}: with pkgs.lib;
###### interface
let let
inherit (pkgs.lib) mkOption mkIf;
options = {
services = {
nfsKernel = {
enable = mkOption {
default = false;
description = "
wether to use the kernel nfs functionality to export filesystems.
You should be aware about existing security issues.
requires portmap!
";
};
exports = mkOption {
check = v: v != "/etc/exports"; # this won't work
description = "
the file listing the directories to be exported.
install nfsUtils and run man exports to learn about its format.
The exports setting can either be a file path or the file contents.
Don't use /etc/exports. This won't work as nix will overwrite it.
";
};
hostName = mkOption {
default = null;
description = "
specify a particular hostname (or address) that NFS requests will be accepted on.
Default: all.
See man rpc.nfsd (-H option)
";
};
nproc = mkOption {
default = 8;
description = "
specify the number of NFS server threads. (-> man rpc.nfsd). Defaults to recommended value 8
";
};
createMountPoints = mkOption {
default = false;
description = "Whether to create the mount points in the exports file at startup time.";
};
};
};
};
###### implementation
inherit (pkgs) writeText openssh; inherit (pkgs) writeText openssh;
cfg = (config.services.nfsKernel); cfg = config.services.nfsKernel;
modprobe = config.system.sbin.modprobe; exports =
if builtins.pathExists cfg.exports
exports = if builtins.pathExists cfg.exports then cfg.exports
then cfg.exports else pkgs.writeText "exports" cfg.exports; else pkgs.writeText "exports" cfg.exports;
in in
{
mkIf config.services.nfsKernel.enable { ###### interface
require = [
options
];
environment.etc = [ options = {
{ source = exports;
target = "exports"; } services.nfsKernel = {
];
services = { enable = mkOption {
extraJobs = [ default = false;
{ description = ''
name = "nfs-kernel-exports"; Whether to enable the kernel's NFS server.
'';
};
job = '' # !!! Why is this a file? Why not a list of export entries?
description "export filesystems using kernel nfs" exports = mkOption {
check = v: v != "/etc/exports"; # this won't work
description = ''
The file listing the directories to be exported. See
<citerefentry><refentrytitle>exports</refentrytitle>
<manvolnum>5</manvolnum></citerefentry> for the format.
'';
};
start on network-interfaces/started hostName = mkOption {
stop on network-interfaces/stop default = null;
description = ''
start script Hostname or address on which NFS requests will be accepted.
export PATH=${pkgs.nfsUtils}/sbin:$PATH Default is all. See the <option>-H</option> option in
mkdir -p /var/lib/nfs <citerefentry><refentrytitle>nfsd</refentrytitle>
${modprobe}/sbin/modprobe nfsd || true <manvolnum>8</manvolnum></citerefentry>.
'';
${if cfg.createMountPoints == true then };
''
# create export directories:
# skip comments, take first col which may either be a quoted
# "foo bar" or just foo (-> man export)
sed '/^#.*/d;s/^"\([^"]*\)".*/\1/;t;s/[ ].*//' ${exports} \
| xargs -d '\n' mkdir -p
''
else ""}
# exports file is ${exports}
# keep this comment so that this job is restarted whenever exports changes!
exportfs -ra
end script
respawn sleep 1000000
'';
}
{
name = "nfs-kernel-rpc-nfsd";
job = ''
description "export filesystems using kernel nfs"
start on nfs-kernel-exports/started
stop on nfs-kernel-exports/stop
respawn ${pkgs.nfsUtils}/sbin/rpc.nfsd ${if cfg.hostName != null then "-H ${cfg.hostName}" else ""} ${builtins.toString cfg.nproc}
'';
}
{
name = "nfs-kernel-mountd";
job = ''
description "export filesystems using kernel nfs"
start on nfs-kernel-rpc-nfsd/started
stop on nfs-kernel-exports/stop
respawn ${pkgs.nfsUtils}/sbin/rpc.mountd -F -f ${exports}
'';
}
{
name = "nfs-kernel-statd";
job = '' nproc = mkOption {
description "NSM (Network Status Monitor) of the RPC protocol" default = 8;
description = ''
start on nfs-kernel-rpc-nfsd/started Number of NFS server threads. Defaults to the recommended value of 8.
stop on nfs-kernel-exports/stop '';
};
start script
mkdir -p /var/lib/nfs createMountPoints = mkOption {
end script default = false;
description = "Whether to create the mount points in the exports file at startup time.";
};
};
respawn ${pkgs.nfsUtils}/sbin/rpc.statd -F
'';
}
];
}; };
###### implementation
config = mkIf config.services.nfsKernel.enable {
environment.etc = singleton
{ source = exports;
target = "exports";
};
jobAttrs.nfs_kernel_exports =
{ name = "nfs-kernel-exports";
description = "Kernel NFS server";
startOn = "network-interfaces/started";
stopOn = "network-interfaces/stop";
preStart =
''
export PATH=${pkgs.nfsUtils}/sbin:$PATH
mkdir -p /var/lib/nfs
${config.system.sbin.modprobe}/sbin/modprobe nfsd || true
${optionalString cfg.createMountPoints
''
# create export directories:
# skip comments, take first col which may either be a quoted
# "foo bar" or just foo (-> man export)
sed '/^#.*/d;s/^"\([^"]*\)".*/\1/;t;s/[ ].*//' ${exports} \
| xargs -d '\n' mkdir -p
''
}
# exports file is ${exports}
# keep this comment so that this job is restarted whenever exports changes!
exportfs -ra
'';
};
jobAttrs.nfs_kernel_nfsd =
{ name = "nfs-kernel-nfsd";
description = "Kernel NFS server";
startOn = "nfs-kernel-exports/started";
stopOn = "nfs-kernel-exports/stop";
exec = "${pkgs.nfsUtils}/sbin/rpc.nfsd ${if cfg.hostName != null then "-H ${cfg.hostName}" else ""} ${builtins.toString cfg.nproc}";
};
jobAttrs.nfs_kernel_mountd =
{ name = "nfs-kernel-mountd";
description = "Kernel NFS server - mount daemon";
startOn = "nfs-kernel-nfsd/started";
stopOn = "nfs-kernel-exports/stop";
exec = "${pkgs.nfsUtils}/sbin/rpc.mountd -F -f ${exports}";
};
jobAttrs.nfs_kernel_statd =
{ name = "nfs-kernel-statd";
description = "Kernel NFS server - Network Status Monitor";
startOn = "nfs-kernel-nfsd/started";
stopOn = "nfs-kernel-exports/stop";
preStart =
''
mkdir -p /var/lib/nfs
'';
exec = "${pkgs.nfsUtils}/sbin/rpc.statd -F";
};
};
} }

View File

@ -1,118 +1,6 @@
{pkgs, config, ...}: { config, pkgs, ... }:
###### interface with pkgs.lib;
let
inherit (pkgs.lib) mkOption mkIf mkAlways;
options = {
services = {
samba = {
enable = mkOption {
default = false;
description = "
Whether to enable the samba server. (to communicate with, and provide windows shares)
use start / stop samba-control to start/stop all daemons.
smbd and nmbd are not shutdown correctly yet. so just pkill them and restart those jobs.
";
};
syncPasswordsByPam = mkOption {
default = false;
description = "
enabling this will add a line directly after pam_unix.so.
Whenever a password is changed the samba password will be updated as well.
However you still yave to add the samba password once using smbpasswd -a user
If you don't want to maintain an extra pwd database you still can send plain text
passwords which is not secure.
";
};
extraConfig = mkOption {
default = ''
# [global] continuing global section here, section is started by nix to set pids etc
smb passwd file = /etc/samba/passwd
# is this useful ?
domain master = auto
encrypt passwords = Yes
client plaintext auth = No
# yes: if you use this you probably also want to enable syncPasswordsByPam
# no: You can still use the pam password database. However
# passwords will be sent plain text on network (discouraged)
workgroup = Users
server string = %h
comment = Samba
log file = /var/log/samba/log.%m
log level = 10
max log size = 50000
security = user
client lanman auth = Yes
dns proxy = no
invalid users = root
passdb backend = tdbsam
passwd program = /usr/bin/passwd %u
### end [ global ] section
# Un-comment the following (and tweak the other settings below to suit)
# to enable the default home directory shares. This will share each
# user's home directory as \\server\username
;[homes]
; comment = Home Directories
; browseable = no
; writable = no
# File creation mask is set to 0700 for security reasons. If you want to
# create files with group=rw permissions, set next parameter to 0775.
; create mask = 0700
# this directory and user is created automatically for you by nixos
;[default]
; path = /home/smbd
; read only = no
; guest ok = yes
# this directory and user is created automatically for you by nixos
;[default]
; path = /home/smbd
; read only = no
; guest ok = yes
# additional share example
;[raidbackup]
; path = /home/raidbackup/files
; read only = no
; guest ok = no
; available = yes
; browseable = yes
; public = yes
; valid users = raidbackup
; comment = Raid backup Files
'';
description = "
additional global section and extra section lines go in here.
";
};
configFile = mkOption {
description = "
internal use to pass filepath to samba pam module
";
};
};
};
};
in
###### implementation
let let
@ -121,115 +9,179 @@ let
user = "smbguest"; user = "smbguest";
group = "smbguest"; group = "smbguest";
logDir = "/var/log/samba"; logDir = "/var/log/samba";
privateDir = "/var/samba/private"; privateDir = "/var/samba/private";
inherit (pkgs) samba; inherit (pkgs) samba;
setupScript = '' setupScript =
mkdir -p /var/lock ''
mkdir -p /var/lock
if ! test -d /home/smbd ; then if ! test -d /home/smbd ; then
mkdir -p /home/smbd mkdir -p /home/smbd
chown ${user} /home/smbd chown ${user} /home/smbd
chmod a+rwx /home/smbd chmod a+rwx /home/smbd
fi fi
if ! test -d /var/samba ; then if ! test -d /var/samba ; then
mkdir -p /var/samba/locks /var/samba/cores/nmbd /var/samba/cores/smbd /var/samba/cores/winbindd mkdir -p /var/samba/locks /var/samba/cores/nmbd /var/samba/cores/smbd /var/samba/cores/winbindd
fi fi
passwdFile="$(sed -n 's/^.*smb[ ]\+passwd[ ]\+file[ ]\+=[ ]\+\(.*\)/\1/p' /nix/store/nnmrqalldfv2vkwy6qpg340rv7w34lmp-smb.conf)" passwdFile="$(sed -n 's/^.*smb[ ]\+passwd[ ]\+file[ ]\+=[ ]\+\(.*\)/\1/p' /nix/store/nnmrqalldfv2vkwy6qpg340rv7w34lmp-smb.conf)"
if [ -n "$passwdFile" ]; then if [ -n "$passwdFile" ]; then
echo 'INFO: creating directory containing passwd file' echo 'INFO: creating directory containing passwd file'
mkdir -p "$(dirname "$passwdFile")" mkdir -p "$(dirname "$passwdFile")"
fi fi
mkdir -p ${logDir} mkdir -p ${logDir}
mkdir -p ${privateDir} mkdir -p ${privateDir}
'';
configFile = pkgs.writeText "smb.conf" '' # The following line is to trigger a restart of the daemons when
[ global ] # the configuration changes:
# ${configFile}
'';
configFile = pkgs.writeText "smb.conf"
''
[ global ]
log file = ${logDir}/log.%m log file = ${logDir}/log.%m
private dir = ${privateDir} private dir = ${privateDir}
${optionalString cfg.syncPasswordsByPam "pam password change = true"}
${if cfg.syncPasswordsByPam then "pam password change = true" else "" /* does this make sense ? */ } ${cfg.extraConfig}
'';
daemonJob = appName: args:
{ name = "samba-${appName}";
description = "Samba Service daemon ${appName}";
${cfg.extraConfig}"; startOn = "samba/started";
''; stopOn = "samba-control/stop";
daemonJob = appName : args : exec = "${samba}/sbin/${appName} ${args}";
{
name = "samba-${appName}";
job = ''
description "Samba Service daemon ${appName}"
start on samba-control/started
stop on samba-control/stop
respawn ${samba}/sbin/${appName} ${args}
'';
}; };
in in
{
mkIf config.services.samba.enable { ###### interface
require = [
options
];
users = { options = {
extraUsers = [
# !!! clean up the descriptions.
services.samba = {
enable = mkOption {
default = false;
description = "
Whether to enable the samba server. (to communicate with, and provide windows shares)
use start / stop samba-control to start/stop all daemons.
smbd and nmbd are not shutdown correctly yet. so just pkill them and restart those jobs.
";
};
syncPasswordsByPam = mkOption {
default = false;
description = "
enabling this will add a line directly after pam_unix.so.
Whenever a password is changed the samba password will be updated as well.
However you still yave to add the samba password once using smbpasswd -a user
If you don't want to maintain an extra pwd database you still can send plain text
passwords which is not secure.
";
};
extraConfig = mkOption {
# !!! Bad default.
default = ''
# [global] continuing global section here, section is started by nix to set pids etc
smb passwd file = /etc/samba/passwd
# is this useful ?
domain master = auto
encrypt passwords = Yes
client plaintext auth = No
# yes: if you use this you probably also want to enable syncPasswordsByPam
# no: You can still use the pam password database. However
# passwords will be sent plain text on network (discouraged)
workgroup = Users
server string = %h
comment = Samba
log file = /var/log/samba/log.%m
log level = 10
max log size = 50000
security = user
client lanman auth = Yes
dns proxy = no
invalid users = root
passdb backend = tdbsam
passwd program = /usr/bin/passwd %u
'';
description = "
additional global section and extra section lines go in here.
";
};
configFile = mkOption {
description = "
internal use to pass filepath to samba pam module
";
};
};
};
###### implementation
config = mkIf config.services.samba.enable {
users.extraUsers = singleton
{ name = user; { name = user;
description = "Samba service user"; description = "Samba service user";
group = group; group = group;
} };
];
users.extraGroups = singleton
extraGroups = [
{ name = group; { name = group;
} };
];
}; # always provide a smb.conf to shut up programs like smbclient and smbspool.
environment.etc = mkAlways (singleton
# always provide a smb.conf to shut up programs like smbclient and smbspool. { source =
environment = { if cfg.enable then configFile
etc = mkAlways [{ else pkgs.writeText "smb-dummy.conf" "# Samba is disabled.";
source = if cfg.enable then configFile else pkgs.writeText "smb-dummy.conf" "# samba is disabled. Purpose see samba expression in nixpkgs"; target = "samba/smb.conf";
target = "samba/smb.conf"; });
}];
}; # Dummy job to start the real Samba daemons (nmbd, smbd, winbindd).
jobAttrs.sambaControl =
services = { { name = "samba";
description = "Samba server";
extraJobs = [
{ name = "samba-control"; # start this dummy job to start the real samba daemons nmbd, smbd, winbindd startOn = "network-interfaces/started";
job = '' stopOn = "network-interfaces/stop";
description "samba job starting/stopping the real samba jobs";
preStart = setupScript;
start on network-interfaces/started };
stop on network-interfaces/stop
# nmbd says "standard input is not a socket, assuming -D option",
start script # but using -i makes it stay in foreground (?)
${setupScript} jobAttrs.nmbd = daemonJob "nmbd" " -i -F";
end script
jobAttrs.smbd = daemonJob "smbd" " -i -F";
respawn sleep 1000000 # !!! hack
jobAttrs.winbindd = daemonJob "winbindd" " -F";
# put the store path here so that daemons are restarted when configuration changes
# config is ${configFile}
'';
}
# add -S to get debugging output on stdout
# config directory is passed by configure at compilation time
( daemonJob "nmbd" " -i -F" ) # nmbd says "standard input is not a socket, assuming -D option", but using -i makes it stay in foreground (?)
( daemonJob "smbd" " -i -F" ) # dito
( daemonJob "winbindd" " -F" )
];
}; };
} }

View File

@ -1,86 +1,18 @@
# Avahi daemon. # Avahi daemon.
{pkgs, config, ...}: { config, pkgs, ... }:
with pkgs.lib;
###### interface
let let
inherit (pkgs.lib) mkOption;
options = {
services = {
avahi = {
enable = mkOption {
default = false;
description = ''
Whether to run the Avahi daemon, which allows Avahi clients
to use Avahi's service discovery facilities and also allows
the local machine to advertise its presence and services
(through the mDNS responder implemented by `avahi-daemon').
'';
};
hostName = mkOption {
default = config.networking.hostName;
description = ''Host name advertised on the LAN.'';
};
browseDomains = mkOption {
default = [ "0pointer.de" "zeroconf.org" ];
description = ''
List of non-local DNS domains to be browsed.
'';
};
ipv4 = mkOption {
default = true;
description = ''Whether to use IPv4'';
};
ipv6 = mkOption {
default = false;
description = ''Whether to use IPv6'';
};
wideArea = mkOption {
default = true;
description = ''Whether to enable wide-area service discovery.'';
};
publishing = mkOption {
default = true;
description = ''Whether to allow publishing.'';
};
nssmdns = mkOption {
default = false;
description = ''
Whether to enable the mDNS NSS (Name Service Switch) plug-in.
Enabling it allows applications to resolve names in the `.local'
domain by transparently querying the Avahi daemon.
Warning: Currently, enabling this option breaks DNS lookups after
a `nixos-rebuild'. This is because `/etc/nsswitch.conf' is
updated to use `nss-mdns' but `libnss_mdns' is not in
applications' `LD_LIBRARY_PATH'. The next time `/etc/profile' is
sourced, it will set up an appropriate `LD_LIBRARY_PATH', though.
'';
};
};
};
};
in
###### implementation
let
cfg = config.services.avahi; cfg = config.services.avahi;
inherit (pkgs.lib) mkIf mkThenElse;
inherit (pkgs) avahi writeText lib; inherit (pkgs) avahi;
avahiDaemonConf = with cfg; writeText "avahi-daemon.conf" '' avahiDaemonConf = with cfg; pkgs.writeText "avahi-daemon.conf" ''
[server] [server]
host-name=${hostName} host-name=${hostName}
browse-domains=${lib.concatStringsSep ", " browseDomains} browse-domains=${concatStringsSep ", " browseDomains}
use-ipv4=${if ipv4 then "yes" else "no"} use-ipv4=${if ipv4 then "yes" else "no"}
use-ipv6=${if ipv6 then "yes" else "no"} use-ipv6=${if ipv6 then "yes" else "no"}
@ -91,69 +23,119 @@ let
disable-publishing=${if publishing then "no" else "yes"} disable-publishing=${if publishing then "no" else "yes"}
''; '';
user = {
name = "avahi";
uid = config.ids.uids.avahi;
description = "`avahi-daemon' privilege separation user";
home = "/var/empty";
};
group = {
name = "avahi";
gid = config.ids.gids.avahi;
};
job = {
name = "avahi-daemon";
job = ''
start on network-interfaces/started
stop on network-interfaces/stop
respawn
script
export PATH="${avahi}/bin:${avahi}/sbin:$PATH"
# Make NSS modules visible so that `avahi_nss_support ()' can
# return a sensible value.
export LD_LIBRARY_PATH="${config.system.nssModules.path}"
exec ${avahi}/sbin/avahi-daemon --daemonize -f "${avahiDaemonConf}"
end script
'';
};
in in
mkIf cfg.enable { {
require = [
# ../upstart-jobs/default.nix # config.services.extraJobs
# ../system/? # system.nssModules
# ? # config.environment.etc
# ../system/user.nix # users.*
# ../upstart-jobs/udev.nix # services.udev.*
# ../upstart-jobs/dbus.nix # services.dbus.*
# ? # config.environment.extraPackages
options
];
system = { ###### interface
nssModules = pkgs.lib.optional cfg.nssmdns pkgs.nssmdns;
};
environment = { options = {
systemPackages = [avahi];
}; services.avahi = {
users = { enable = mkOption {
extraUsers = [user]; default = false;
extraGroups = [group]; description = ''
}; Whether to run the Avahi daemon, which allows Avahi clients
to use Avahi's service discovery facilities and also allows
the local machine to advertise its presence and services
(through the mDNS responder implemented by `avahi-daemon').
'';
};
services = { hostName = mkOption {
extraJobs = [job]; default = config.networking.hostName;
description = ''Host name advertised on the LAN.'';
};
dbus = { browseDomains = mkOption {
enable = true; default = [ "0pointer.de" "zeroconf.org" ];
packages = [avahi]; description = ''
List of non-local DNS domains to be browsed.
'';
};
ipv4 = mkOption {
default = true;
description = ''Whether to use IPv4'';
};
ipv6 = mkOption {
default = false;
description = ''Whether to use IPv6'';
};
wideArea = mkOption {
default = true;
description = ''Whether to enable wide-area service discovery.'';
};
publishing = mkOption {
default = true;
description = ''Whether to allow publishing.'';
};
nssmdns = mkOption {
default = false;
description = ''
Whether to enable the mDNS NSS (Name Service Switch) plug-in.
Enabling it allows applications to resolve names in the `.local'
domain by transparently querying the Avahi daemon.
Warning: Currently, enabling this option breaks DNS lookups after
a `nixos-rebuild'. This is because `/etc/nsswitch.conf' is
updated to use `nss-mdns' but `libnss_mdns' is not in
applications' `LD_LIBRARY_PATH'. The next time `/etc/profile' is
sourced, it will set up an appropriate `LD_LIBRARY_PATH', though.
'';
};
}; };
}; };
###### implementation
config = mkIf cfg.enable {
users.extraUsers = singleton
{ name = "avahi";
uid = config.ids.uids.avahi;
description = "`avahi-daemon' privilege separation user";
home = "/var/empty";
};
users.extraGroups = singleton
{ name = "avahi";
gid = config.ids.gids.avahi;
};
system.nssModules = optional cfg.nssmdns pkgs.nssmdns;
environment.systemPackages = [ avahi ];
jobAttrs.avahi_daemon =
{ name = "avahi-daemon";
startOn = "network-interfaces/started";
stopOn = "network-interfaces/stop";
script =
''
export PATH="${avahi}/bin:${avahi}/sbin:$PATH"
# Make NSS modules visible so that `avahi_nss_support ()' can
# return a sensible value.
export LD_LIBRARY_PATH="${config.system.nssModules.path}"
exec ${avahi}/sbin/avahi-daemon --daemonize -f "${avahiDaemonConf}"
'';
};
services.dbus.enable = true;
services.dbus.packages = [avahi];
};
} }

View File

@ -1,123 +1,121 @@
{pkgs, config, ...}: { config, pkgs, ... }:
with pkgs.lib;
###### interface
let let
inherit (pkgs.lib) mkOption mkIf;
startingDependency = if config.services.gw6c.enable then "gw6c" else "network-interfaces";
cfg = config.services.bind;
confFile = pkgs.writeText "named.conf"
''
acl cachenetworks { ${concatMapStrings (entry: " ${entry}; ") cfg.cacheNetworks} };
acl badnetworks { ${concatMapStrings (entry: " ${entry}; ") cfg.blockedNetworks} };
options {
listen-on {any;};
listen-on-v6 {any;};
allow-query { cachenetworks; };
blackhole { badnetworks; };
forward first;
forwarders { ${concatMapStrings (entry: " ${entry}; ") config.networking.nameservers} };
directory "/var/run/named";
pid-file "/var/run/named/named.pid";
};
${ concatMapStrings
({ name, file, master ? true, slaves ? [], masters ? [] }:
''
zone "${name}" {
type ${if master then "master" else "slave"};
file "${file}";
${ if master then
''
allow-transfer {
${concatMapStrings (ip: "${ip};\n") slaves}
};
''
else
''
masters {
${concatMapStrings (ip: "${ip};\n") masters}
};
''
}
allow-query { any; };
};
'')
cfg.zones }
'';
in
{
###### interface
options = { options = {
services = {
bind = { services.bind = {
enable = mkOption {
default = false; enable = mkOption {
description = " default = false;
Whether to enable BIND domain name server. description = "
"; Whether to enable BIND domain name server.
}; ";
cacheNetworks = mkOption {
default = ["127.0.0.0/24"];
description = "
What networks are allowed to use us as a resolver.
";
};
blockedNetworks = mkOption {
default = [];
description = "
What networks are just blocked.
";
};
zones = mkOption {
default = [];
description = "
List of zones we claim authority over.
master=false means slave server; slaves means addresses
who may request zone transfer.
";
example = [{
name = "example.com";
master = false;
file = "/var/dns/example.com";
masters = ["192.168.0.1"];
slaves = [];
}];
};
}; };
};
}; cacheNetworks = mkOption {
in default = ["127.0.0.0/24"];
description = "
###### implementation What networks are allowed to use us as a resolver.
";
let };
startingDependency = if config.services.gw6c.enable then "gw6c" else "network-interfaces";
cfg = config.services.bind; blockedNetworks = mkOption {
concatMapStrings = pkgs.lib.concatMapStrings; default = [];
description = "
namedConf = What networks are just blocked.
('' ";
acl cachenetworks { ${concatMapStrings (entry: " ${entry}; ") cfg.cacheNetworks} }; };
acl badnetworks { ${concatMapStrings (entry: " ${entry}; ") cfg.blockedNetworks} };
zones = mkOption {
options { default = [];
listen-on {any;}; description = "
listen-on-v6 {any;}; List of zones we claim authority over.
allow-query { cachenetworks; }; master=false means slave server; slaves means addresses
blackhole { badnetworks; }; who may request zone transfer.
forward first; ";
forwarders { ${concatMapStrings (entry: " ${entry}; ") config.networking.nameservers} }; example = [{
directory "/var/run/named"; name = "example.com";
pid-file "/var/run/named/named.pid"; master = false;
file = "/var/dns/example.com";
masters = ["192.168.0.1"];
slaves = [];
}];
};
}; };
'')
+
(concatMapStrings
(_entry:let entry={master=true;slaves=[];masters=[];}//_entry; in
''
zone "${entry.name}" {
type ${if entry.master then "master" else "slave"};
file "${entry.file}";
${ if entry.master then
''
allow-transfer {
${concatMapStrings (ip: ip+";\n") entry.slaves}
};
''
else
''
masters {
${concatMapStrings (ip: ip+";\n") entry.masters}
};
''
}
allow-query { any; };
};
''
)
cfg.zones
)
;
confFile = pkgs.writeText "named.conf" namedConf;
in
mkIf config.services.bind.enable {
require = [
options
];
services = {
extraJobs = [{
name = "bind";
job = ''
description "BIND name server job"
start script
${pkgs.coreutils}/bin/mkdir -p /var/run/named
end script
respawn ${pkgs.bind}/sbin/named -c ${confFile} -f
'';
}];
}; };
###### implementation
config = mkIf config.services.bind.enable {
jobAttrs.bind =
{ description = "BIND name server job";
preStart =
''
${pkgs.coreutils}/bin/mkdir -p /var/run/named
'';
exec = "${pkgs.bind}/sbin/named -c ${confFile} -f";
};
};
} }

View File

@ -1,91 +1,93 @@
{pkgs, config, ...}: { config, pkgs, ... }:
with pkgs.lib;
###### interface
let let
inherit (pkgs.lib) mkOption mkIf;
bitlbeeUid = config.ids.uids.bitlbee;
inherit (config.services.bitlbee) portNumber interface;
in
{
###### interface
options = { options = {
services = {
bitlbee = { services.bitlbee = {
enable = mkOption {
default = false;
description = ''
Whether to run the BitlBee IRC to other chat network gateway.
Running it allows you to access the MSN, Jabber, Yahoo! and ICQ chat
networks via an IRC client.
'';
};
interface = mkOption {
default = "127.0.0.1";
description = ''
The interface the BitlBee deamon will be listening to. If `127.0.0.1',
only clients on the local host can connect to it; if `0.0.0.0', clients
can access it from any network interface.
'';
};
portNumber = mkOption {
default = 6667;
description = ''
Number of the port BitlBee will be listening to.
'';
};
enable = mkOption {
default = false;
description = ''
Whether to run the BitlBee IRC to other chat network gateway.
Running it allows you to access the MSN, Jabber, Yahoo! and ICQ chat
networks via an IRC client.
'';
}; };
interface = mkOption {
default = "127.0.0.1";
description = ''
The interface the BitlBee deamon will be listening to. If `127.0.0.1',
only clients on the local host can connect to it; if `0.0.0.0', clients
can access it from any network interface.
'';
};
portNumber = mkOption {
default = 6667;
description = ''
Number of the port BitlBee will be listening to.
'';
};
}; };
}; };
in
###### implementation ###### implementation
let config = mkIf config.services.bitlbee.enable {
bitlbeeUid = config.ids.uids.bitlbee;
inherit (config.services.bitlbee) portNumber interface;
in
mkIf config.services.bitlbee.enable { users.extraUsers = singleton
require = options;
users = {
extraUsers = [
{ name = "bitlbee"; { name = "bitlbee";
uid = bitlbeeUid; uid = bitlbeeUid;
description = "BitlBee user"; description = "BitlBee user";
home = "/var/empty"; home = "/var/empty";
} };
];
extraGroups = [ users.extraGroups = singleton
{ name = "bitlbee"; { name = "bitlbee";
gid = config.ids.gids.bitlbee; gid = config.ids.gids.bitlbee;
} };
];
};
services.extraJobs = [{ jobAttrs.bitlbee =
name = "bitlbee"; { description = "BitlBee IRC to other chat networks gateway";
job = '' startOn = "network-interfaces/started";
description "BitlBee IRC to other chat networks gateway" stopOn = "network-interfaces/stop";
start on network-interfaces/started preStart =
stop on network-interfaces/stop ''
if ! test -d /var/lib/bitlbee
then
mkdir -p /var/lib/bitlbee
chown bitlbee:bitlbee /var/lib/bitlbee
fi
'';
start script exec =
if ! test -d /var/lib/bitlbee ''
then ${pkgs.bitlbee}/sbin/bitlbee -F -p ${toString portNumber} \
mkdir -p /var/lib/bitlbee
chown bitlbee:bitlbee /var/lib/bitlbee
fi
end script
respawn ${pkgs.bitlbee}/sbin/bitlbee -F -p ${toString portNumber} \
-i ${interface} -u bitlbee -i ${interface} -u bitlbee
''; '';
}]; };
environment.systemPackages = [ pkgs.bitlbee ]; environment.systemPackages = [ pkgs.bitlbee ];
};
} }

View File

@ -1,79 +1,6 @@
{pkgs, config, ...}: { config, pkgs, ... }:
###### interface with pkgs.lib;
let
inherit (pkgs.lib) mkOption mkIf;
options = {
services = {
dhcpd = {
enable = mkOption {
default = false;
description = "
Whether to enable the DHCP server.
";
};
extraConfig = mkOption {
default = "";
example = "
option subnet-mask 255.255.255.0;
option broadcast-address 192.168.1.255;
option routers 192.168.1.5;
option domain-name-servers 130.161.158.4, 130.161.33.17, 130.161.180.1;
option domain-name \"example.org\";
subnet 192.168.1.0 netmask 255.255.255.0 {
range 192.168.1.100 192.168.1.200;
}
";
description = "
Extra text to be appended to the DHCP server configuration
file. Currently, you almost certainly need to specify
something here, such as the options specifying the subnet
mask, DNS servers, etc.
";
};
configFile = mkOption {
default = null;
description = "
The path of the DHCP server configuration file. If no file
is specified, a file is generated using the other options.
";
};
interfaces = mkOption {
default = ["eth0"];
description = "
The interfaces on which the DHCP server should listen.
";
};
machines = mkOption {
default = [];
example = [
{ hostName = "foo";
ethernetAddress = "00:16:76:9a:32:1d";
ipAddress = "192.168.1.10";
}
{ hostName = "bar";
ethernetAddress = "00:19:d1:1d:c4:9a";
ipAddress = "192.168.1.11";
}
];
description = "
A list mapping ethernet addresses to IP addresses for the
DHCP server.
";
};
};
};
};
in
###### implementation
let let
@ -81,43 +8,114 @@ let
stateDir = "/var/lib/dhcp"; # Don't use /var/state/dhcp; not FHS-compliant. stateDir = "/var/lib/dhcp"; # Don't use /var/state/dhcp; not FHS-compliant.
machines = pkgs.lib.concatMapStrings (machine: '' configFile = if cfg.configFile != null then cfg.configFile else pkgs.writeText "dhcpd.conf"
host ${machine.hostName} { ''
hardware ethernet ${machine.ethernetAddress}; default-lease-time 600;
fixed-address ${machine.ipAddress}; max-lease-time 7200;
} authoritative;
'') cfg.machines; ddns-update-style ad-hoc;
log-facility local1; # see dhcpd.nix
${cfg.extraConfig}
configFile = if cfg.configFile != null then cfg.configFile else pkgs.writeText "dhcpd.conf" '' ${pkgs.lib.concatMapStrings
default-lease-time 600; (machine: ''
max-lease-time 7200; host ${machine.hostName} {
authoritative; hardware ethernet ${machine.ethernetAddress};
ddns-update-style ad-hoc; fixed-address ${machine.ipAddress};
log-facility local1; # see dhcpd.nix }
${cfg.extraConfig} '')
${machines} cfg.machines
''; }
'';
in in
{
mkIf config.services.dhcpd.enable { ###### interface
require = [
options
];
services = { options = {
extraJobs = [{
name = "dhcpd"; services.dhcpd = {
job = ''
description "DHCP server"
start on network-interfaces/started enable = mkOption {
stop on network-interfaces/stop default = false;
description = "
Whether to enable the DHCP server.
";
};
script extraConfig = mkOption {
default = "";
example = "
option subnet-mask 255.255.255.0;
option broadcast-address 192.168.1.255;
option routers 192.168.1.5;
option domain-name-servers 130.161.158.4, 130.161.33.17, 130.161.180.1;
option domain-name \"example.org\";
subnet 192.168.1.0 netmask 255.255.255.0 {
range 192.168.1.100 192.168.1.200;
}
";
description = "
Extra text to be appended to the DHCP server configuration
file. Currently, you almost certainly need to specify
something here, such as the options specifying the subnet
mask, DNS servers, etc.
";
};
configFile = mkOption {
default = null;
description = "
The path of the DHCP server configuration file. If no file
is specified, a file is generated using the other options.
";
};
interfaces = mkOption {
default = ["eth0"];
description = "
The interfaces on which the DHCP server should listen.
";
};
machines = mkOption {
default = [];
example = [
{ hostName = "foo";
ethernetAddress = "00:16:76:9a:32:1d";
ipAddress = "192.168.1.10";
}
{ hostName = "bar";
ethernetAddress = "00:19:d1:1d:c4:9a";
ipAddress = "192.168.1.11";
}
];
description = "
A list mapping ethernet addresses to IP addresses for the
DHCP server.
";
};
};
};
###### implementation
config = mkIf config.services.dhcpd.enable {
jobAttrs.dhcpd =
{ description = "DHCP server";
startOn = "network-interfaces/started";
stopOn = "network-interfaces/stop";
script =
''
mkdir -m 755 -p ${stateDir} mkdir -m 755 -p ${stateDir}
touch ${stateDir}/dhcpd.leases touch ${stateDir}/dhcpd.leases
@ -125,9 +123,9 @@ mkIf config.services.dhcpd.enable {
exec ${pkgs.dhcp}/sbin/dhcpd -f -cf ${configFile} \ exec ${pkgs.dhcp}/sbin/dhcpd -f -cf ${configFile} \
-lf ${stateDir}/dhcpd.leases \ -lf ${stateDir}/dhcpd.leases \
${toString cfg.interfaces} ${toString cfg.interfaces}
'';
};
end script
'';
}];
}; };
} }

View File

@ -1,85 +1,83 @@
{pkgs, config, ...}: { config, pkgs, ... }:
with pkgs.lib;
###### interface
let let
inherit (pkgs.lib) mkOption mkIf;
cfg = config.services.ejabberd;
in
{
###### interface
options = { options = {
services = {
ejabberd = { services.ejabberd = {
enable = mkOption {
default = false; enable = mkOption {
description = "Whether to enable ejabberd server"; default = false;
}; description = "Whether to enable ejabberd server";
spoolDir = mkOption {
default = "/var/lib/ejabberd";
description = "Location of the spooldir of ejabberd";
};
logsDir = mkOption {
default = "/var/log/ejabberd";
description = "Location of the logfile directory of ejabberd";
};
confDir = mkOption {
default = "/var/ejabberd";
description = "Location of the config directory of ejabberd";
};
virtualHosts = mkOption {
default = "\"localhost\"";
description = "Virtualhosts that ejabberd should host. Hostnames are surrounded with doublequotes and separated by commas";
};
}; };
spoolDir = mkOption {
default = "/var/lib/ejabberd";
description = "Location of the spooldir of ejabberd";
};
logsDir = mkOption {
default = "/var/log/ejabberd";
description = "Location of the logfile directory of ejabberd";
};
confDir = mkOption {
default = "/var/ejabberd";
description = "Location of the config directory of ejabberd";
};
virtualHosts = mkOption {
default = "\"localhost\"";
description = "Virtualhosts that ejabberd should host. Hostnames are surrounded with doublequotes and separated by commas";
};
}; };
}; };
in
###### implementation ###### implementation
let config = mkIf cfg.enable {
cfg = config.services.ejabberd; jobAttrs.ejabberd =
{ description = "EJabberd server";
in startOn = "network-interface/started";
stopOn = "network-interfaces/stop";
mkIf config.services.ejabberd.enable { preStart =
''
# Initialise state data
mkdir -p ${cfg.logsDir}
require = [ if ! test -d ${cfg.spoolDir}
options then
]; cp -av ${pkgs.ejabberd}/var/lib/ejabberd /var/lib
fi
mkdir -p ${cfg.confDir}
test -f ${cfg.confDir}/ejabberd.cfg || sed -e 's|{hosts, \["localhost"\]}.|{hosts, \[${cfg.virtualHosts}\]}.|' ${pkgs.ejabberd}/etc/ejabberd/ejabberd.cfg > ${cfg.confDir}/ejabberd.cfg
'';
services = { exec = "${pkgs.bash}/bin/sh -c 'export PATH=$PATH:${pkgs.ejabberd}/sbin:${pkgs.coreutils}/bin:${pkgs.bash}/bin; cd ~; ejabberdctl --logs ${cfg.logsDir} --spool ${cfg.spoolDir} --config ${cfg.confDir}/ejabberd.cfg start; sleep 1d'";
extraJobs = [{
name = "ejabberd";
job = ''
description "EJabberd server"
start on network-interface/started postStop =
stop on network-interfaces/stop ''
start script
# Initialise state data
mkdir -p ${cfg.logsDir}
if ! test -d ${cfg.spoolDir}
then
cp -av ${pkgs.ejabberd}/var/lib/ejabberd /var/lib
fi
mkdir -p ${cfg.confDir}
test -f ${cfg.confDir}/ejabberd.cfg || sed -e 's|{hosts, \["localhost"\]}.|{hosts, \[${cfg.virtualHosts}\]}.|' ${pkgs.ejabberd}/etc/ejabberd/ejabberd.cfg > ${cfg.confDir}/ejabberd.cfg
end script
respawn ${pkgs.bash}/bin/sh -c 'export PATH=$PATH:${pkgs.ejabberd}/sbin:${pkgs.coreutils}/bin:${pkgs.bash}/bin; cd ~; ejabberdctl --logs ${cfg.logsDir} --spool ${cfg.spoolDir} --config ${cfg.confDir}/ejabberd.cfg start; sleep 1d'
stop script
${pkgs.ejabberd}/sbin/ejabberdctl stop ${pkgs.ejabberd}/sbin/ejabberdctl stop
end script '';
''; };
}];
}; };
} }

View File

@ -1,218 +1,218 @@
{pkgs, config, ...}: { config, pkgs, ... }:
with pkgs.lib;
###### interface
let let
inherit (pkgs.lib) mkOption mkIf;
cfg = config.services.gnunet;
configFile = with cfg; pkgs.writeText "gnunetd.conf"
''
[PATHS]
GNUNETD_HOME = ${home}
[GNUNETD]
HOSTLISTURL = ${lib.concatStringsSep " " hostLists}
APPLICATIONS = ${lib.concatStringsSep " " applications}
TRANSPORTS = ${lib.concatStringsSep " " transports}
[LOAD]
MAXNETDOWNBPSTOTAL = ${toString load.maxNetDownBandwidth}
MAXNETUPBPSTOTAL = ${toString load.maxNetUpBandwidth}
HARDUPLIMIT = ${toString load.hardNetUpBandwidth}
MAXCPULOAD = ${toString load.maxCPULoad}
INTERFACES = ${lib.concatStringsSep " " load.interfaces}
[FS]
QUOTA = ${toString fileSharing.quota}
ACTIVEMIGRATION = ${if fileSharing.activeMigration then "YES" else "NO"}
[MODULES]
sqstore = sqstore_sqlite
dstore = dstore_sqlite
topology = topology_default
${extraOptions}
'';
in
{
###### interface
options = { options = {
services = {
gnunet = { services.gnunet = {
enable = mkOption { enable = mkOption {
default = false;
description = ''
Whether to run the GNUnet daemon. GNUnet is GNU's anonymous
peer-to-peer communication and file sharing framework.
'';
};
home = mkOption {
default = "/var/lib/gnunet";
description = ''
Directory where the GNUnet daemon will store its data.
'';
};
debug = mkOption {
default = false;
description = ''
When true, run in debug mode; gnunetd will not daemonize and
error messages will be written to stderr instead of a
logfile.
'';
};
logLevel = mkOption {
default = "ERROR";
example = "INFO";
description = ''
Log level of the deamon (see `gnunetd(1)' for details).
'';
};
hostLists = mkOption {
default = [
"http://gnunet.org/hostlist.php"
"http://gnunet.mine.nu:8081/hostlist"
"http://vserver1236.vserver-on.de/hostlist-074"
];
description = ''
URLs of host lists.
'';
};
applications = mkOption {
default = [ "advertising" "getoption" "fs" "stats" "traffic" ];
example = [ "chat" "fs" ];
description = ''
List of GNUnet applications supported by the daemon. Note that
`fs', which means "file sharing", is probably the one you want.
'';
};
transports = mkOption {
default = [ "udp" "tcp" "http" "nat" ];
example = [ "smtp" "http" ];
description = ''
List of transport methods used by the server.
'';
};
fileSharing = {
quota = mkOption {
default = 1024;
description = ''
Maximum file system usage (in MiB) for file sharing.
'';
};
activeMigration = mkOption {
default = false; default = false;
description = '' description = ''
Whether to run the GNUnet daemon. GNUnet is GNU's anonymous Whether to allow active migration of content originating
peer-to-peer communication and file sharing framework. from other nodes.
'';
};
home = mkOption {
default = "/var/lib/gnunet";
description = ''
Directory where the GNUnet daemon will store its data.
'';
};
debug = mkOption {
default = false;
description = ''
When true, run in debug mode; gnunetd will not daemonize and
error messages will be written to stderr instead of a
logfile.
'';
};
logLevel = mkOption {
default = "ERROR";
example = "INFO";
description = ''
Log level of the deamon (see `gnunetd(1)' for details).
'';
};
hostLists = mkOption {
default = [
"http://gnunet.org/hostlist.php"
"http://gnunet.mine.nu:8081/hostlist"
"http://vserver1236.vserver-on.de/hostlist-074"
];
description = ''
URLs of host lists.
'';
};
applications = mkOption {
default = [ "advertising" "getoption" "fs" "stats" "traffic" ];
example = [ "chat" "fs" ];
description = ''
List of GNUnet applications supported by the daemon. Note that
`fs', which means "file sharing", is probably the one you want.
'';
};
transports = mkOption {
default = [ "udp" "tcp" "http" "nat" ];
example = [ "smtp" "http" ];
description = ''
List of transport methods used by the server.
'';
};
fileSharing = {
quota = mkOption {
default = 1024;
description = ''
Maximum file system usage (in MiB) for file sharing.
'';
};
activeMigration = mkOption {
default = false;
description = ''
Whether to allow active migration of content originating
from other nodes.
'';
};
};
load = {
maxNetDownBandwidth = mkOption {
default = 50000;
description = ''
Maximum bandwidth usage (in bits per second) for GNUnet
when downloading data.
'';
};
maxNetUpBandwidth = mkOption {
default = 50000;
description = ''
Maximum bandwidth usage (in bits per second) for GNUnet
when downloading data.
'';
};
hardNetUpBandwidth = mkOption {
default = 0;
description = ''
Hard bandwidth limit (in bits per second) when uploading
data.
'';
};
maxCPULoad = mkOption {
default = 100;
description = ''
Maximum CPU load (percentage) authorized for the GNUnet
daemon.
'';
};
interfaces = mkOption {
default = [ "eth0" ];
example = [ "wlan0" "eth1" ];
description = ''
List of network interfaces to use.
'';
};
};
extraOptions = mkOption {
default = "";
example = ''
[NETWORK]
INTERFACE = eth3
'';
description = ''
Additional options that will be copied verbatim in `gnunetd.conf'.
See `gnunetd.conf(5)' for details.
''; '';
}; };
}; };
load = {
maxNetDownBandwidth = mkOption {
default = 50000;
description = ''
Maximum bandwidth usage (in bits per second) for GNUnet
when downloading data.
'';
};
maxNetUpBandwidth = mkOption {
default = 50000;
description = ''
Maximum bandwidth usage (in bits per second) for GNUnet
when downloading data.
'';
};
hardNetUpBandwidth = mkOption {
default = 0;
description = ''
Hard bandwidth limit (in bits per second) when uploading
data.
'';
};
maxCPULoad = mkOption {
default = 100;
description = ''
Maximum CPU load (percentage) authorized for the GNUnet
daemon.
'';
};
interfaces = mkOption {
default = [ "eth0" ];
example = [ "wlan0" "eth1" ];
description = ''
List of network interfaces to use.
'';
};
};
extraOptions = mkOption {
default = "";
example = ''
[NETWORK]
INTERFACE = eth3
'';
description = ''
Additional options that will be copied verbatim in `gnunetd.conf'.
See `gnunetd.conf(5)' for details.
'';
};
}; };
}; };
in
###### implementation
mkIf config.services.gnunet.enable { ###### implementation
require = [
options
];
users = { config = mkIf config.services.gnunet.enable {
extraUsers = [
users.extraUsers = singleton
{ name = "gnunetd"; { name = "gnunetd";
uid = config.ids.uids.gnunetd; uid = config.ids.uids.gnunetd;
description = "GNUnet Daemon User"; description = "GNUnet Daemon User";
home = "/var/empty"; home = "/var/empty";
} };
];
};
services = { jobAttrs.gnunetd =
extraJobs = [{ { description = "The GNUnet Daemon";
name = "gnunetd";
job = startOn = "network-interfaces/started";
with config.services.gnunet; stopOn = "network-interfaces/stop";
let
inherit (pkgs) lib gnunet;
configFile = pkgs.writeText "gnunetd.conf" ''
[PATHS]
GNUNETD_HOME = ${home}
[GNUNETD] preStart =
HOSTLISTURL = ${lib.concatStringsSep " " hostLists} ''
APPLICATIONS = ${lib.concatStringsSep " " applications} test -d "${cfg.home}" || \
TRANSPORTS = ${lib.concatStringsSep " " transports} ( mkdir -m 755 -p "${cfg.home}" && chown -R gnunetd:users "${cfg.home}")
'';
[LOAD] exec =
MAXNETDOWNBPSTOTAL = ${toString load.maxNetDownBandwidth} ''
MAXNETUPBPSTOTAL = ${toString load.maxNetUpBandwidth} respawn ${pkgs.gnunet}/bin/gnunetd \
HARDUPLIMIT = ${toString load.hardNetUpBandwidth}
MAXCPULOAD = ${toString load.maxCPULoad}
INTERFACES = ${lib.concatStringsSep " " load.interfaces}
[FS]
QUOTA = ${toString fileSharing.quota}
ACTIVEMIGRATION = ${if fileSharing.activeMigration then "YES" else "NO"}
[MODULES]
sqstore = sqstore_sqlite
dstore = dstore_sqlite
topology = topology_default
${extraOptions}
'';
in ''
description "The GNUnet Daemon"
start on network-interfaces/started
stop on network-interfaces/stop
start script
test -d "${home}" || \
( mkdir -m 755 -p "${home}" && chown -R gnunetd:users "${home}")
end script
respawn ${gnunet}/bin/gnunetd \
${if debug then "--debug" else "" } \ ${if debug then "--debug" else "" } \
--user="gnunetd" \ --user="gnunetd" \
--config="${configFile}" \ --config="${configFile}" \
--log="${logLevel}" --log="${cfg.logLevel}"
''; '';
}]; };
}; };
} }

View File

@ -1,141 +1,143 @@
{servicesPath, pkgs, config, ...}: { config, pkgs, servicesPath, ... }:
with pkgs.lib;
###### interface
let let
inherit (pkgs.lib) mkOption mkIf;
cfg = config.services.gw6c;
gw6cService = import (servicesPath + /gw6c) {
inherit (pkgs) stdenv gw6c coreutils
procps upstart iputils gnused
gnugrep seccure writeScript;
username = cfg.username;
password = cfg.password;
server = cfg.server;
keepAlive = cfg.keepAlive;
everPing = cfg.everPing;
seccureKeys = config.security.seccureKeys;
waitPingableBroker = cfg.waitPingableBroker;
};
in
{
###### interface
options = { options = {
services = {
gw6c = { services.gw6c = {
enable = mkOption {
default = false; enable = mkOption {
description = " default = false;
Whether to enable Gateway6 client (IPv6 tunnel). description = "
"; Whether to enable Gateway6 client (IPv6 tunnel).
}; ";
autorun = mkOption {
default = true;
description = "
Switch to false to create upstart-job and configuration,
but not run it automatically
";
};
username = mkOption {
default = "";
description = "
Your Gateway6 login name, if any.
";
};
password = mkOption {
default = "";
description = "
Your Gateway6 password, if any.
";
};
server = mkOption {
default = "anon.freenet6.net";
example = "broker.freenet6.net";
description = "
Used Gateway6 server.
";
};
keepAlive = mkOption {
default = "30";
example = "2";
description = "
Gateway6 keep-alive period.
";
};
everPing = mkOption {
default = "1000000";
example = "2";
description = "
Gateway6 manual ping period.
";
};
waitPingableBroker = mkOption {
default = true;
example = false;
description = "
Whether to wait until tunnel broker returns ICMP echo.
";
};
}; };
};
security = {
seccureKeys = {
public = mkOption {
default = /var/elliptic-keys/public;
description = "
Public key. Make it path argument, so it is copied into store and
hashed.
The key is used to encrypt Gateway 6 configuration in store, as it autorun = mkOption {
contains a password for external service. Unfortunately, default = true;
derivation file should be protected by other means. For example, description = "
nix-http-export.cgi will happily export any non-derivation path, Switch to false to create upstart-job and configuration,
but not a derivation. but not run it automatically
"; ";
};
private = mkOption {
default = "/var/elliptic-keys/private";
description = "
Private key. Make it string argument, so it is not copied into store.
";
};
}; };
username = mkOption {
default = "";
description = "
Your Gateway6 login name, if any.
";
};
password = mkOption {
default = "";
description = "
Your Gateway6 password, if any.
";
};
server = mkOption {
default = "anon.freenet6.net";
example = "broker.freenet6.net";
description = "
Used Gateway6 server.
";
};
keepAlive = mkOption {
default = "30";
example = "2";
description = "
Gateway6 keep-alive period.
";
};
everPing = mkOption {
default = "1000000";
example = "2";
description = "
Gateway6 manual ping period.
";
};
waitPingableBroker = mkOption {
default = true;
example = false;
description = "
Whether to wait until tunnel broker returns ICMP echo.
";
};
}; };
security.seccureKeys = {
# !!! It's not clear to me (ED) what additional security this
# provides. Passwords shouldn't be in configuration.nix,
# period. You could just place the password in
# /var/blah/password or whatever.
public = mkOption {
default = /var/elliptic-keys/public;
description = "
Public key. Make it path argument, so it is copied into store and
hashed.
The key is used to encrypt Gateway 6 configuration in store, as it
contains a password for external service. Unfortunately,
derivation file should be protected by other means. For example,
nix-http-export.cgi will happily export any non-derivation path,
but not a derivation.
";
};
private = mkOption {
default = "/var/elliptic-keys/private";
description = "
Private key. Make it string argument, so it is not copied into store.
";
};
};
}; };
in
###### implementation ###### implementation
let config = mkIf cfg.enable {
cfg = config.services.gw6c;
procps = pkgs.procps;
gw6cService = import (servicesPath + /gw6c) {
inherit (pkgs) stdenv gw6c coreutils
procps upstart iputils gnused
gnugrep seccure writeScript;
username = cfg.username;
password = cfg.password;
server = cfg.server;
keepAlive = cfg.keepAlive;
everPing = cfg.everPing;
seccureKeys = config.security.seccureKeys; jobAttrs.gw6c =
{ description = "Gateway6 client";
startOn = if cfg.autorun then "network-interfaces/started" else "";
stopOn = "network-interfaces/stop";
waitPingableBroker = cfg.waitPingableBroker; exec = "${gw6cService}/bin/control start";
}; };
in
mkIf config.services.gw6c.enable {
require = [
options
];
services = {
extraJobs = [{
name = "gw6c";
users = [];
groups = [];
job = ''
description \"Gateway6 client\"
start on ${ if cfg.autorun then "network-interfaces/started" else "never" }
stop on network-interfaces/stop
respawn ${gw6cService}/bin/control start
'';
}];
}; };
} }

View File

@ -1,89 +1,11 @@
{servicesPath, pkgs, config, ...}: { config, pkgs, servicesPath, ... }:
###### interface with pkgs.lib;
let
inherit (pkgs.lib) mkOption mkIf;
options = {
services = {
ircdHybrid = {
enable = mkOption {
default = false;
description = "
Enable IRCD.
";
};
serverName = mkOption {
default = "hades.arpa";
description = "
IRCD server name.
";
};
sid = mkOption {
default = "0NL";
description = "
IRCD server unique ID in a net of servers.
";
};
description = mkOption {
default = "Hybrid-7 IRC server.";
description = "
IRCD server description.
";
};
rsaKey = mkOption {
default = null;
example = /root/certificates/irc.key;
description = "
IRCD server RSA key.
";
};
certificate = mkOption {
default = null;
example = /root/certificates/irc.pem;
description = "
IRCD server SSL certificate. There are some limitations - read manual.
";
};
adminEmail = mkOption {
default = "<bit-bucket@example.com>";
example = "<name@domain.tld>";
description = "
IRCD server administrator e-mail.
";
};
extraIPs = mkOption {
default = [];
example = ["127.0.0.1"];
description = "
Extra IP's to bind.
";
};
extraPort = mkOption {
default = "7117";
description = "
Extra port to avoid filtering.
";
};
};
};
};
in
###### implementation
let let
cfg = config.services.ircdHybrid; cfg = config.services.ircdHybrid;
ircdService = import (servicesPath + /ircd-hybrid) { ircdService = import (servicesPath + /ircd-hybrid) {
stdenv = pkgs.stdenv; stdenv = pkgs.stdenv;
inherit (pkgs) ircdHybrid coreutils inherit (pkgs) ircdHybrid coreutils
@ -96,35 +18,116 @@ let
adminEmail = cfg.adminEmail; adminEmail = cfg.adminEmail;
extraIPs = cfg.extraIPs; extraIPs = cfg.extraIPs;
extraPort = cfg.extraPort; extraPort = cfg.extraPort;
gw6cEnabled = (config.services.gw6c.enable) && gw6cEnabled = config.services.gw6c.enable && config.services.gw6c.autorun;
(config.services.gw6c.autorun);
}; };
startingDependency = if config.services.gw6c.enable then "gw6c" else "network-interfaces"; startingDependency = if config.services.gw6c.enable then "gw6c" else "network-interfaces";
in in
mkIf config.services.ircdHybrid.enable { {
require = [
options
];
services = { ###### interface
extraJobs = [{
name = "ircd-hybrid";
users = [ {
name = "ircd";
description = "IRCD owner.";
} ];
groups = [{name = "ircd";}];
job = ''
description = "IRCD Hybrid server."
start on ${startingDependency}/started options = {
stop on ${startingDependency}/stop
services.ircdHybrid = {
enable = mkOption {
default = false;
description = "
Enable IRCD.
";
};
serverName = mkOption {
default = "hades.arpa";
description = "
IRCD server name.
";
};
sid = mkOption {
default = "0NL";
description = "
IRCD server unique ID in a net of servers.
";
};
description = mkOption {
default = "Hybrid-7 IRC server.";
description = "
IRCD server description.
";
};
rsaKey = mkOption {
default = null;
example = /root/certificates/irc.key;
description = "
IRCD server RSA key.
";
};
certificate = mkOption {
default = null;
example = /root/certificates/irc.pem;
description = "
IRCD server SSL certificate. There are some limitations - read manual.
";
};
adminEmail = mkOption {
default = "<bit-bucket@example.com>";
example = "<name@domain.tld>";
description = "
IRCD server administrator e-mail.
";
};
extraIPs = mkOption {
default = [];
example = ["127.0.0.1"];
description = "
Extra IP's to bind.
";
};
extraPort = mkOption {
default = "7117";
description = "
Extra port to avoid filtering.
";
};
};
respawn ${ircdService}/bin/control start
'';
}];
}; };
###### implementation
config = mkIf config.services.ircdHybrid.enable {
users.extraUsers = singleton
{ name = "ircd";
description = "IRCD owner";
};
users.extraGroups = singleton
{ name = "ircd"; };
jobAttrs.ircd_hybrid =
{ # name = "ircd-hybrid"; !!! mkIf bug
description = "IRCD Hybrid server";
startOn = "${startingDependency}/started";
stopOn = "${startingDependency}/stop";
exec = "${ircdService}/bin/control start";
};
};
} }

View File

@ -1,65 +1,62 @@
{pkgs, config, ...}: { config, pkgs, ... }:
###### interface with pkgs.lib;
let
inherit (pkgs.lib) mkOption mkIf;
options = {
services = {
openfire = {
enable = mkOption {
default = false;
description = "
Whether to enable OpenFire XMPP server.
";
};
usePostgreSQL = mkOption {
default = true;
description = "
Whether you use PostgreSQL service for your storage back-end.
";
};
};
};
};
in
###### implementation
let let
inherit (pkgs) jre openfire coreutils which gnugrep gawk gnused; inherit (pkgs) jre openfire coreutils which gnugrep gawk gnused;
startDependency = if config.services.openfire.usePostgreSQL then startDependency =
"postgresql" if config.services.openfire.usePostgreSQL then "postgresql" else
else if config.services.gw6c.enable then "gw6c" else
if config.services.gw6c.enable then "network-interfaces";
"gw6c"
else
"network-interfaces";
in in
mkIf config.services.openfire.enable { {
assertions = [ { ###### interface
assertion = !(config.services.openfire.usePostgreSQL -> config.services.postgresql.enable);
message = "openfire assertion failed";
} ];
require = [ options = {
options
]; services.openfire = {
enable = mkOption {
default = false;
description = "
Whether to enable OpenFire XMPP server.
";
};
usePostgreSQL = mkOption {
default = true;
description = "
Whether you use PostgreSQL service for your storage back-end.
";
};
};
};
services = { ###### implementation
extraJobs = [{
name = "openfire";
job = ''
description "OpenFire XMPP server"
start on ${startDependency}/started config = mkIf config.services.openfire.enable {
stop on shutdown
script assertions = singleton
{ assertion = !(config.services.openfire.usePostgreSQL -> config.services.postgresql.enable);
message = "openfire assertion failed";
};
jobAttrs.openfire =
{ description = "OpenFire XMPP server";
startOn = "${startDependency}/started";
stopOn = "shutdown";
script =
''
export PATH=${jre}/bin:${openfire}/bin:${coreutils}/bin:${which}/bin:${gnugrep}/bin:${gawk}/bin:${gnused}/bin export PATH=${jre}/bin:${openfire}/bin:${coreutils}/bin:${which}/bin:${gnugrep}/bin:${gawk}/bin:${gnused}/bin
export HOME=/tmp export HOME=/tmp
mkdir /var/log/openfire || true mkdir /var/log/openfire || true
@ -70,8 +67,9 @@ mkIf config.services.openfire.enable {
fi fi
done done
openfire start openfire start
end script ''; # */
''; };
}];
}; };
} }

View File

@ -1,83 +1,14 @@
{ config, pkgs, ... }:
{pkgs, config, ...}: with pkgs.lib;
###### interface
let let
inherit (pkgs.lib) mkOption mkIf;
options = {
services = {
openvpn = {
enable = mkOption {
default = false;
description = "
Whether to enable the Secure Shell daemon, which allows secure
remote logins.
";
};
servers = mkOption {
example = [
{
id = "server-simplest";
config = ''
# Most simple configuration: http://openvpn.net/index.php/documentation/miscellaneous/static-key-mini-howto.html.
# server :
dev tun
ifconfig 10.8.0.1 10.8.0.2
secret static.key
'';
up = "ip route add ..!";
down = "ip route add ..!";
}
{
id = "client-simplest";
config = ''
#client:
#remote myremote.mydomain
#dev tun
#ifconfig 10.8.0.2 10.8.0.1
#secret static.key
'';
}
{
id = "server-scalable";
config = ''
multiple clienst
see example file found in http://openvpn.net/index.php/documentation/howto.html
'';
}
{
id = "client-scalabe";
config = '' dito '';
}
];
default = [];
description = ''
openvpn instances to be run. Each will be put into an extra job named openvpn-{id}
The up and down properties will be added config line up=/nix/store/xxx-up-script
automatically for you. If you define at least one of up/down
"script-security 2" will be prepended to your config.
Don't forget to check that the all package sizes can be sent. if scp hangs or such you should set
--fragment XXX --mssfix YYY.
'';
};
};
};
};
modprobe = config.system.sbin.modprobe;
###### implementation
cfg = config.services.openvpn; cfg = config.services.openvpn;
inherit (pkgs) openvpn; inherit (pkgs) openvpn;
inherit (builtins) hasAttr;
PATH="${pkgs.iptables}/sbin:${pkgs.coreutils}/bin:${pkgs.iproute}/sbin:${pkgs.nettools}/sbin"; PATH = "${pkgs.iptables}/sbin:${pkgs.coreutils}/bin:${pkgs.iproute}/sbin:${pkgs.nettools}/sbin";
makeOpenVPNJob = cfg : makeOpenVPNJob = cfg :
let let
@ -93,42 +24,105 @@ let
PATH=${PATH} PATH=${PATH}
${cfg.down} ${cfg.down}
''; '';
configFile = pkgs.writeText "openvpn-config-${cfg.id}" '' configFile = pkgs.writeText "openvpn-config-${cfg.id}"
${if hasAttr "up" cfg || hasAttr "down" cfg then "script-security 2" else ""} ''
${cfg.config} ${if cfg ? up || cfg ? down then "script-security 2" else ""}
${if hasAttr "up" cfg then "up ${pkgs.writeScript "openvpn-${cfg.id}-up" upScript}" else "" } ${cfg.config}
${if hasAttr "down" cfg then "down ${pkgs.writeScript "openvpn-${cfg.id}-down" downScript}" else "" } ${if cfg ? up then "up ${pkgs.writeScript "openvpn-${cfg.id}-up" upScript}" else "" }
''; ${if cfg ? down then "down ${pkgs.writeScript "openvpn-${cfg.id}-down" downScript}" else "" }
'';
in { in {
name = "openvpn-${cfg.id}"; description = "OpenVPN-${cfg.id}";
job = '' startOn = "network-interfaces/started";
description "OpenVPN-${cfg.id}" stopOn = "network-interfaces/stop";
start on network-interfaces/started environment = { PATH = "${pkgs.coreutils}/bin"; };
stop on network-interfaces/stop
script =
PATH=${pkgs.coreutils}/bin ''
respawn
script
exec &> /var/log/openvpn-${cfg.id} exec &> /var/log/openvpn-${cfg.id}
${modprobe} tun || true ${config.system.sbin.modprobe} tun || true
${openvpn}/sbin/openvpn --config ${configFile} ${openvpn}/sbin/openvpn --config ${configFile}
end script '';
'';
}; };
in in
{
###### interface
mkIf cfg.enable { options = {
require = [
options services.openvpn = {
];
enable = mkOption {
default = false;
description = "Whether to enable OpenVPN.";
};
servers = mkOption {
example = [
{
id = "server-simplest";
config = ''
# Most simple configuration: http://openvpn.net/index.php/documentation/miscellaneous/static-key-mini-howto.html.
# server :
dev tun
ifconfig 10.8.0.1 10.8.0.2
secret static.key
'';
up = "ip route add ..!";
down = "ip route add ..!";
}
{
id = "client-simplest";
config = ''
#client:
#remote myremote.mydomain
#dev tun
#ifconfig 10.8.0.2 10.8.0.1
#secret static.key
'';
}
{
id = "server-scalable";
config = ''
multiple clienst
see example file found in http://openvpn.net/index.php/documentation/howto.html
'';
}
{
id = "client-scalabe";
config = '' dito '';
}
];
default = [];
# !!! clean up this description please
description = ''
openvpn instances to be run. Each will be put into an extra job named openvpn-{id}
The up and down properties will be added config line up=/nix/store/xxx-up-script
automatically for you. If you define at least one of up/down
"script-security 2" will be prepended to your config.
Don't forget to check that the all package sizes can be sent. if scp hangs or such you should set
--fragment XXX --mssfix YYY.
'';
};
};
services = {
extraJobs = map makeOpenVPNJob cfg.servers;
}; };
###### implementation
config = mkIf cfg.enable {
jobAttrs = listToAttrs (map (c: nameValuePair "openvpn-${cfg.id}" (makeOpenVPNJob c)) cfg.servers);
};
} }

View File

@ -1,89 +1,84 @@
{pkgs, config, ...}: { config, pkgs, ... }:
with pkgs.lib;
###### interface
let let
inherit (pkgs.lib) mkOption mkIf;
uid = config.ids.uids.portmap;
gid = config.ids.gids.portmap;
portmap = pkgs.portmap.override { daemonUID = uid; daemonGID = gid; };
in
{
###### interface
options = { options = {
services = {
portmap = { services.portmap = {
enable = mkOption {
default = false; enable = mkOption {
description = '' default = false;
Whether to enable `portmap', an ONC RPC directory service description = ''
notably used by NFS and NIS, and which can be queried Whether to enable `portmap', an ONC RPC directory service
using the rpcinfo(1) command. notably used by NFS and NIS, and which can be queried
''; using the rpcinfo(1) command.
}; '';
verbose = mkOption {
default = false;
description = ''
Whether to enable verbose output.
'';
};
chroot = mkOption {
default = "/var/empty";
description = ''
If non-empty, a path to change root to.
'';
};
}; };
verbose = mkOption {
default = false;
description = ''
Whether to enable verbose output.
'';
};
chroot = mkOption {
default = "/var/empty";
description = ''
If non-empty, a path to change root to.
'';
};
}; };
}; };
in
###### implementation ###### implementation
let uid = config.ids.uids.portmap; config = mkIf config.services.portmap.enable {
gid = config.ids.gids.portmap;
in
mkIf config.services.portmap.enable { users.extraUsers = singleton
require = [
options
];
users = {
extraUsers = [
{ name = "portmap"; { name = "portmap";
inherit uid; inherit uid;
description = "portmap daemon user"; description = "portmap daemon user";
home = "/var/empty"; home = "/var/empty";
} };
];
extraGroups = [ users.extraGroups = singleton
{ name = "portmap"; { name = "portmap";
inherit gid; inherit gid;
} };
];
};
services = { jobAttrs.portmap =
extraJobs = [{ { description = "ONC RPC portmap";
name = "portmap";
job = startOn = "network-interfaces/started";
let portmap = pkgs.portmap.override { daemonUID = uid; daemonGID = gid; }; stopOn = "network-interfaces/stop";
in
exec =
'' ''
description "ONC RPC portmap" ${portmap}/sbin/portmap -f \
${if config.services.portmap.chroot == ""
then ""
else "-t \"${config.services.portmap.chroot}\""} \
${if config.services.portmap.verbose then "-v" else ""}
'';
};
start on network-interfaces/started
stop on network-interfaces/stop
respawn ${portmap}/sbin/portmap -f \
${if config.services.portmap.chroot == ""
then ""
else "-t \"${config.services.portmap.chroot}\""} \
${if config.services.portmap.verbose then "-v" else ""}
'';
}];
}; };
} }

View File

@ -1,138 +1,132 @@
{pkgs, config, ...}: { config, pkgs, ... }:
###### interface with pkgs.lib;
let
inherit (pkgs.lib) mkOption mkIf;
options = {
services = {
lshd = {
enable = mkOption {
default = false;
description = ''
Whether to enable the GNU lshd SSH2 daemon, which allows
secure remote login.
'';
};
portNumber = mkOption {
default = 22;
description = ''
The port on which to listen for connections.
'';
};
interfaces = mkOption {
default = [];
description = ''
List of network interfaces where listening for connections.
When providing the empty list, `[]', lshd listens on all
network interfaces.
'';
example = [ "localhost" "1.2.3.4:443" ];
};
hostKey = mkOption {
default = "/etc/lsh/host-key";
description = ''
Path to the server's private key. Note that this key must
have been created, e.g., using "lsh-keygen --server |
lsh-writekey --server", so that you can run lshd.
'';
};
syslog = mkOption {
default = true;
description = ''Whether to enable syslog output.'';
};
passwordAuthentication = mkOption {
default = true;
description = ''Whether to enable password authentication.'';
};
publicKeyAuthentication = mkOption {
default = true;
description = ''Whether to enable public key authentication.'';
};
rootLogin = mkOption {
default = false;
description = ''Whether to enable remote root login.'';
};
loginShell = mkOption {
default = null;
description = ''
If non-null, override the default login shell with the
specified value.
'';
example = "/nix/store/xyz-bash-10.0/bin/bash10";
};
srpKeyExchange = mkOption {
default = false;
description = ''
Whether to enable SRP key exchange and user authentication.
'';
};
tcpForwarding = mkOption {
default = true;
description = ''Whether to enable TCP/IP forwarding.'';
};
x11Forwarding = mkOption {
default = true;
description = ''Whether to enable X11 forwarding.'';
};
subsystems = mkOption {
default = [ ["sftp" "${pkgs.lsh}/sbin/sftp-server"] ];
description = ''
List of subsystem-path pairs, where the head of the pair
denotes the subsystem name, and the tail denotes the path to
an executable implementing it.
'';
};
};
};
};
in
###### implementation
let let
inherit (pkgs) lsh; inherit (pkgs) lsh;
inherit (pkgs.lib) concatStrings concatStringsSep head tail;
lshdConfig = config.services.lshd; cfg = config.services.lshd;
nssModules = config.system.nssModules.list;
nssModulesPath = config.system.nssModules.path;
in in
mkIf config.services.lshd.enable { {
require = [
options
];
services = { ###### interface
extraJobs = [{
name = "lshd"; options = {
services.lshd = {
enable = mkOption {
default = false;
description = ''
Whether to enable the GNU lshd SSH2 daemon, which allows
secure remote login.
'';
};
portNumber = mkOption {
default = 22;
description = ''
The port on which to listen for connections.
'';
};
interfaces = mkOption {
default = [];
description = ''
List of network interfaces where listening for connections.
When providing the empty list, `[]', lshd listens on all
network interfaces.
'';
example = [ "localhost" "1.2.3.4:443" ];
};
hostKey = mkOption {
default = "/etc/lsh/host-key";
description = ''
Path to the server's private key. Note that this key must
have been created, e.g., using "lsh-keygen --server |
lsh-writekey --server", so that you can run lshd.
'';
};
syslog = mkOption {
default = true;
description = ''Whether to enable syslog output.'';
};
passwordAuthentication = mkOption {
default = true;
description = ''Whether to enable password authentication.'';
};
publicKeyAuthentication = mkOption {
default = true;
description = ''Whether to enable public key authentication.'';
};
rootLogin = mkOption {
default = false;
description = ''Whether to enable remote root login.'';
};
loginShell = mkOption {
default = null;
description = ''
If non-null, override the default login shell with the
specified value.
'';
example = "/nix/store/xyz-bash-10.0/bin/bash10";
};
srpKeyExchange = mkOption {
default = false;
description = ''
Whether to enable SRP key exchange and user authentication.
'';
};
tcpForwarding = mkOption {
default = true;
description = ''Whether to enable TCP/IP forwarding.'';
};
x11Forwarding = mkOption {
default = true;
description = ''Whether to enable X11 forwarding.'';
};
subsystems = mkOption {
default = [ ["sftp" "${pkgs.lsh}/sbin/sftp-server"] ];
description = ''
List of subsystem-path pairs, where the head of the pair
denotes the subsystem name, and the tail denotes the path to
an executable implementing it.
'';
};
job = with lshdConfig; '' };
description "GNU lshd SSH2 daemon"
start on network-interfaces/started };
stop on network-interfaces/stop
env LD_LIBRARY_PATH=${nssModulesPath}
start script ###### implementation
config = mkIf cfg.enable {
jobAttrs.lshd =
{ description = "GNU lshd SSH2 daemon";
startOn = "network-interfaces/started";
stopOn = "network-interfaces/stop";
environment =
{ LD_LIBRARY_PATH = config.system.nssModules.path; };
preStart =
''
test -d /etc/lsh || mkdir -m 0755 -p /etc/lsh test -d /etc/lsh || mkdir -m 0755 -p /etc/lsh
test -d /var/spool/lsh || mkdir -m 0755 -p /var/spool/lsh test -d /var/spool/lsh || mkdir -m 0755 -p /var/spool/lsh
@ -144,35 +138,37 @@ mkIf config.services.lshd.enable {
${lsh}/bin/lsh-make-seed -o /var/spool/lsh/yarrow-seed-file ${lsh}/bin/lsh-make-seed -o /var/spool/lsh/yarrow-seed-file
fi fi
if ! test -f "${hostKey}" if ! test -f "${cfg.hostKey}"
then then
${lsh}/bin/lsh-keygen --server | \ ${lsh}/bin/lsh-keygen --server | \
${lsh}/bin/lsh-writekey --server -o "${hostKey}" ${lsh}/bin/lsh-writekey --server -o "${cfg.hostKey}"
fi fi
end script '';
respawn ${lsh}/sbin/lshd --daemonic \ exec = with cfg;
--password-helper="${lsh}/sbin/lsh-pam-checkpw" \ ''
-p ${toString portNumber} \ ${lsh}/sbin/lshd --daemonic \
${if interfaces == [] then "" --password-helper="${lsh}/sbin/lsh-pam-checkpw" \
else (concatStrings (map (i: "--interface=\"${i}\"") -p ${toString portNumber} \
interfaces))} \ ${if interfaces == [] then ""
-h "${hostKey}" \ else (concatStrings (map (i: "--interface=\"${i}\"")
${if !syslog then "--no-syslog" else ""} \ interfaces))} \
${if passwordAuthentication then "--password" else "--no-password" } \ -h "${hostKey}" \
${if publicKeyAuthentication then "--publickey" else "--no-publickey" } \ ${if !syslog then "--no-syslog" else ""} \
${if rootLogin then "--root-login" else "--no-root-login" } \ ${if passwordAuthentication then "--password" else "--no-password" } \
${if loginShell != null then "--login-shell=\"${loginShell}\"" else "" } \ ${if publicKeyAuthentication then "--publickey" else "--no-publickey" } \
${if srpKeyExchange then "--srp-keyexchange" else "--no-srp-keyexchange" } \ ${if rootLogin then "--root-login" else "--no-root-login" } \
${if !tcpForwarding then "--no-tcpip-forward" else "--tcpip-forward"} \ ${if loginShell != null then "--login-shell=\"${loginShell}\"" else "" } \
${if x11Forwarding then "--x11-forward" else "--no-x11-forward" } \ ${if srpKeyExchange then "--srp-keyexchange" else "--no-srp-keyexchange" } \
--subsystems=${concatStringsSep "," ${if !tcpForwarding then "--no-tcpip-forward" else "--tcpip-forward"} \
(map (pair: (head pair) + "=" + ${if x11Forwarding then "--x11-forward" else "--no-x11-forward" } \
(head (tail pair))) --subsystems=${concatStringsSep ","
subsystems)} (map (pair: (head pair) + "=" +
''; (head (tail pair)))
subsystems)}
'';
};
};
}
];
};
} }

View File

@ -1,92 +1,11 @@
{pkgs, config, ...}: { config, pkgs, ... }:
###### interface with pkgs.lib;
let
inherit (pkgs.lib) mkOption mkIf;
options = {
services = {
vsftpd = {
enable = mkOption {
default = false;
description = "
Whether to enable the vsftpd FTP server.
";
};
anonymousUser = mkOption {
default = false;
description = "
Whether to enable the anonymous FTP user.
";
};
anonymousUserHome = mkOption {
default = "/home/ftp";
description = "
Path to anonymous user data.
";
};
localUsers = mkOption {
default = false;
description = "
Whether to enable FTP for the local users.
";
};
writeEnable = mkOption {
default = false;
description = "
Whether any write activity is permitted to users.
";
};
anonymousUploadEnable = mkOption {
default = false;
description = "
Whether any uploads are permitted to anonymous users.
";
};
anonymousMkdirEnable = mkOption {
default = false;
description = "
Whether mkdir is permitted to anonymous users.
";
};
chrootlocalUser = mkOption {
default = false;
description = "
Whether u can like out of ur home dir.
";
};
userlistEnable = mkOption {
default = false;
description = "
Whether users are included.
";
};
userlistDeny = mkOption {
default = false;
description = "
Whether users are excluded.
";
};
};
};
};
in
###### implementation
let let
inherit (config.services.vsftpd) anonymousUser anonymousUserHome localUsers writeEnable anonymousUploadEnable anonymousMkdirEnable cfg = config.services.vsftpd;
chrootlocalUser userlistEnable userlistDeny;
inherit (pkgs) vsftpd; inherit (pkgs) vsftpd;
yesNoOption = p : name : yesNoOption = p : name :
@ -94,67 +13,123 @@ let
in in
mkIf config.services.vsftpd.enable { {
require = [
options
];
users = { ###### interface
extraUsers = [
{ name = "vsftpd"; options = {
services.vsftpd = {
enable = mkOption {
default = false;
description = "Whether to enable the vsftpd FTP server.";
};
anonymousUser = mkOption {
default = false;
description = "Whether to enable the anonymous FTP user.";
};
anonymousUserHome = mkOption {
default = "/home/ftp";
description = "Path to anonymous user data.";
};
localUsers = mkOption {
default = false;
description = "Whether to enable FTP for local users.";
};
writeEnable = mkOption {
default = false;
description = "Whether any write activity is permitted to users.";
};
anonymousUploadEnable = mkOption {
default = false;
description = "Whether any uploads are permitted to anonymous users.";
};
anonymousMkdirEnable = mkOption {
default = false;
description = "Whether mkdir is permitted to anonymous users.";
};
chrootlocalUser = mkOption {
default = false;
description = "Whether local users are confined to their home directory.";
};
userlistEnable = mkOption {
default = false;
description = "Whether users are included.";
};
userlistDeny = mkOption {
default = false;
description = "Whether users are excluded.";
};
};
};
###### implementation
config = mkIf cfg.enable {
users.extraUsers =
[ { name = "vsftpd";
uid = config.ids.uids.vsftpd; uid = config.ids.uids.vsftpd;
description = "VSFTPD user"; description = "VSFTPD user";
home = "/homeless-shelter"; home = "/homeless-shelter";
} }
] ++ pkgs.lib.optional anonymousUser ] ++ pkgs.lib.optional cfg.anonymousUser
{ name = "ftp"; { name = "ftp";
uid = config.ids.uids.ftp; uid = config.ids.uids.ftp;
group = "ftp"; group = "ftp";
description = "Anonymous ftp user"; description = "Anonymous FTP user";
home = anonymousUserHome; home = cfg.anonymousUserHome;
}; };
extraGroups = [ users.extraGroups = singleton
{ name = "ftp"; { name = "ftp";
gid = config.ids.gids.ftp; gid = config.ids.gids.ftp;
} };
];
jobAttrs.vsftpd =
}; { description = "vsftpd server";
services = { startOn = "network-interfaces/started";
extraJobs = [{ stopOn = "network-interfaces/stop";
name = "vsftpd";
preStart =
job = '' ''
description "vsftpd server" # !!! Why isn't this generated in the normal way?
cat > /etc/vsftpd.conf <<EOF
start on network-interfaces/started ${yesNoOption cfg.anonymousUser "anonymous_enable"}
stop on network-interfaces/stop ${yesNoOption cfg.localUsers "local_enable"}
${yesNoOption cfg.writeEnable "write_enable"}
start script ${yesNoOption cfg.anonymousUploadEnable "anon_upload_enable"}
cat > /etc/vsftpd.conf <<EOF ${yesNoOption cfg.anonymousMkdirEnable "anon_mkdir_write_enable"}
${yesNoOption anonymousUser "anonymous_enable"} ${yesNoOption cfg.chrootlocalUser "chroot_local_user"}
${yesNoOption localUsers "local_enable"} ${yesNoOption cfg.userlistEnable "userlist_enable"}
${yesNoOption writeEnable "write_enable"} ${yesNoOption cfg.userlistDeny "userlist_deny"}
${yesNoOption anonymousUploadEnable "anon_upload_enable"} background=NO
${yesNoOption anonymousMkdirEnable "anon_mkdir_write_enable"} listen=YES
${yesNoOption chrootlocalUser "chroot_local_user"} nopriv_user=vsftpd
${yesNoOption userlistEnable "userlist_enable"} secure_chroot_dir=/var/ftp/empty
${yesNoOption userlistDeny "userlist_deny"} EOF
background=NO
listen=YES mkdir -p ${cfg.anonymousUserHome}
nopriv_user=vsftpd chown -R ftp:ftp ${cfg.anonymousUserHome}
secure_chroot_dir=/var/ftp/empty '';
EOF
exec = "${vsftpd}/sbin/vsftpd /etc/vsftpd.conf";
mkdir -p ${anonymousUserHome} && };
chown -R ftp:ftp ${anonymousUserHome}
end script
respawn ${vsftpd}/sbin/vsftpd /etc/vsftpd.conf
'';
}];
}; };
} }

View File

@ -1,41 +1,13 @@
{pkgs, config, ...}: { config, pkgs, ... }:
###### interface with pkgs.lib;
let
inherit (pkgs.lib) mkOption mkIf;
options = {
services = {
printing = {
enable = mkOption {
default = false;
description = "
Whether to enable printing support through the CUPS daemon.
";
};
bindirCmds = mkOption {
default = "";
description = "
add commands adding additional symlinks to the bindir such as bjnp
";
};
};
};
};
in
###### implementation
let let
logDir = "/var/log/cups";
inherit (pkgs) cups; inherit (pkgs) cups;
logDir = "/var/log/cups";
modprobe = config.system.sbin.modprobe; modprobe = config.system.sbin.modprobe;
cfg = config.services.printing; cfg = config.services.printing;
@ -45,135 +17,163 @@ let
# we can't update ${cups}/lib/cups itself, we create a symlink tree # we can't update ${cups}/lib/cups itself, we create a symlink tree
# here and add the additional programs. The ServerBin directive in # here and add the additional programs. The ServerBin directive in
# cupsd.conf tells cupsd to use this tree. # cupsd.conf tells cupsd to use this tree.
bindir = pkgs.runCommand "cups-progs" {} '' bindir = pkgs.runCommand "cups-progs" {}
ensureDir $out/lib/cups ''
ln -s ${cups}/lib/cups/* $out/lib/cups/ ensureDir $out/lib/cups
ln -s ${cups}/lib/cups/* $out/lib/cups/
# Provide support for printing via SMB. # Provide support for printing via SMB.
rm $out/lib/cups/backend rm $out/lib/cups/backend
ensureDir $out/lib/cups/backend ensureDir $out/lib/cups/backend
ln -s ${cups}/lib/cups/backend/* $out/lib/cups/backend/ ln -s ${cups}/lib/cups/backend/* $out/lib/cups/backend/
ln -s ${pkgs.samba}/bin/smbspool $out/lib/cups/backend/smb ln -s ${pkgs.samba}/bin/smbspool $out/lib/cups/backend/smb
# Provide support for printing via HTTPS. # Provide support for printing via HTTPS.
ln -s ipp $out/lib/cups/backend/https ln -s ipp $out/lib/cups/backend/https
# Provide Ghostscript rasterisation, necessary for non-Postscript # Provide Ghostscript rasterisation, necessary for non-Postscript
# printers. # printers.
rm $out/lib/cups/filter rm $out/lib/cups/filter
ensureDir $out/lib/cups/filter ensureDir $out/lib/cups/filter
ln -s ${cups}/lib/cups/filter/* $out/lib/cups/filter/ ln -s ${cups}/lib/cups/filter/* $out/lib/cups/filter/
ln -s ${pkgs.ghostscript}/lib/cups/filter/* $out/lib/cups/filter/ ln -s ${pkgs.ghostscript}/lib/cups/filter/* $out/lib/cups/filter/
${cfg.bindirCmds} ${cfg.bindirCmds}
''; # */ ''; # */
cupsdConfig = pkgs.writeText "cupsd.conf" '' cupsdConfig = pkgs.writeText "cupsd.conf"
LogLevel debug ''
LogLevel debug
SystemGroup root SystemGroup root
Listen localhost:631 Listen localhost:631
Listen /var/run/cups/cups.sock Listen /var/run/cups/cups.sock
# Note: we can't use ${cups}/etc/cups as the ServerRoot, since # Note: we can't use ${cups}/etc/cups as the ServerRoot, since
# CUPS will write in the ServerRoot when e.g. adding new printers # CUPS will write in the ServerRoot when e.g. adding new printers
# through the web interface. # through the web interface.
ServerRoot /etc/cups ServerRoot /etc/cups
ServerBin ${bindir}/lib/cups ServerBin ${bindir}/lib/cups
AccessLog ${logDir}/access_log AccessLog ${logDir}/access_log
ErrorLog ${logDir}/access_log ErrorLog ${logDir}/access_log
PageLog ${logDir}/page_log PageLog ${logDir}/page_log
TempDir /tmp TempDir /tmp
Browsing On Browsing On
BrowseOrder allow,deny BrowseOrder allow,deny
BrowseAllow @LOCAL BrowseAllow @LOCAL
DefaultAuthType Basic DefaultAuthType Basic
<Location /> <Location />
Order allow,deny Order allow,deny
Allow localhost Allow localhost
</Location> </Location>
<Location /admin>
Order allow,deny
Allow localhost
</Location>
<Location /admin/conf>
AuthType Basic
Require user @SYSTEM
Order allow,deny
Allow localhost
</Location>
<Policy default> <Location /admin>
<Limit Send-Document Send-URI Hold-Job Release-Job Restart-Job Purge-Jobs Set-Job-Attributes Create-Job-Subscription Renew-Subscription Cancel-Subscription Get-Notifications Reprocess-Job Cancel-Current-Job Suspend-Current-Job Resume-Job CUPS-Move-Job> Order allow,deny
Require user @OWNER @SYSTEM Allow localhost
Order deny,allow </Location>
</Limit>
<Limit Pause-Printer Resume-Printer Set-Printer-Attributes Enable-Printer Disable-Printer Pause-Printer-After-Current-Job Hold-New-Jobs Release-Held-New-Jobs Deactivate-Printer Activate-Printer Restart-Printer Shutdown-Printer Startup-Printer Promote-Job Schedule-Job-After CUPS-Add-Printer CUPS-Delete-Printer CUPS-Add-Class CUPS-Delete-Class CUPS-Accept-Jobs CUPS-Reject-Jobs CUPS-Set-Default> <Location /admin/conf>
AuthType Basic AuthType Basic
Require user @SYSTEM Require user @SYSTEM
Order deny,allow Order allow,deny
</Limit> Allow localhost
</Location>
<Limit Cancel-Job CUPS-Authenticate-Job> <Policy default>
Require user @OWNER @SYSTEM <Limit Send-Document Send-URI Hold-Job Release-Job Restart-Job Purge-Jobs Set-Job-Attributes Create-Job-Subscription Renew-Subscription Cancel-Subscription Get-Notifications Reprocess-Job Cancel-Current-Job Suspend-Current-Job Resume-Job CUPS-Move-Job>
Order deny,allow Require user @OWNER @SYSTEM
</Limit> Order deny,allow
</Limit>
<Limit All> <Limit Pause-Printer Resume-Printer Set-Printer-Attributes Enable-Printer Disable-Printer Pause-Printer-After-Current-Job Hold-New-Jobs Release-Held-New-Jobs Deactivate-Printer Activate-Printer Restart-Printer Shutdown-Printer Startup-Printer Promote-Job Schedule-Job-After CUPS-Add-Printer CUPS-Delete-Printer CUPS-Add-Class CUPS-Delete-Class CUPS-Accept-Jobs CUPS-Reject-Jobs CUPS-Set-Default>
Order deny,allow AuthType Basic
</Limit> Require user @SYSTEM
</Policy> Order deny,allow
''; </Limit>
<Limit Cancel-Job CUPS-Authenticate-Job>
Require user @OWNER @SYSTEM
Order deny,allow
</Limit>
<Limit All>
Order deny,allow
</Limit>
</Policy>
'';
in in
{
mkIf config.services.printing.enable { ###### interface
require = [
options
];
environment.systemPackages = [cups]; options = {
services.printing = {
environment.etc = enable = mkOption {
[ # CUPS expects the following files in its ServerRoot. default = false;
{ source = "${cups}/etc/cups/mime.convs"; description = ''
target = "cups/mime.convs"; Whether to enable printing support through the CUPS daemon.
} '';
{ source = "${cups}/etc/cups/mime.types"; };
target = "cups/mime.types";
}
];
services.extraJobs = pkgs.lib.singleton bindirCmds = mkOption {
{ name = "cupsd"; default = "";
description = ''
Additional commands executed while creating the directory
containing the CUPS server binaries.
'';
};
job = '' };
description "CUPS printing daemon"
start on network-interfaces/started };
stop on network-interfaces/stop
start script
###### implementation
config = mkIf config.services.printing.enable {
environment.systemPackages = [cups];
environment.etc =
[ # CUPS expects the following files in its ServerRoot.
{ source = "${cups}/etc/cups/mime.convs";
target = "cups/mime.convs";
}
{ source = "${cups}/etc/cups/mime.types";
target = "cups/mime.types";
}
];
jobAttrs.cupsd =
{ description = "CUPS printing daemon";
startOn = "network-interfaces/started";
stopOn = "network-interfaces/stop";
preStart =
''
mkdir -m 0755 -p ${logDir} mkdir -m 0755 -p ${logDir}
mkdir -m 0700 -p /var/cache/cups mkdir -m 0700 -p /var/cache/cups
mkdir -m 0700 -p /var/spool/cups mkdir -m 0700 -p /var/spool/cups
# Make USB printers show up. # Make USB printers show up.
${modprobe}/sbin/modprobe usblp || true ${modprobe}/sbin/modprobe usblp || true
end script '';
respawn ${cups}/sbin/cupsd -c ${cupsdConfig} -F exec = "${cups}/sbin/cupsd -c ${cupsdConfig} -F";
''; };
};
};
} }

View File

@ -1,92 +1,82 @@
{pkgs, config, ...}: { config, pkgs, ... }:
with pkgs.lib;
###### interface
let let
inherit (pkgs.lib) mkOption;
options = {
services = {
cron = {
mailto = mkOption {
default = "";
description = " The job output will be mailed to this email address. ";
};
systemCronJobs = mkOption {
default = [];
example = [
"* * * * * test ls -l / > /tmp/cronout 2>&1"
"* * * * * eelco echo Hello World > /home/eelco/cronout"
];
description = ''
A list of Cron jobs to be appended to the system-wide
crontab. See the manual page for crontab for the expected
format. If you want to get the results mailed you must setuid
sendmail. See <option>security.setuidOwners</option>
If neither /var/cron/cron.deny nor /var/cron/cron.allow exist only root
will is allowed to have its own crontab file. The /var/cron/cron.deny file
is created automatically for you. So every user can use a crontab.
'';
};
};
};
};
in
###### implementation
let
inherit (config.services) jobsTags; inherit (config.services) jobsTags;
# Put all the system cronjobs together. # Put all the system cronjobs together.
systemCronJobs = systemCronJobsFile = pkgs.writeText "system-crontab"
config.services.cron.systemCronJobs; ''
SHELL=${pkgs.bash}/bin/sh
systemCronJobsFile = pkgs.writeText "system-crontab" '' PATH=${pkgs.coreutils}/bin:${pkgs.findutils}/bin:${pkgs.gnused}/bin:${pkgs.su}/bin
SHELL=${pkgs.bash}/bin/sh MAILTO="${config.services.cron.mailto}"
PATH=${pkgs.coreutils}/bin:${pkgs.findutils}/bin:${pkgs.gnused}/bin:${pkgs.su}/bin ${pkgs.lib.concatStrings (map (job: job + "\n") config.services.cron.systemCronJobs)}
MAILTO="${config.services.cron.mailto}" '';
${pkgs.lib.concatStrings (map (job: job + "\n") systemCronJobs)}
'';
in in
{ {
require = [
# ../upstart-jobs/default.nix # config.services.extraJobs
# ? # config.time.timeZone
# ? # config.environment.etc
# ? # config.environment.extraPackages
options
];
environment = { ###### interface
etc = [
options = {
services.cron = {
mailto = mkOption {
default = "";
description = " The job output will be mailed to this email address. ";
};
systemCronJobs = mkOption {
default = [];
example = [
"* * * * * test ls -l / > /tmp/cronout 2>&1"
"* * * * * eelco echo Hello World > /home/eelco/cronout"
];
description = ''
A list of Cron jobs to be appended to the system-wide
crontab. See the manual page for crontab for the expected
format. If you want to get the results mailed you must setuid
sendmail. See <option>security.setuidOwners</option>
If neither /var/cron/cron.deny nor /var/cron/cron.allow exist only root
will is allowed to have its own crontab file. The /var/cron/cron.deny file
is created automatically for you. So every user can use a crontab.
'';
};
};
};
###### implementation
config = {
environment.etc = singleton
# The system-wide crontab. # The system-wide crontab.
{ source = systemCronJobsFile; { source = systemCronJobsFile;
target = "crontab"; target = "crontab";
mode = "0600"; # Cron requires this. mode = "0600"; # Cron requires this.
} };
];
systemPackages = [pkgs.cron]; environment.systemPackages = [pkgs.cron];
};
services = { jobAttrs.cron =
extraJobs = [{ { description = "Cron daemon";
name = "cron";
job = ''
description "Cron daemon"
start on startup
stop on shutdown
startOn = "startup";
stopOn = "shutdown";
# Needed to interpret times in the local timezone. # Needed to interpret times in the local timezone.
env TZ=${config.time.timeZone} environment = { TZ = config.time.timeZone; };
start script preStart =
''
mkdir -m 710 -p /var/cron mkdir -m 710 -p /var/cron
# By default, allow all users to create a crontab. This # By default, allow all users to create a crontab. This
@ -94,10 +84,11 @@ in
if ! test -e /var/cron/cron.allow -o -e /var/cron/cron.deny; then if ! test -e /var/cron/cron.allow -o -e /var/cron/cron.deny; then
touch /var/cron/cron.deny touch /var/cron/cron.deny
fi fi
end script '';
exec = "${pkgs.cron}/sbin/cron -n";
};
respawn ${pkgs.cron}/sbin/cron -n
'';
}];
}; };
} }

View File

@ -1,135 +1,122 @@
{pkgs, config, ...}: { config, pkgs, ... }:
with pkgs.lib;
###### interface
let let
inherit (pkgs.lib) mkOption concatStringsSep;
inherit (pkgs) writeText;
options = {
services = {
fcron = {
enable = mkOption {
default = false;
description = ''Whether to enable the `fcron' daemon.
From its docs: "fcron does both the job of Vixie Cron and anacron, but does even more and better".
It can trigger actions even if the event has passed due to shutdown for example.
TODO: add supoprt for fcron.allow and fcron.deny
Of course on cron daemon is enough.. So if fcron works fine there should be a system option systemCron="fcron or cron"
There are (or have been) some security issues.
I haven't yet checked wether they have been resolved.
For now you should trust the users registering crontab files.
I think gentoo has them listed.
'';
};
allow = mkOption {
default = [];
description = ''
Users allowed to use fcrontab and fcrondyn (one name per line, special name "all" acts for everyone)
nix adds username "root" for you.
'';
};
deny = mkOption {
default = [];
description = " same as allow but deny ";
};
maxSerialJobs = mkOption {
default = 1;
description = "maximum number of serial jobs which can run simultaneously (-m)";
};
queuelen = mkOption {
default = "";
description = "number of jobs the serial queue and the lavg queue can contain - empty to net set this number (-q)";
};
systab = mkOption {
default = "";
description = ''
The "system" crontab contents..
'';
};
};
};
};
in
###### implementation
let
# Put all the system cronjobs together. # Put all the system cronjobs together.
# TODO allow using fcron only.. # TODO allow using fcron only..
#systemCronJobs = #systemCronJobs =
# config.services.cron.systemCronJobs; # config.services.cron.systemCronJobs;
cfg = config.services.fcron; cfg = config.services.fcron;
ifEnabled = if cfg.enable then pkgs.lib.id else (x : []);
queuelen = if cfg.queuelen == "" then "" else "-q ${toString cfg.queuelen}"; queuelen = if cfg.queuelen == "" then "" else "-q ${toString cfg.queuelen}";
# shell is set to /sh in config.. # shell is set to /sh in config..
# ${pkgs.lib.concatStrings (map (job: job + "\n") systemCronJobs)} # ${pkgs.lib.concatStrings (map (job: job + "\n") systemCronJobs)}
systemCronJobsFile = pkgs.writeText "fcron-systab" '' systemCronJobsFile = pkgs.writeText "fcron-systab"
SHELL=${pkgs.bash}/bin/sh ''
PATH=${pkgs.coreutils}/bin:${pkgs.findutils}/bin:${pkgs.gnused}/bin SHELL=${pkgs.bash}/bin/sh
''; PATH=${pkgs.coreutils}/bin:${pkgs.findutils}/bin:${pkgs.gnused}/bin
'';
allowdeny = target: users : { allowdeny = target: users:
source = writeText "fcron.${target}" (concatStringsSep "\n" users); { source = pkgs.writeText "fcron.${target}" (concatStringsSep "\n" users);
target = "fcron.${target}"; target = "fcron.${target}";
mode = "600"; # fcron has some security issues.. So I guess this is most safe mode = "600"; # fcron has some security issues.. So I guess this is most safe
}; };
in in
{ {
require = [
# ../upstart-jobs/default.nix # config.services.extraJobs
# ? # config.time.timeZone
# ? # config.environment.etc
# ? # config.environment.extraPackages
# ? # config.environment.cleanStart
options
];
environment = { ###### interface
etc = ifEnabled [
(allowdeny "allow" (["root"] ++ cfg.allow)) options = {
(allowdeny "deny" cfg.deny)
# see man 5 fcron.conf services.fcron = {
{ source = writeText "fcon.conf" ''
fcrontabs = /var/spool/fcron enable = mkOption {
pidfile = /var/run/fcron.pid default = false;
fifofile = /var/run/fcron.fifo description = "Whether to enable the `fcron' daemon.";
fcronallow = /etc/fcron.allow };
fcrondeny = /etc/fcron.deny
shell = /bin/sh allow = mkOption {
sendmail = /var/setuid-wrappers/sendmail default = [];
editor = /var/run/current-system/sw/bin/vi description = ''
''; Users allowed to use fcrontab and fcrondyn (one name per line, "all" for everyone).
target = "fcron.conf"; '';
mode = "0600"; # max allowed is 644 };
}
]; deny = mkOption {
default = [];
description = "Users forbidden from using fcron.";
};
maxSerialJobs = mkOption {
default = 1;
description = "Maximum number of serial jobs which can run simultaneously.";
};
queuelen = mkOption {
default = "";
description = "Number of jobs the serial queue and the lavg queue can contain - empty to net set this number (-q)";
};
systab = mkOption {
default = "";
description = ''The "system" crontab contents.'';
};
};
systemPackages = ifEnabled [pkgs.fcron];
}; };
services = {
extraJobs = ifEnabled [{
name = "fcron";
job = '' ###### implementation
description "fcron daemon"
start on startup config = mkIf cfg.enable {
stop on shutdown
env PATH=/var/run/current-system/sw/bin environment.etc =
[ (allowdeny "allow" (["root"] ++ cfg.allow))
(allowdeny "deny" cfg.deny)
# see man 5 fcron.conf
{ source = pkgs.writeText "fcon.conf" ''
fcrontabs = /var/spool/fcron
pidfile = /var/run/fcron.pid
fifofile = /var/run/fcron.fifo
fcronallow = /etc/fcron.allow
fcrondeny = /etc/fcron.deny
shell = /bin/sh
sendmail = /var/setuid-wrappers/sendmail
editor = /var/run/current-system/sw/bin/vi
'';
target = "fcron.conf";
mode = "0600"; # max allowed is 644
}
];
start script environment.systemPackages = [ pkgs.fcron ];
jobAttrs.fcron =
{ description = "fcron daemon";
startOn = "startup";
stopOn = "shutdown";
environment =
{ PATH = "/var/run/current-system/sw/bin";
};
preStart =
''
${pkgs.coreutils}/bin/mkdir -m 0700 -p /var/spool/fcron ${pkgs.coreutils}/bin/mkdir -m 0700 -p /var/spool/fcron
# load system crontab file # load system crontab file
${pkgs.fcron}/bin/fcrontab -u systab ${writeText "systab" cfg.systab} ${pkgs.fcron}/bin/fcrontab -u systab ${pkgs.writeText "systab" cfg.systab}
end script '';
exec = "${pkgs.fcron}/sbin/fcron -f -m ${toString cfg.maxSerialJobs} ${queuelen}";
};
respawn ${pkgs.fcron}/sbin/fcron -f -m ${toString cfg.maxSerialJobs} ${queuelen}
'';
}];
}; };
} }

View File

@ -1,58 +1,52 @@
{pkgs, config, ...}: { config, pkgs, ... }:
with pkgs.lib;
###### interface
let let
inherit (pkgs.lib) mkOption;
cfg = config.services.gpm;
in
{
###### interface
options = { options = {
services = {
gpm = { services.gpm = {
enable = mkOption {
default = false; enable = mkOption {
description = " default = false;
Whether to enable general purpose mouse daemon. description = ''
"; Whether to enable GPM, the General Purpose Mouse daemon,
}; which enables mouse support in virtual consoles.
protocol = mkOption { '';
default = "ps/2";
description = "
Mouse protocol to use.
";
};
}; };
protocol = mkOption {
default = "ps/2";
description = "Mouse protocol to use.";
};
}; };
}; };
in
###### implementation ###### implementation
let
cfg = config.services.gpm;
inherit (pkgs.lib) mkIf;
gpm = pkgs.gpm; config = mkIf cfg.enable {
gpmBin = "${gpm}/sbin/gpm";
job = { jobAttrs.gpm =
name = "gpm"; { description = "General purpose mouse";
job = ''
description = "General purpose mouse"
start on udev startOn = "udev";
stop on shutdown stopOn = "shutdown";
exec = "${pkgs.gpm}/sbin/gpm -m /dev/input/mice -t ${cfg.protocol} -D &>/dev/null";
};
respawn ${gpmBin} -m /dev/input/mice -t ${cfg.protocol} -D &>/dev/null
'';
};
in
mkIf cfg.enable {
require = [
# ../upstart-jobs/default.nix # config.services.extraJobs
# /etc/security/console.perms (should be generated ?)
options
];
services = {
extraJobs = [job];
}; };
} }

View File

@ -1,82 +1,81 @@
{servicesPath, pkgs, config, ...}: { config, pkgs, servicesPath, ... }:
with pkgs.lib;
###### interface
let let
inherit (pkgs.lib) mkOption mkIf;
cfg = config.services.jboss;
jbossService = import (servicesPath + /jboss) {
inherit (pkgs) stdenv jboss su;
inherit (cfg) tempDir logDir libUrl deployDir serverDir user useJK;
};
in
{
###### interface
options = { options = {
services = {
jboss = { services.jboss = {
enable = mkOption {
default = false; enable = mkOption {
description = "Whether to enable jboss"; default = false;
}; description = "Whether to enable jboss";
tempDir = mkOption {
default = "/tmp";
description = "Location where JBoss stores its temp files";
};
logDir = mkOption {
default = "/var/log/jboss";
description = "Location of the logfile directory of JBoss";
};
serverDir = mkOption {
description = "Location of the server instance files";
default = "/var/jboss/server";
};
deployDir = mkOption {
description = "Location of the deployment files";
default = "/nix/var/nix/profiles/default/server/default/deploy/";
};
libUrl = mkOption {
default = "file:///nix/var/nix/profiles/default/server/default/lib";
description = "Location where the shared library JARs are stored";
};
user = mkOption {
default = "nobody";
description = "User account under which jboss runs.";
};
useJK = mkOption {
default = false;
description = "Whether to use to connector to the Apache HTTP server";
};
}; };
tempDir = mkOption {
default = "/tmp";
description = "Location where JBoss stores its temp files";
};
logDir = mkOption {
default = "/var/log/jboss";
description = "Location of the logfile directory of JBoss";
};
serverDir = mkOption {
description = "Location of the server instance files";
default = "/var/jboss/server";
};
deployDir = mkOption {
description = "Location of the deployment files";
default = "/nix/var/nix/profiles/default/server/default/deploy/";
};
libUrl = mkOption {
default = "file:///nix/var/nix/profiles/default/server/default/lib";
description = "Location where the shared library JARs are stored";
};
user = mkOption {
default = "nobody";
description = "User account under which jboss runs.";
};
useJK = mkOption {
default = false;
description = "Whether to use to connector to the Apache HTTP server";
};
}; };
}; };
in
###### implementation
let
cfg = config.services.jboss; ###### implementation
jbossService = import (servicesPath + /jboss) {
inherit (pkgs) stdenv jboss su;
inherit (cfg) tempDir logDir libUrl deployDir serverDir user useJK;
};
in config = mkIf config.services.jboss.enable {
mkIf config.services.jboss.enable { jobAttrs.jboss =
require = [ { description = "JBoss server";
options
];
services = { exec = "${jbossService}/bin/control start";
extraJobs = [{ };
name = "jboss";
job = ''
description \"JBoss server\"
stop on shutdown
respawn ${jbossService}/bin/control start
'';
}];
}; };
} }

View File

@ -1,114 +1,114 @@
{pkgs, config, ...}: { config, pkgs, ... }:
with pkgs.lib;
###### interface
let let
inherit (pkgs.lib) mkOption mkIf;
cfg = config.services.tomcat;
in
{
###### interface
options = { options = {
services = {
tomcat = { services.tomcat = {
enable = mkOption {
default = false;
description = "Whether to enable Apache Tomcat";
};
baseDir = mkOption {
default = "/var/tomcat";
description = "Location where Tomcat stores configuration files, webapplications and logfiles";
};
user = mkOption {
default = "tomcat";
description = "User account under which Apache Tomcat runs.";
};
group = mkOption {
default = "tomcat";
description = "Group account under which Apache Tomcat runs.";
};
javaOpts = mkOption {
default = "";
description = "Parameters to pass to the Java Virtual Machine which spawns Apache Tomcat";
};
catalinaOpts = mkOption {
default = "";
description = "Parameters to pass to the Java Virtual Machine which spawns the Catalina servlet container";
};
sharedLibs = mkOption {
default = [];
description = "List containing JAR files or directories with JAR files which are libraries shared by the web applications";
};
commonLibs = mkOption {
default = [];
description = "List containing JAR files or directories with JAR files which are libraries shared by the web applications and the servlet container";
};
webapps = mkOption {
default = [ pkgs.tomcat6 ];
description = "List containing WAR files or directories with WAR files which are web applications to be deployed on Tomcat";
};
virtualHosts = mkOption {
default = [];
description = "List consisting of a virtual host name and a list of web applications to deploy on each virtual host";
};
axis2 = {
enable = mkOption { enable = mkOption {
default = false; default = false;
description = "Whether to enable Apache Tomcat"; description = "Whether to enable an Apache Axis2 container";
}; };
baseDir = mkOption { services = mkOption {
default = "/var/tomcat";
description = "Location where Tomcat stores configuration files, webapplications and logfiles";
};
user = mkOption {
default = "tomcat";
description = "User account under which Apache Tomcat runs.";
};
group = mkOption {
default = "tomcat";
description = "Group account under which Apache Tomcat runs.";
};
javaOpts = mkOption {
default = "";
description = "Parameters to pass to the Java Virtual Machine which spawns Apache Tomcat";
};
catalinaOpts = mkOption {
default = "";
description = "Parameters to pass to the Java Virtual Machine which spawns the Catalina servlet container";
};
sharedLibs = mkOption {
default = []; default = [];
description = "List containing JAR files or directories with JAR files which are libraries shared by the web applications"; description = "List containing AAR files or directories with AAR files which are web services to be deployed on Axis2";
}; };
commonLibs = mkOption {
default = [];
description = "List containing JAR files or directories with JAR files which are libraries shared by the web applications and the servlet container";
};
webapps = mkOption {
default = [ pkgs.tomcat6 ];
description = "List containing WAR files or directories with WAR files which are web applications to be deployed on Tomcat";
};
virtualHosts = mkOption {
default = [];
description = "List consisting of a virtual host name and a list of web applications to deploy on each virtual host";
};
axis2 = {
enable = mkOption {
default = false;
description = "Whether to enable an Apache Axis2 container";
};
services = mkOption {
default = [];
description = "List containing AAR files or directories with AAR files which are web services to be deployed on Axis2";
};
};
}; };
}; };
}; };
in
###### implementation
let ###### implementation
cfg = config.services.tomcat;
in
mkIf config.services.tomcat.enable { config = mkIf config.services.tomcat.enable {
require = [
options
];
services = { users.extraGroups = singleton
extraJobs = [{ { name = "tomcat";
name = "tomcat"; gid = config.ids.gids.tomcat;
};
groups = [ users.extraUsers = singleton
{ name = "tomcat"; { name = "tomcat";
gid = config.ids.gids.tomcat; uid = config.ids.uids.tomcat;
} description = "Tomcat user";
]; home = "/homeless-shelter";
};
users = [ jobAttrs.tomcat =
{ name = "tomcat"; { description = "Apache Tomcat server";
uid = config.ids.uids.tomcat;
description = "Tomcat user";
home = "/homeless-shelter";
}
];
job = ''
description "Apache Tomcat server"
start on network-interface/started startOn = "network-interface/started";
stop on network-interfaces/stop stopOn = "network-interfaces/stop";
start script preStart =
''
# Create the base directory # Create the base directory
mkdir -p ${cfg.baseDir} mkdir -p ${cfg.baseDir}
@ -304,15 +304,21 @@ mkIf config.services.tomcat.enable {
done done
'' ''
else ""} else ""}
end script ''; # */
respawn ${pkgs.su}/bin/su -s ${pkgs.bash}/bin/sh ${cfg.user} -c 'CATALINA_BASE=${cfg.baseDir} JAVA_HOME=${pkgs.jdk} JAVA_OPTS="${cfg.javaOpts}" CATALINA_OPTS="${cfg.catalinaOpts}" ${pkgs.tomcat6}/bin/startup.sh; sleep 1000d' exec =
''
stop script ${pkgs.su}/bin/su -s ${pkgs.bash}/bin/sh ${cfg.user} -c 'CATALINA_BASE=${cfg.baseDir} JAVA_HOME=${pkgs.jdk} JAVA_OPTS="${cfg.javaOpts}" CATALINA_OPTS="${cfg.catalinaOpts}" ${pkgs.tomcat6}/bin/startup.sh; sleep 1000d'
'';
postStop =
''
echo "Stopping tomcat..." echo "Stopping tomcat..."
CATALINA_BASE=${cfg.baseDir} JAVA_HOME=${pkgs.jdk} ${pkgs.su}/bin/su -s ${pkgs.bash}/bin/sh ${cfg.user} -c ${pkgs.tomcat6}/bin/shutdown.sh CATALINA_BASE=${cfg.baseDir} JAVA_HOME=${pkgs.jdk} ${pkgs.su}/bin/su -s ${pkgs.bash}/bin/sh ${cfg.user} -c ${pkgs.tomcat6}/bin/shutdown.sh
end script '';
'';
}]; };
}; };
} }

View File

@ -1,54 +1,54 @@
{pkgs, config, ...}: { config, pkgs, ... }:
with pkgs.lib;
###### interface
let let
inherit (pkgs.lib) mkOption mkIf;
configFile = ./xfs.conf;
startingDependency =
if config.services.gw6c.enable && config.services.gw6c.autorun
then "gw6c"
else "network-interfaces";
in
{
###### interface
options = { options = {
services = {
xfs = { services.xfs = {
enable = mkOption {
default = false;
description = "
Whether to enable the X Font Server.
";
};
enable = mkOption {
default = false;
description = "Whether to enable the X Font Server.";
}; };
}; };
}; };
in
###### implementation
let ###### implementation
configFile = ./xfs.conf;
startingDependency = if config.services.gw6c.enable && config.services.gw6c.autorun then "gw6c" else "network-interfaces";
in
mkIf config.services.xfs.enable { config = mkIf config.services.xfs.enable {
assertions = [ { assertion = config.fonts.enableFontDir; message = "Please enable fontDir (fonts.enableFontDir) to use xfs."; } ]; assertions = singleton
{ assertion = config.fonts.enableFontDir;
message = "Please enable fontDir (fonts.enableFontDir) to use xfs.";
};
require = [ jobAttrs.xfs =
options { description = "X Font Server";
];
startOn = "${startingDependency}/started";
stopOn = "shutdown";
services = { exec = "${pkgs.xorg.xfs}/bin/xfs -config ${configFile}";
};
extraJobs = [ (rec {
name = "xfs";
groups = [];
users = [];
job = ''
description "X Font Server"
start on ${startingDependency}/started
stop on shutdown
respawn ${pkgs.xorg.xfs}/bin/xfs -config ${configFile}
'';
})];
}; };
} }

View File

@ -1,20 +1,18 @@
{pkgs, config, ...}: { config, pkgs, ... }:
###### implementation ###### implementation
{ {
jobAttrs.ctrl_alt_delete =
{ name = "ctrl-alt-delete";
services = { startOn = "ctrlaltdel";
extraJobs = [{
name = "ctrl-alt-delete"; task = true;
job = '' script =
on ctrlaltdel ''
shutdown -r now 'Ctrl-Alt-Delete pressed'
script '';
shutdown -r now 'Ctrl-Alt-Delete pressed' };
end script
'';
}];
};
} }

View File

@ -1,19 +1,20 @@
{pkgs, config, ...}: { config, pkgs, ... }:
with pkgs.lib;
###### implementation ###### implementation
let let
inherit (pkgs) bash utillinux; inherit (pkgs) bash utillinux;
jobFun = event : { jobFun = event:
name = "sys-" + event; { startOn = event;
job = '' task = true;
start on ${event}
script =
script ''
set +e # continue in case of errors set +e # continue in case of errors
exec < /dev/tty1 > /dev/tty1 2>&1 exec < /dev/tty1 > /dev/tty1 2>&1
@ -109,16 +110,12 @@ let
sleep 1 sleep 1
exec halt -f -p exec halt -f -p
fi fi
'';
end script };
'';
};
in in
{ {
services = { jobAttrs = listToAttrs (map (n: nameValuePair "sys-${n}" (jobFun n))
extraJobs = map jobFun ["reboot" "halt" "system-halt" "power-off"]; [ "reboot" "halt" "system-halt" "power-off" ] );
};
} }

View File

@ -1,24 +1,22 @@
{pkgs, config, ...}: { config, pkgs, ... }:
###### implementation ###### implementation
{ {
services = { jobAttrs.maintenance_shell =
extraJobs = [{ { name = "maintenance-shell";
name = "maintenance-shell";
startOn = [ "maintenance" "stalled" ];
job = ''
start on maintenance task = true;
start on stalled
script =
script ''
exec < /dev/tty1 > /dev/tty1 2>&1 exec < /dev/tty1 > /dev/tty1 2>&1
echo \"\" echo \
echo \"<<< MAINTENANCE SHELL >>>\" echo "<<< MAINTENANCE SHELL >>>"
echo \"\" echo ""
exec ${pkgs.bash}/bin/sh exec ${pkgs.bash}/bin/sh
end script '';
''; };
}];
};
} }

View File

@ -327,7 +327,7 @@ in
} }
]; ];
# see test/test-upstart-job.sh (!!! check whether this still works) # !!! fix this
tests.upstartJobs = { recurseForDerivations = true; } // tests.upstartJobs = { recurseForDerivations = true; } //
builtins.listToAttrs (map (job: { builtins.listToAttrs (map (job: {
name = removePrefix "upstart-" job.name; name = removePrefix "upstart-" job.name;

View File

@ -1,117 +1,9 @@
{pkgs, config, ...}: { config, pkgs, ... }:
with pkgs.lib;
let let
###### interface
inherit (pkgs.lib) mkOption types;
options = {
fileSystems = mkOption {
example = [
{ mountPoint = "/";
device = "/dev/hda1";
}
{ mountPoint = "/data";
device = "/dev/hda2";
fsType = "ext3";
options = "data=journal";
}
{ mountPoint = "/bigdisk";
label = "bigdisk";
}
];
description = "
The file systems to be mounted. It must include an entry for
the root directory (<literal>mountPoint = \"/\"</literal>). Each
entry in the list is an attribute set with the following fields:
<literal>mountPoint</literal>, <literal>device</literal>,
<literal>fsType</literal> (a file system type recognised by
<command>mount</command>; defaults to
<literal>\"auto\"</literal>), and <literal>options</literal>
(the mount options passed to <command>mount</command> using the
<option>-o</option> flag; defaults to <literal>\"defaults\"</literal>).
Instead of specifying <literal>device</literal>, you can also
specify a volume label (<literal>label</literal>) for file
systems that support it, such as ext2/ext3 (see <command>mke2fs
-L</command>).
<literal>autocreate</literal> forces <literal>mountPoint</literal> to be created with
<command>mkdir -p</command> .
";
type = types.nullOr (types.list types.optionSet);
options = {
mountPoint = mkOption {
example = "/mnt/usb";
type = types.uniq types.string;
description = "
Location of the mounted the file system.
";
};
device = mkOption {
default = null;
example = "/dev/sda";
type = types.uniq (types.nullOr types.string);
description = "
Location of the device.
";
};
label = mkOption {
default = null;
example = "root-partition";
type = types.uniq (types.nullOr types.string);
description = "
Label of the device (if any).
";
};
fsType = mkOption {
default = "auto";
example = "ext3";
type = types.uniq types.string;
description = "
Type of the file system.
";
};
options = mkOption {
default = "defaults,relatime";
example = "data=journal";
type = types.string;
merge = pkgs.lib.concatStringsSep ",";
description = "
Option used to mount the file system.
";
};
autocreate = mkOption {
default = false;
type = types.bool;
description = "
Automatically create the mount point defined in
<option>fileSystems.*.mountPoint</option>.
";
};
};
};
system.sbin.mount = mkOption {
internal = true;
default = pkgs.utillinuxng;
description = "
Package containing mount and umount.
";
};
};
###### implementation
fileSystems = config.fileSystems; fileSystems = config.fileSystems;
mountPoints = map (fs: fs.mountPoint) fileSystems; mountPoints = map (fs: fs.mountPoint) fileSystems;
devices = map (fs: if fs.device != null then fs.device else "/dev/disk/by-label/${fs.label}") fileSystems; devices = map (fs: if fs.device != null then fs.device else "/dev/disk/by-label/${fs.label}") fileSystems;
@ -120,12 +12,8 @@ let
autocreates = map (fs: fs.autocreate) fileSystems; autocreates = map (fs: fs.autocreate) fileSystems;
mount = config.system.sbin.mount; mount = config.system.sbin.mount;
job = '' task =
start on startup ''
start on new-devices
start on ip-up
script
PATH=${pkgs.e2fsprogs}/sbin:${pkgs.utillinuxng}/sbin:$PATH PATH=${pkgs.e2fsprogs}/sbin:${pkgs.utillinuxng}/sbin:$PATH
mountPoints=(${toString mountPoints}) mountPoints=(${toString mountPoints})
@ -218,25 +106,141 @@ let
if ${mount}/bin/mount -t "$fsType" -o "$options" "$device" "$mountPoint"; then if ${mount}/bin/mount -t "$fsType" -o "$options" "$device" "$mountPoint"; then
newDevices=1 newDevices=1
fi fi
done done
done done
'';
end script
'';
in in
{ {
require = [options];
###### interface
options = {
fileSystems = mkOption {
example = [
{ mountPoint = "/";
device = "/dev/hda1";
}
{ mountPoint = "/data";
device = "/dev/hda2";
fsType = "ext3";
options = "data=journal";
}
{ mountPoint = "/bigdisk";
label = "bigdisk";
}
];
description = "
The file systems to be mounted. It must include an entry for
the root directory (<literal>mountPoint = \"/\"</literal>). Each
entry in the list is an attribute set with the following fields:
<literal>mountPoint</literal>, <literal>device</literal>,
<literal>fsType</literal> (a file system type recognised by
<command>mount</command>; defaults to
<literal>\"auto\"</literal>), and <literal>options</literal>
(the mount options passed to <command>mount</command> using the
<option>-o</option> flag; defaults to <literal>\"defaults\"</literal>).
Instead of specifying <literal>device</literal>, you can also
specify a volume label (<literal>label</literal>) for file
systems that support it, such as ext2/ext3 (see <command>mke2fs
-L</command>).
<literal>autocreate</literal> forces <literal>mountPoint</literal> to be created with
<command>mkdir -p</command> .
";
type = types.nullOr (types.list types.optionSet);
options = {
mountPoint = mkOption {
example = "/mnt/usb";
type = types.uniq types.string;
description = "
Location of the mounted the file system.
";
};
device = mkOption {
default = null;
example = "/dev/sda";
type = types.uniq (types.nullOr types.string);
description = "
Location of the device.
";
};
label = mkOption {
default = null;
example = "root-partition";
type = types.uniq (types.nullOr types.string);
description = "
Label of the device (if any).
";
};
fsType = mkOption {
default = "auto";
example = "ext3";
type = types.uniq types.string;
description = "
Type of the file system.
";
};
options = mkOption {
default = "defaults,relatime";
example = "data=journal";
type = types.string;
merge = pkgs.lib.concatStringsSep ",";
description = "
Option used to mount the file system.
";
};
autocreate = mkOption {
default = false;
type = types.bool;
description = "
Automatically create the mount point defined in
<option>fileSystems.*.mountPoint</option>.
";
};
};
};
services = { system.sbin.mount = mkOption {
extraJobs = [{ internal = true;
name = "filesystems"; default = pkgs.utillinuxng;
inherit job; description = "
}]; Package containing mount and umount.
";
};
};
###### implementation
config = {
# Add the mount helpers to the system path so that `mount' can find them.
environment.systemPackages = [pkgs.ntfs3g pkgs.mount_cifs pkgs.nfsUtils];
jobAttrs.filesystems =
{ startOn = [ "startup" "new-devices" "ip-up" ];
script = task;
task = true;
};
}; };
# Add the mount helpers to the system path so that `mount' can find them.
environment.systemPackages = [pkgs.ntfs3g pkgs.mount_cifs pkgs.nfsUtils];
} }

View File

@ -1,27 +1,18 @@
{pkgs, config, ...}: { config, pkgs, ... }:
###### implementation
let
modprobe = config.system.sbin.modprobe;
in
{ {
services = { ###### implementation
extraJobs = [{
name = "lvm";
job = ''
start on udev
#start on new-devices
script config = {
jobAttrs.lvm =
{ startOn = " udev"; # !!! or on new-devices
script =
''
# Load the device mapper. # Load the device mapper.
${modprobe}/sbin/modprobe dm_mod || true ${config.system.sbin.modprobe}/sbin/modprobe dm_mod || true
${pkgs.devicemapper}/sbin/dmsetup mknodes ${pkgs.devicemapper}/sbin/dmsetup mknodes
# Scan for block devices that might contain LVM physical volumes # Scan for block devices that might contain LVM physical volumes
@ -33,9 +24,11 @@ in
${pkgs.lvm2}/sbin/vgchange --available y ${pkgs.lvm2}/sbin/vgchange --available y
initctl emit new-devices initctl emit new-devices
'';
end script
''; task = true;
}]; };
}; };
} }

View File

@ -132,7 +132,6 @@ in
pkgs.wirelesstools pkgs.wirelesstools
]; ];
jobs = pkgs.lib.singleton jobs = pkgs.lib.singleton
{ name = "network-interfaces"; { name = "network-interfaces";

View File

@ -1,4 +1,4 @@
{pkgs, config, ...}: { config, pkgs, ... }:
###### implementation ###### implementation
@ -12,16 +12,11 @@ in
{ {
services = { jobAttrs.swraid =
extraJobs = [{ { startOn = "udev"; # !!! or on "new-devices"
name = "swraid";
job = ''
start on udev
#start on new-devices
script
script =
''
# Load the necessary RAID personalities. # Load the necessary RAID personalities.
# !!! hm, doesn't the kernel load these automatically? # !!! hm, doesn't the kernel load these automatically?
for mod in raid0 raid1 raid5; do for mod in raid0 raid1 raid5; do
@ -35,10 +30,9 @@ in
${mdadm}/sbin/mdadm --assemble -c ${tempConf} --scan ${mdadm}/sbin/mdadm --assemble -c ${tempConf} --scan
initctl emit new-devices initctl emit new-devices
'';
end script
task = true;
''; };
}];
};
} }