* Synced with branches/fix-style @ 14408

svn path=/nixos/branches/modular-nixos/; revision=14949
This commit is contained in:
Nicolas Pierron 2009-04-08 13:46:34 +00:00
commit 57a524368b
60 changed files with 4326 additions and 3852 deletions

View File

@ -17,6 +17,7 @@
httpd = { httpd = {
enable = true; enable = true;
experimental = true;
adminAddr = "admin@example.org"; adminAddr = "admin@example.org";
subservices = { subservices = {

View File

@ -129,32 +129,6 @@ let
target = "inputrc"; target = "inputrc";
} }
{ # Nix configuration.
source =
let
# Tricky: if we're using a chroot for builds, then we need
# /bin/sh in the chroot (our own compromise to purity).
# However, since /bin/sh is a symlink to some path in the
# Nix store, which furthermore has runtime dependencies on
# other paths in the store, we need the closure of /bin/sh
# in `build-chroot-dirs' - otherwise any builder that uses
# /bin/sh won't work.
refs = pkgs.writeReferencesToFile binsh;
in
pkgs.runCommand "nix.conf" {} ''
binshDeps=$(for i in $(cat ${refs}); do if test -d $i; then echo $i; fi; done)
cat > $out <<END
# WARNING: this file is generated.
build-users-group = nixbld
build-max-jobs = ${toString (config.nix.maxJobs)}
build-use-chroot = ${if config.nix.useChroot then "true" else "false"}
build-chroot-dirs = /dev /dev/pts /proc /bin $(echo $binshDeps)
${config.nix.extraOptions}
END
'';
target = "nix.conf"; # will be symlinked from /nix/etc/nix/nix.conf in activate-configuration.sh.
}
{ # Script executed when the shell starts as a non-login shell (user version). { # Script executed when the shell starts as a non-login shell (user version).
source = ./skel/bashrc; source = ./skel/bashrc;
target = "skel/.bashrc"; target = "skel/.bashrc";
@ -187,15 +161,6 @@ let
target = "ssmtp/ssmtp.conf"; target = "ssmtp/ssmtp.conf";
} }
# LDAP configuration.
++ optional config.users.ldap.enable {
source = import ./ldap.conf.nix {
inherit (pkgs) writeText;
inherit config;
};
target = "ldap.conf";
}
# A bunch of PAM configuration files for various programs. # A bunch of PAM configuration files for various programs.
++ (map ++ (map
(program: (program:
@ -241,13 +206,6 @@ let
target = "nix.machines"; target = "nix.machines";
} }
# unixODBC drivers (this solution is not perfect.. Because the user has to
# ask the admin to add a driver.. but it's an easy solution which works)
++ (let inis = config.environment.unixODBCDrivers pkgs;
in optional (inis != [] ) {
source = pkgs.writeText "odbcinst.ini" (pkgs.lib.concatStringsSep "\n" inis);
target = "odbcinst.ini";
})
; ;
in in

View File

@ -3,7 +3,8 @@
let let
inherit (pkgs.stringsWithDeps) textClosureOverridable noDepEntry; inherit (pkgs.stringsWithDeps) textClosureOverridable noDepEntry;
inherit (pkgs.lib) mkOption mergeTypedOption mergeAttrs mapRecordFlatten mapAttrs; inherit (pkgs.lib) mkOption mergeTypedOption mergeAttrs mapRecordFlatten
mapAttrs addErrorContext fold;
textClosure = steps: textClosure = steps:
textClosureOverridable steps ( textClosureOverridable steps (
@ -44,8 +45,9 @@ in
Activate the new configuration (i.e., update /etc, make accounts, Activate the new configuration (i.e., update /etc, make accounts,
and so on). and so on).
''; '';
merge = mergeTypedOption "script" builtins.isAttrs mergeAttrs; merge = mergeTypedOption "script" builtins.isAttrs (fold mergeAttrs {});
apply = set: let lib = addAttributeName set; in { apply = set:
let lib = addAttributeName set; in {
inherit lib; # used to fetch dependencies. inherit lib; # used to fetch dependencies.
script = aggregateScripts "activationScript" lib; script = aggregateScripts "activationScript" lib;
}; };

47
system/i18n.nix Normal file
View File

@ -0,0 +1,47 @@
{pkgs, config, ...}:
###### interface
let
inherit (pkgs.lib) mkOption mkIf;
options = {
i18n = {
defaultLocale = mkOption {
default = "en_US.UTF-8";
example = "nl_NL.UTF-8";
description = "
The default locale. It determines the language for program
messages, the format for dates and times, sort order, and so on.
It also determines the character set, such as UTF-8.
";
};
consoleFont = mkOption {
default = "lat9w-16";
example = "LatArCyrHeb-16";
description = "
The font used for the virtual consoles. Leave empty to use
whatever the <command>setfont</command> program considers the
default font.
";
};
consoleKeyMap = mkOption {
default = "us";
example = "fr";
description = "
The keyboard mapping table for the virtual consoles.
";
};
};
};
in
###### implementation
mkIf config.services.pulseaudio.enable {
require = [
options
];
}

View File

@ -0,0 +1,67 @@
{pkgs, config, ...}:
let
inherit (pkgs.lib) mergeOneOption mkOption mkIf;
in
{
require = [
{
environment = {
checkConfigurationOptions = mkOption {
default = true;
example = false;
description = "
If all configuration options must be checked. Non-existing options fail build.
";
};
nix = mkOption {
default = pkgs.nixUnstable;
example = pkgs.nixCustomFun /root/nix.tar.gz;
merge = mergeOneOption;
description = "
Use non-default Nix easily. Be careful, though, not to break everything.
";
};
extraPackages = mkOption {
default = [];
example = [pkgs.firefox pkgs.thunderbird];
description = "
This option allows you to add additional packages to the system
path. These packages are automatically available to all users,
and they are automatically updated every time you rebuild the
system configuration. (The latter is the main difference with
installing them in the default profile,
<filename>/nix/var/nix/profiles/default</filename>. The value
of this option must be a function that returns a list of
packages. The function will be called with the Nix Packages
collection as its argument for convenience.
";
};
pathsToLink = mkOption {
default = ["/bin" "/sbin" "/lib" "/share" "/man" "/info" "/etc"];
example = ["/"];
description = "
Lists directories to be symlinked in `/var/run/current-system/sw'.
";
};
cleanStart = mkOption {
default = false;
example = true;
description = "
There are some times when you want really small system for specific
purpose and do not want default package list. Setting
<varname>cleanStart</varname> to <literal>true</literal> allows you
to create a system with empty path - only extraPackages will be
included.
";
};
};
}
];
}

View File

@ -0,0 +1,98 @@
{pkgs, config, ...}:
###### interface
let
inherit (pkgs.lib) mkOption mkIf;
options = {
installer = {
nixpkgsURL = mkOption {
default = "";
example = http://nixos.org/releases/nix/nixpkgs-0.11pre7577;
description = "
URL of the Nixpkgs distribution to use when building the
installation CD.
";
};
repos = {
nixos = mkOption {
default = [ { type = "svn"; } ];
example = [ { type = "svn"; url = "https://svn.nixos.org/repos/nix/nixos/branches/stdenv-updates"; target = "/etc/nixos/nixos-stdenv-updates"; }
{ type = "git"; initialize = ''git clone git://mawercer.de/nixos $target''; update = "git pull origin"; target = "/etc/nixos/nixos-git"; }
];
description = ''
The NixOS repository from which the system will be built.
<command>nixos-checkout</command> will update all working
copies of the given repositories,
<command>nixos-rebuild</command> will use the first item
which has the attribute <literal>default = true</literal>
falling back to the first item. The type defines the
repository tool added to the path. It also defines a "valid"
repository. If the target directory already exists and it's
not valid it will be moved to the backup location
<filename><replaceable>dir</replaceable>-date</filename>.
For svn the default target and repositories are
<filename>/etc/nixos/nixos</filename> and
<filename>https://svn.nixos.org/repos/nix/nixos/trunk</filename>.
For git repositories update is called after initialization
when the repo is initialized. The initialize code is run
from working directory dirname
<replaceable>target</replaceable> and should create the
directory
<filename><replaceable>dir</replaceable></filename>. (<command>git
clone url nixos/nixpkgs/services</command> should do) For
the executables used see <option>repoTypes</option>.
'';
};
nixpkgs = mkOption {
default = [ { type = "svn"; } ];
description = "same as <option>repos.nixos</option>";
};
services = mkOption {
default = [ { type = "svn"; } ];
description = "same as <option>repos.nixos</option>";
};
};
repoTypes = mkOption {
default = {
svn = { valid = "[ -d .svn ]"; env = [ pkgs.coreutils pkgs.subversion ]; };
git = { valid = "[ -d .git ]"; env = [ pkgs.coreutils pkgs.git pkgs.gnused /* FIXME: use full path to sed in nix-pull */ ]; };
};
description = ''
Defines, for each supported version control system
(e.g. <literal>git</literal>), the dependencies for the
mechanism, as well as a test used to determine whether a
directory is a checkout created by that version control
system.
'';
};
manifests = mkOption {
default = [http://nixos.org/releases/nixpkgs/channels/nixpkgs-unstable/MANIFEST];
example =
[ http://nixos.org/releases/nixpkgs/channels/nixpkgs-unstable/MANIFEST
http://nixos.org/releases/nixpkgs/channels/nixpkgs-stable/MANIFEST
];
description = "
URLs of manifests to be downloaded when you run
<command>nixos-rebuild</command> to speed up builds.
";
};
};
};
in
###### implementation
mkIf config.services.pulseaudio.enable {
require = [
options
];
}

49
system/nixos-security.nix Normal file
View File

@ -0,0 +1,49 @@
{pkgs, config, ...}:
let
inherit (pkgs.lib) mergeOneOption mkOption mkIf;
in
{
require = [
{
security = {
setuidPrograms = mkOption {
default = [
"passwd" "su" "crontab" "ping" "ping6"
"fusermount" "wodim" "cdrdao" "growisofs"
];
description = "
Only the programs from system path listed her will be made setuid root
(through a wrapper program). It's better to set
<option>security.extraSetuidPrograms</option>.
";
};
extraSetuidPrograms = mkOption {
default = [];
example = ["fusermount"];
description = "
This option lists additional programs that must be made setuid
root.
";
};
setuidOwners = mkOption {
default = [];
example = [{
program = "sendmail";
owner = "nodody";
group = "postdrop";
setuid = false;
setgid = true;
}];
description = ''
List of non-trivial setuid programs from system path, like Postfix sendmail. Default
should probably be nobody:nogroup:false:false - if you are bothering
doing anything with a setuid program, "root.root u+s g-s" is not what
you are aiming at..
'';
};
};
}
];
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,43 @@
{pkgs, config, ...}:
###### interface
let
inherit (pkgs.lib) mkOption mkIf;
options = {
environment = {
unixODBCDrivers = mkOption {
default = [];
example = "map (x : x.ini) (with pkgs.unixODBCDrivers; [ mysql psql psqlng ] )";
description = ''
specifies unix odbc drivers to be registered at /etc/odbcinst.ini.
Maybe you also want to add pkgs.unixODBC to the system path to get a
command line client t connnect to odbc databases.
'';
};
};
};
in
###### implementation
# unixODBC drivers (this solution is not perfect.. Because the user has to
# ask the admin to add a driver.. but it's simple and works
mkIf (config.environment.unixODBCDrivers != []) {
require = [
options
];
environment = {
etc = [
{ source =
let inis = config.environment.unixODBCDrivers;
in pkgs.writeText "odbcinst.ini" (pkgs.lib.concatStringsSep "\n" inis);
target = "odbcinst.ini";
}
];
};
}

View File

@ -143,6 +143,9 @@ let
inherit (pkgs.stringsWithDeps) FullDepEntry; inherit (pkgs.stringsWithDeps) FullDepEntry;
activateLib = config.system.activationScripts.lib; activateLib = config.system.activationScripts.lib;
# keep this extra file so that cat can be used to pass special chars such as "`" which is used in the avahi daemon
usersFile = pkgs.writeText "users" (concatStringsSep "\n" (map serializedUser users));
in in
{ {
@ -157,7 +160,7 @@ in
activationScripts = { activationScripts = {
users = FullDepEntry '' users = FullDepEntry ''
while true; do cat ${usersFile} | while true; do
read name || break read name || break
read description read description
read uid read uid
@ -198,9 +201,7 @@ in
''${home:+--home "$home"} \ ''${home:+--home "$home"} \
--shell "$shell" --shell "$shell"
fi fi
done <<EndOfUserList done
${concatStringsSep "\n" (map serializedUser users)}
EndOfUserList
'' [ '' [
activateLib.groups activateLib.groups
]; ];

14
test/test-config-examples.sh Executable file
View File

@ -0,0 +1,14 @@
#!/bin/sh
# This script try to evaluate all configurations which are stored in
# doc/config-examples. This script is useful to ensure that examples are
# working with the current system.
pwd=$(pwd)
set -xe
for i in ../doc/config-examples/*.nix; do
NIXOS_CONFIG="$pwd/$i" nix-instantiate \
--eval-only --xml --strict > /dev/null 2>&1 \
../default.nix -A system
done
set +xe

View File

@ -1,5 +1,22 @@
{pkgs, config, ...}: {pkgs, config, ...}:
###### interface
let
inherit (pkgs.lib) mkOption mkIf;
options = {
powerManagement = {
enable = mkOption {
default = false;
description = "Whether to enable power management (ACPI daemon)";
};
};
};
in
###### implementation
let let
acpiConfDir = pkgs.runCommand "acpi-events" {} acpiConfDir = pkgs.runCommand "acpi-events" {}
@ -18,8 +35,6 @@ let
} }
''; '';
events = [powerEvent lidEvent acEvent];
# Called when the power button is pressed. # Called when the power button is pressed.
powerEvent = powerEvent =
{ name = "power-button"; { name = "power-button";
@ -64,12 +79,18 @@ let
''; '';
}; };
events = [powerEvent lidEvent acEvent];
in in
{ mkIf config.powerManagement.enable {
name = "acpid"; require = [
options
];
extraPath = [pkgs.acpid]; services = {
extraJobs = [{
name = "acpid";
job = '' job = ''
description "ACPI daemon" description "ACPI daemon"
@ -79,5 +100,6 @@ in
respawn ${pkgs.acpid}/sbin/acpid --foreground --confdir ${acpiConfDir} respawn ${pkgs.acpid}/sbin/acpid --foreground --confdir ${acpiConfDir}
''; '';
}];
};
} }

View File

@ -1,6 +1,209 @@
{config, pkgs}: {pkgs, config, ...}:
###### interface
let let
inherit (pkgs.lib) mkOption mkIf;
options = {
services = {
httpd = {
enable = mkOption {
default = false;
description = "
Whether to enable the Apache httpd server.
";
};
experimental = mkOption {
default = false;
description = "
Whether to use the new-style Apache configuration.
";
};
extraConfig = mkOption {
default = "";
description = "
These configuration lines will be passed verbatim to the apache config
";
};
extraModules = mkOption {
default = [];
example = [ "proxy_connect" { name = "php5_module"; path = "${pkgs.php}/modules/libphp5.so"; } ];
description = ''
Specifies additional Apache modules. These can be specified
as a string in the case of modules distributed with Apache,
or as an attribute set specifying the
<varname>name</varname> and <varname>path</varname> of the
module.
'';
};
logPerVirtualHost = mkOption {
default = false;
description = "
If enabled, each virtual host gets its own
<filename>access_log</filename> and
<filename>error_log</filename>, namely suffixed by the
<option>hostName</option> of the virtual host.
";
};
user = mkOption {
default = "wwwrun";
description = "
User account under which httpd runs. The account is created
automatically if it doesn't exist.
";
};
group = mkOption {
default = "wwwrun";
description = "
Group under which httpd runs. The account is created
automatically if it doesn't exist.
";
};
logDir = mkOption {
default = "/var/log/httpd";
description = "
Directory for Apache's log files. It is created automatically.
";
};
stateDir = mkOption {
default = "/var/run/httpd";
description = "
Directory for Apache's transient runtime state (such as PID
files). It is created automatically. Note that the default,
<filename>/var/run/httpd</filename>, is deleted at boot time.
";
};
mod_php = mkOption {
default = false;
description = "Whether to enable the PHP module.";
};
mod_jk = {
enable = mkOption {
default = false;
description = "Whether to enable the Apache Tomcat connector.";
};
applicationMappings = mkOption {
default = [];
description = "List of Java webapplications that should be mapped to the servlet container (Tomcat/JBoss)";
};
};
virtualHosts = mkOption {
default = [];
example = [
{ hostName = "foo";
documentRoot = "/data/webroot-foo";
}
{ hostName = "bar";
documentRoot = "/data/webroot-bar";
}
];
description = ''
Specification of the virtual hosts served by Apache. Each
element should be an attribute set specifying the
configuration of the virtual host. The available options
are the non-global options permissible for the main host.
'';
};
subservices = {
# !!! remove this
subversion = {
enable = mkOption {
default = false;
description = "
Whether to enable the Subversion subservice in the webserver.
";
};
notificationSender = mkOption {
default = "svn-server@example.org";
example = "svn-server@example.org";
description = "
The email address used in the Sender field of commit
notification messages sent by the Subversion subservice.
";
};
userCreationDomain = mkOption {
default = "example.org";
example = "example.org";
description = "
The domain from which user creation is allowed. A client can
only create a new user account if its IP address resolves to
this domain.
";
};
autoVersioning = mkOption {
default = false;
description = "
Whether you want the Subversion subservice to support
auto-versioning, which enables Subversion repositories to be
mounted as read/writable file systems on operating systems that
support WebDAV.
";
};
dataDir = mkOption {
default = "/no/such/path/exists";
description = "
Place to put SVN repository.
";
};
organization = {
name = mkOption {
default = null;
description = "
Name of the organization hosting the Subversion service.
";
};
url = mkOption {
default = null;
description = "
URL of the website of the organization hosting the Subversion service.
";
};
logo = mkOption {
default = null;
description = "
Logo the organization hosting the Subversion service.
";
};
};
};
};
} // # Include the options shared between the main server and virtual hosts.
(import ../../upstart-jobs/apache-httpd/per-server-options.nix {
inherit mkOption;
forMainServer = true;
});
};
};
###### implementation
mainCfg = config.services.httpd; mainCfg = config.services.httpd;
@ -361,20 +564,27 @@ let
in in
{
name = "httpd"; mkIf (config.services.httpd.enable && config.services.httpd.experimental) {
require = [
options
];
users = [ users = {
extraUsers = [
{ name = mainCfg.user; { name = mainCfg.user;
description = "Apache httpd user"; description = "Apache httpd user";
} }
]; ];
extraGroups = [
groups = [
{ name = mainCfg.group; { name = mainCfg.group;
} }
]; ];
};
services = {
extraJobs = [{
name = "httpd";
extraPath = [httpd] ++ concatMap (svc: svc.extraPath) allSubservices; extraPath = [httpd] ++ concatMap (svc: svc.extraPath) allSubservices;
@ -422,4 +632,7 @@ in
respawn ${httpd}/bin/httpd -f ${httpdConf} -DNO_DETACH respawn ${httpd}/bin/httpd -f ${httpdConf} -DNO_DETACH
''; '';
}];
};
} }

View File

@ -1,4 +1,52 @@
{config, pkgs}: {pkgs, config, ...}:
###### interface
let
inherit (pkgs.lib) mkOption mkIf;
options = {
services = {
bind = {
enable = mkOption {
default = false;
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 = [];
}];
};
};
};
};
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.bind; cfg = config.services.bind;
@ -52,7 +100,14 @@ let
confFile = pkgs.writeText "named.conf" namedConf; confFile = pkgs.writeText "named.conf" namedConf;
in in
{
mkIf config.services.bind.enable {
require = [
options
];
services = {
extraJobs = [{
name = "bind"; name = "bind";
job = '' job = ''
description "BIND name server job" description "BIND name server job"
@ -63,4 +118,6 @@ in
respawn ${pkgs.bind}/sbin/named -c ${confFile} -f respawn ${pkgs.bind}/sbin/named -c ${confFile} -f
''; '';
}];
};
} }

View File

@ -1,12 +1,58 @@
args: with args; {pkgs, config, ...}:
###### interface
let
inherit (pkgs.lib) mkOption mkIf;
options = {
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.
'';
};
};
};
};
in
###### implementation
let let
bitlbeeUid = (import ../system/ids.nix).uids.bitlbee; bitlbeeUid = (import ../system/ids.nix).uids.bitlbee;
inherit (config.services.bitlbee) portNumber interface;
in in
{
name = "bitlbee";
users = [ mkIf config.services.bitlbee.enable {
require = [
options
];
users = {
extraUsers = [
{ name = "bitlbee"; { name = "bitlbee";
uid = bitlbeeUid; uid = bitlbeeUid;
description = "BitlBee user"; description = "BitlBee user";
@ -14,27 +60,34 @@ in
} }
]; ];
groups = [ extraGroups = [
{ name = "bitlbee"; { name = "bitlbee";
gid = (import ../system/ids.nix).gids.bitlbee; gid = (import ../system/ids.nix).gids.bitlbee;
} }
]; ];
};
services = {
extraJobs = [{
name = "bitlbee";
job = '' job = ''
description "BitlBee IRC to other chat networks gateway" description "BitlBee IRC to other chat networks gateway"
start on network-interfaces/started start on network-interfaces/started
stop on network-interfaces/stop stop on network-interfaces/stop
start script start script
if ! test -d /var/lib/bitlbee if ! test -d /var/lib/bitlbee
then then
mkdir -p /var/lib/bitlbee mkdir -p /var/lib/bitlbee
fi fi
end script end script
respawn ${bitlbee}/sbin/bitlbee -F -p ${toString portNumber} \ respawn ${pkgs.bitlbee}/sbin/bitlbee -F -p ${toString portNumber} \
-i ${interface} -u bitlbee -i ${interface} -u bitlbee
''; '';
}];
};
} }

View File

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

View File

@ -1,4 +1,26 @@
{config, pkgs, modprobe}: {pkgs, config, ...}:
###### interface
let
inherit (pkgs.lib) mkOption mkIf;
options = {
services = {
printing = {
enable = mkOption {
default = false;
description = "
Whether to enable printing support through the CUPS daemon.
";
};
};
};
};
in
###### implementation
let let
@ -7,6 +29,8 @@ let
inherit (pkgs) cups; inherit (pkgs) cups;
modprobe = config.system.sbin.modprobe;
# Here we can enable additional backends, filters, etc. that are not # Here we can enable additional backends, filters, etc. that are not
# part of CUPS itself, e.g. the SMB backend is part of Samba. Since # part of CUPS itself, e.g. the SMB backend is part of Samba. Since
@ -101,7 +125,14 @@ let
in in
{
mkIf config.services.pulseaudio.enable {
require = [
options
];
services = {
extraJobs = [{
name = "cupsd"; name = "cupsd";
extraPath = [cups]; extraPath = [cups];
@ -133,5 +164,6 @@ in
respawn ${cups}/sbin/cupsd -c ${cupsdConfig} -F respawn ${cups}/sbin/cupsd -c ${cupsdConfig} -F
''; '';
}];
};
} }

View File

@ -19,7 +19,7 @@ let
exec sh -c "echo 'hello world' | ${pkgs.netcat}/bin/nc -l -p 9000" exec sh -c "echo 'hello world' | ${pkgs.netcat}/bin/nc -l -p 9000"
''; '';
} ]; } ];
# should have some checks to everify the syntax # should have some checks to verify the syntax
merge = pkgs.lib.mergeListOption; merge = pkgs.lib.mergeListOption;
description = " description = "
Additional Upstart jobs. Additional Upstart jobs.
@ -66,373 +66,9 @@ let
optional = cond: service: pkgs.lib.optional cond (makeJob service); optional = cond: service: pkgs.lib.optional cond (makeJob service);
requiredTTYs = requiredTTYs = config.requiredTTYs;
config.services.mingetty.ttys
++ config.boot.extraTTYs
++ [config.services.syslogd.tty];
# looks for a job file foreach attr name found in services from config jobs = map makeJob []
# passes { thisConfig, config, pkgs }
# a job must return { options = {}; job =; }
# options is the same format as options.nix, but only contains documentation for this job
# TODO check validation
newProposalJobs =
(
let
inherit (pkgs.lib) getAttr;
inherit (builtins) attrNames pathExists map;
services = getAttr [ "servicesProposal" ] {} config;
nameToJobs = name : (
(
let p = ./new-proposal + "/${name}.nix";
p2 = ./new-proposal + "/${name}/default.nix";
thisConfig = getAttr [ name ] {} services;
path = [name];
args = confgiV : {
inherit config pkgs thisConfig path;
lib = pkgs.lib;
upstartHelpers = { # some useful functions
inherit configV; # the first time a error function is passed to get the option list
# the second time a function is passed getting the option for you automatically,
# either returning the default option or the user supplied value (the function apply is applied when given)
# maybe this is complicated, but easy to use (IMHO)
mkOption = pkgs.lib.mkOption; # the same function used in options.nix
autoGeneratedEtcFile = { name, commentChar ? "#", content } :
{ source = pkgs.writeText name
("${commentChar} nixos autogenerated etc file based on /etc/nixos/configuration.nix\n" + content);
target = name;
};
};
};
jobFunc = if pathExists p
then import p
else if pathExists p2 then import p2
else abort "service ${name} requested but there is no ${p}.nix or ${p}/default.nix file!";
options = (jobFunc (args (abort "you can't use configV within options!"))).options;
errorWhere = name : "${name} of service ${builtins.toString path}";
configV = name : if (__hasAttr name options ) then
let opt = (__getAttr name options ); # this config option description
in if (__hasAttr name thisConfig )
then let v = (__getAttr name thisConfig); in if opt ? apply then opt.apply v else v
else if opt ? default then opt.default else abort "you need to specify the configuration option ${errorWhere name}"
else abort "unkown option ${errorWhere name}";
checkConfig = config.environment.checkConfigurationOptions;
in # TODO: pass path to checker so it can show full path in the abort case
pkgs.checker ( (jobFunc (args configV)).jobs )
checkConfig
options
thisConfig
));
in pkgs.lib.concatLists ( map nameToJobs (attrNames services)));
jobs = map makeJob
(newProposalJobs ++ [
# Syslogd.
(import ../upstart-jobs/syslogd.nix {
inherit (pkgs) sysklogd writeText;
inherit config;
})
# Klogd.
(import ../upstart-jobs/klogd.nix {
inherit (pkgs) sysklogd writeText;
inherit config;
})
# The udev daemon creates devices nodes and runs programs when
# hardware events occur.
(import ../upstart-jobs/udev.nix {
inherit modprobe config;
inherit (pkgs) stdenv writeText substituteAll udev procps;
inherit (pkgs.lib) cleanSource;
firmwareDirs = config.services.udev.addFirmware;
extraUdevPkgs = config.services.udev.addUdevPkgs;
})
# Makes LVM logical volumes available.
(import ../upstart-jobs/lvm.nix {
inherit modprobe;
inherit (pkgs) lvm2 devicemapper;
})
# Activate software RAID arrays.
(import ../upstart-jobs/swraid.nix {
inherit modprobe;
inherit (pkgs) mdadm;
})
# Mount file systems.
(import ../upstart-jobs/filesystems.nix {
inherit mount;
inherit (pkgs) utillinux e2fsprogs;
fileSystems = config.fileSystems;
})
# Swapping.
(import ../upstart-jobs/swap.nix {
inherit (pkgs) utillinux lib;
swapDevices = config.swapDevices;
})
# Network interfaces.
(import ../upstart-jobs/network-interfaces.nix {
inherit modprobe config;
inherit (pkgs) nettools wirelesstools bash writeText;
})
# Nix daemon - required for multi-user Nix.
(import ../upstart-jobs/nix-daemon.nix {
inherit config pkgs nix nixEnvVars;
})
# Name service cache daemon.
(import ../upstart-jobs/nscd.nix {
inherit (pkgs) glibc;
inherit nssModulesPath;
})
# Console font and keyboard maps.
(import ../upstart-jobs/kbd.nix {
inherit (pkgs) glibc kbd gzip;
ttyNumbers = requiredTTYs;
defaultLocale = config.i18n.defaultLocale;
consoleFont = config.i18n.consoleFont;
consoleKeyMap = config.i18n.consoleKeyMap;
})
# Handles the maintenance/stalled event (single-user shell).
(import ../upstart-jobs/maintenance-shell.nix {
inherit (pkgs) bash;
})
# Ctrl-alt-delete action.
(import ../upstart-jobs/ctrl-alt-delete.nix)
])
# ifplugd daemon for monitoring Ethernet cables.
++ optional config.networking.interfaceMonitor.enable
(import ../upstart-jobs/ifplugd.nix {
inherit (pkgs) ifplugd writeScript bash;
inherit config;
})
# DHCP server.
++ optional config.services.dhcpd.enable
(import ../upstart-jobs/dhcpd.nix {
inherit pkgs config;
})
# SSH daemon.
++ optional config.services.sshd.enable
(import ../upstart-jobs/sshd.nix {
inherit (pkgs) writeText openssh glibc;
inherit (pkgs.xorg) xauth;
inherit nssModulesPath;
inherit (config.services.sshd) forwardX11 allowSFTP permitRootLogin gatewayPorts;
})
# GNU lshd SSH2 deamon.
++ optional config.services.lshd.enable
(import ../upstart-jobs/lshd.nix {
inherit (pkgs) lib;
inherit (pkgs) lsh;
inherit (pkgs.xorg) xauth;
inherit nssModulesPath;
lshdConfig = config.services.lshd;
})
# GNUnet daemon.
++ optional config.services.gnunet.enable
(import ../upstart-jobs/gnunet.nix {
inherit (pkgs) gnunet lib writeText;
gnunetConfig = config.services.gnunet;
})
# NTP daemon.
++ optional config.services.ntp.enable
(import ../upstart-jobs/ntpd.nix {
inherit modprobe;
inherit (pkgs) ntp glibc writeText;
servers = config.services.ntp.servers;
})
# portmap daemon.
++ optional config.services.portmap.enable
(import ../upstart-jobs/portmap.nix {
inherit (pkgs) makePortmap;
})
# Apache httpd.
++ optional (config.services.httpd.enable && !config.services.httpd.experimental)
(import ../upstart-jobs/httpd.nix {
inherit config pkgs;
inherit (pkgs) glibc;
extraConfig = pkgs.lib.concatStringsSep "\n"
(map (job: job.extraHttpdConfig) jobs);
})
# Apache httpd (new style).
++ optional (config.services.httpd.enable && config.services.httpd.experimental)
(import ../upstart-jobs/apache-httpd {
inherit config pkgs;
})
# MySQL server
++ optional config.services.mysql.enable
(import ../upstart-jobs/mysql.nix {
inherit config pkgs;
})
# Postgres SQL server
++ optional config.services.postgresql.enable
(import ../upstart-jobs/postgresql.nix {
inherit config pkgs;
})
# EJabberd service
++ optional config.services.ejabberd.enable
(import ../upstart-jobs/ejabberd.nix {
inherit config pkgs;
})
# OpenFire XMPP server
++ optional config.services.openfire.enable
(import ../upstart-jobs/openfire.nix {
inherit config pkgs;
})
# JBoss service
++ optional config.services.jboss.enable
(import ../upstart-jobs/jboss.nix {
inherit config pkgs;
})
# Apache Tomcat service
++ optional config.services.tomcat.enable
(import ../upstart-jobs/tomcat.nix {
inherit config pkgs;
})
# Samba service.
++ optional config.services.samba.enable
(import ../upstart-jobs/samba.nix {
inherit pkgs;
inherit (pkgs) glibc samba;
})
# CUPS (printing) daemon.
++ optional config.services.printing.enable
(import ../upstart-jobs/cupsd.nix {
inherit config pkgs modprobe;
})
# Gateway6
++ optional config.services.gw6c.enable
(import ../upstart-jobs/gw6c.nix {
inherit config pkgs;
})
# VSFTPd server
++ optional config.services.vsftpd.enable
(import ../upstart-jobs/vsftpd.nix {
inherit (pkgs) vsftpd;
inherit (config.services.vsftpd) anonymousUser
writeEnable anonymousUploadEnable anonymousMkdirEnable;
})
# X Font Server
++ optional config.services.xfs.enable
(import ../upstart-jobs/xfs.nix {
inherit config pkgs;
})
++ optional config.services.ircdHybrid.enable
(import ../upstart-jobs/ircd-hybrid.nix {
inherit config pkgs;
})
++ optional config.services.bitlbee.enable
(import ../upstart-jobs/bitlbee.nix {
inherit (pkgs) bitlbee;
inherit (config.services.bitlbee) portNumber interface;
})
# ACPI daemon.
++ optional config.powerManagement.enable
(import ../upstart-jobs/acpid.nix {
inherit config pkgs;
})
# Postfix mail server.
++ optional config.services.postfix.enable
(import ../upstart-jobs/postfix.nix {
inherit config pkgs;
})
# Dovecot POP3/IMAP server.
++ optional config.services.dovecot.enable
(import ../upstart-jobs/dovecot.nix {
inherit config pkgs;
})
# ISC BIND domain name server.
++ optional config.services.bind.enable
(import ../upstart-jobs/bind.nix {
inherit config pkgs;
})
# Handles the reboot/halt events.
++ (map
(event: makeJob (import ../upstart-jobs/halt.nix {
inherit (pkgs) bash utillinux;
inherit event;
}))
["reboot" "halt" "system-halt" "power-off"]
)
# The terminals on ttyX.
++ (map
(ttyNumber: makeJob (import ../upstart-jobs/mingetty.nix {
inherit (pkgs) mingetty;
inherit ttyNumber;
loginProgram = "${pkgs.pam_login}/bin/login";
}))
(config.services.mingetty.ttys)
)
# Transparent TTY backgrounds.
++ optional (config.services.ttyBackgrounds.enable && kernelPackages.splashutils != null)
(import ../upstart-jobs/tty-backgrounds.nix {
inherit (pkgs) stdenv;
inherit (kernelPackages) splashutils;
backgrounds =
let
specificThemes =
config.services.ttyBackgrounds.defaultSpecificThemes
++ config.services.ttyBackgrounds.specificThemes;
overridenTTYs = map (x: x.tty) specificThemes;
# Use the default theme for all the mingetty ttys and for the
# syslog tty, except those for which a specific theme is
# specified.
defaultTTYs =
pkgs.lib.filter (x: !(pkgs.lib.elem x overridenTTYs)) requiredTTYs;
in
(map (ttyNumber: {
tty = ttyNumber;
theme = config.services.ttyBackgrounds.defaultTheme;
}) defaultTTYs)
++ specificThemes;
})
# User-defined events. # User-defined events.
++ (map makeJob (config.services.extraJobs)); ++ (map makeJob (config.services.extraJobs));

View File

@ -1,4 +1,79 @@
{pkgs, config}: {pkgs, config, ...}:
###### interface
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
@ -25,7 +100,14 @@ let
in in
{
mkIf config.services.dhcpd.enable {
require = [
options
];
services = {
extraJobs = [{
name = "dhcpd"; name = "dhcpd";
job = '' job = ''
@ -46,5 +128,6 @@ in
end script end script
''; '';
}];
};
} }

View File

@ -1,4 +1,45 @@
{config, pkgs}: {pkgs, config, ...}:
###### interface
let
inherit (pkgs.lib) mkOption mkIf;
options = {
services = {
dovecot = {
enable = mkOption {
default = false;
description = "Whether to enable dovecot POP3/IMAP server.";
};
user = mkOption {
default = "dovecot";
description = "dovecot user name";
};
group = mkOption {
default = "dovecot";
description = "dovecot group name";
};
sslServerCert = mkOption {
default = "";
description = "Server certificate";
};
sslCACert = mkOption {
default = "";
description = "CA certificate used by server certificate";
};
sslServerKey = mkOption {
default = "";
description = "Server key";
};
};
};
};
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";
@ -54,18 +95,36 @@ let
''; '';
in in
{
name = "dovecot"; mkIf config.services.dovecot.enable {
users = [{
require = [
options
];
environment = {
etc = [{
source = pamdFile;
target = "pam.d/dovecot";
}];
};
users = {
extraUsers = [{
name = cfg.user; name = cfg.user;
uid = idList.uids.dovecot; uid = idList.uids.dovecot;
description = "Dovecot user"; description = "Dovecot user";
group = cfg.group; group = cfg.group;
}]; }];
groups = [{ extraGroups = [{
name = cfg.group; name = cfg.group;
gid = idList.gids.dovecot; gid = idList.gids.dovecot;
}]; }];
};
services = {
extraJobs = [{
name = "dovecot";
job = '' job = ''
description "Dovecot IMAP/POP3 server" description "Dovecot IMAP/POP3 server"
@ -81,9 +140,6 @@ in
respawn ${pkgs.dovecot}/sbin/dovecot -F -c ${confFile} respawn ${pkgs.dovecot}/sbin/dovecot -F -c ${confFile}
''; '';
extraEtc = [{
source = pamdFile;
target = "pam.d/dovecot";
}]; }];
};
} }

View File

@ -1,11 +1,58 @@
args: with args; {pkgs, config, ...}:
###### interface
let
inherit (pkgs.lib) mkOption mkIf;
options = {
services = {
ejabberd = {
enable = mkOption {
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";
};
};
};
};
in
###### implementation
let let
cfg = config.services.ejabberd; cfg = config.services.ejabberd;
in in
{
mkIf config.services.ejabberd.enable {
require = [
options
];
services = {
extraJobs = [{
name = "ejabberd"; name = "ejabberd";
job = '' job = ''
@ -33,4 +80,6 @@ in
${pkgs.ejabberd}/sbin/ejabberdctl stop ${pkgs.ejabberd}/sbin/ejabberdctl stop
end script end script
''; '';
}];
};
} }

View File

@ -1,25 +1,23 @@
{utillinux, e2fsprogs, fileSystems, mount}: {pkgs, config, ...}:
###### implementation
let let
inherit (pkgs) e2fsprogs;
# !!! use XML
mountPoints = map (fs: fs.mountPoint) fileSystems; mountPoints = map (fs: fs.mountPoint) fileSystems;
fileSystems = config.fileSystems;
devices = map (fs: if fs ? device then fs.device else "LABEL=" + fs.label) fileSystems; devices = map (fs: if fs ? device then fs.device else "LABEL=" + fs.label) fileSystems;
fsTypes = map (fs: if fs ? fsType then fs.fsType else "auto") fileSystems; fsTypes = map (fs: if fs ? fsType then fs.fsType else "auto") fileSystems;
optionss = map (fs: if fs ? options then fs.options else "defaults") fileSystems; optionss = map (fs: if fs ? options then fs.options else "defaults") fileSystems;
autocreates = map (fs: if fs ? autocreate then fs.autocreate else "0") fileSystems; autocreates = map (fs: if fs ? autocreate then fs.autocreate else "0") fileSystems;
mount = config.system.sbin.mount;
in job = ''
start on startup
start on new-devices
start on ip-up
{ script
name = "filesystems";
job = "
start on startup
start on new-devices
start on ip-up
script
PATH=${e2fsprogs}/sbin:$PATH PATH=${e2fsprogs}/sbin:$PATH
mountPoints=(${toString mountPoints}) mountPoints=(${toString mountPoints})
@ -34,36 +32,36 @@ script
# mount opportunities may have become available (such as images # mount opportunities may have become available (such as images
# for loopback mounts). # for loopback mounts).
while test -n \"$newDevices\"; do while test -n "$newDevices"; do
newDevices= newDevices=
for ((n = 0; n < \${#mountPoints[*]}; n++)); do for ((n = 0; n < ''${#mountPoints[*]}; n++)); do
mountPoint=\${mountPoints[$n]} mountPoint=''${mountPoints[$n]}
device=\${devices[$n]} device=''${devices[$n]}
fsType=\${fsTypes[$n]} fsType=''${fsTypes[$n]}
options=\${optionss[$n]} options=''${optionss[$n]}
autocreate=\${autocreates[$n]} autocreate=''${autocreates[$n]}
isLabel= isLabel=
if echo \"$device\" | grep -q '^LABEL='; then isLabel=1; fi if echo "$device" | grep -q '^LABEL='; then isLabel=1; fi
isPseudo= isPseudo=
if test \"$fsType\" = \"nfs\" || test \"$fsType\" = \"tmpfs\" || if test "$fsType" = "nfs" || test "$fsType" = "tmpfs" ||
test \"$fsType\" = \"ext3cow\"; then isPseudo=1; fi test "$fsType" = "ext3cow"; then isPseudo=1; fi
if ! test -n \"$isLabel\" -o -n \"$isPseudo\" -o -e \"$device\"; then if ! test -n "$isLabel" -o -n "$isPseudo" -o -e "$device"; then
echo \"skipping $device, doesn't exist (yet)\" echo "skipping $device, doesn't exist (yet)"
continue continue
fi fi
# !!! quick hack: if mount point already exists, try a # !!! quick hack: if mount point already exists, try a
# remount to change the options but nothing else. # remount to change the options but nothing else.
if cat /proc/mounts | grep -F -q \" $mountPoint \"; then if cat /proc/mounts | grep -F -q " $mountPoint "; then
echo \"remounting $device on $mountPoint\" echo "remounting $device on $mountPoint"
${mount}/bin/mount -t \"$fsType\" \\ ${mount}/bin/mount -t "$fsType" \
-o remount,\"$options\" \\ -o remount,"$options" \
\"$device\" \"$mountPoint\" || true "$device" "$mountPoint" || true
continue continue
fi fi
@ -72,41 +70,41 @@ script
# contains more accurate info when using loop devices. # contains more accurate info when using loop devices.
# !!! not very smart about labels yet; should resolve the label somehow. # !!! not very smart about labels yet; should resolve the label somehow.
if test -z \"$isLabel\" -a -z \"$isPseudo\"; then if test -z "$isLabel" -a -z "$isPseudo"; then
device=$(readlink -f \"$device\") device=$(readlink -f "$device")
prevMountPoint=$( prevMountPoint=$(
cat /etc/mtab \\ cat /etc/mtab \
| grep \"^$device \" \\ | grep "^$device " \
| sed 's|^[^ ]\\+ \\+\\([^ ]\\+\\).*|\\1|' \\ | sed 's|^[^ ]\+ \+\([^ ]\+\).*|\1|' \
) )
if test \"$prevMountPoint\" = \"$mountPoint\"; then if test "$prevMountPoint" = "$mountPoint"; then
echo \"remounting $device on $mountPoint\" echo "remounting $device on $mountPoint"
${mount}/bin/mount -t \"$fsType\" \\ ${mount}/bin/mount -t "$fsType" \
-o remount,\"$options\" \\ -o remount,"$options" \
\"$device\" \"$mountPoint\" || true "$device" "$mountPoint" || true
continue continue
fi fi
if test -n \"$prevMountPoint\"; then if test -n "$prevMountPoint"; then
echo \"unmount $device from $prevMountPoint\" echo "unmount $device from $prevMountPoint"
${mount}/bin/umount \"$prevMountPoint\" || true ${mount}/bin/umount "$prevMountPoint" || true
fi fi
fi fi
echo \"mounting $device on $mountPoint\" echo "mounting $device on $mountPoint"
# !!! should do something with the result; also prevent repeated fscks. # !!! should do something with the result; also prevent repeated fscks.
if test -z \"$isPseudo\"; then if test -z "$isPseudo"; then
fsck -a \"$device\" || true fsck -a "$device" || true
fi fi
if test \"\$autocreate\" = 1; then mkdir -p \"\$mountPoint\"; fi if test "$autocreate" = 1; then mkdir -p "$mountPoint"; fi
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
@ -114,7 +112,15 @@ script
done done
end script end script
"; '';
in
{
services = {
extraJobs = [{
name = "filesystems";
inherit job;
}];
};
} }

View File

@ -1,21 +1,175 @@
{ gnunet, gnunetConfig, lib, writeText }: {pkgs, config, ...}:
assert gnunetConfig.enable; ###### interface
let
inherit (pkgs.lib) mkOption mkIf;
{ options = {
name = "gnunetd"; services = {
gnunet = {
users = [ 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;
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.
'';
};
};
};
};
in
###### implementation
mkIf config.services.gnunet.enable {
require = [
options
];
users = {
extraUsers = [
{ name = "gnunetd"; { name = "gnunetd";
uid = (import ../system/ids.nix).uids.gnunetd; uid = (import ../system/ids.nix).uids.gnunetd;
description = "GNUnet Daemon User"; description = "GNUnet Daemon User";
home = "/var/empty"; home = "/var/empty";
} }
]; ];
};
services = {
extraJobs = [{
name = "gnunetd";
job = job =
with gnunetConfig; with config.services.gnunet;
let configFile = writeText "gnunetd.conf" '' let
inherit (pkgs) lib gnunet;
configFile = pkgs.writeText "gnunetd.conf" ''
[PATHS] [PATHS]
GNUNETD_HOME = ${home} GNUNETD_HOME = ${home}
@ -42,23 +196,23 @@ assert gnunetConfig.enable;
${extraOptions} ${extraOptions}
''; '';
in '' in ''
description "The GNUnet Daemon" description "The GNUnet Daemon"
start on network-interfaces/started start on network-interfaces/started
stop on network-interfaces/stop stop on network-interfaces/stop
start script start script
test -d "${home}" || \ test -d "${home}" || \
( mkdir -m 755 -p "${home}" && chown -R gnunetd:users "${home}") ( mkdir -m 755 -p "${home}" && chown -R gnunetd:users "${home}")
end script end script
respawn ${gnunet}/bin/gnunetd \ 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="${logLevel}"
''; '';
}];
};
} }

View File

@ -1,8 +1,106 @@
{config, pkgs}: {pkgs, config, ...}:
###### interface
let
inherit (pkgs.lib) mkOption mkIf;
options = {
services = {
gw6c = {
enable = mkOption {
default = false;
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
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
let let
cfg = config.services.gw6c; cfg = config.services.gw6c;
procps = pkgs.procps; procps = pkgs.procps;
gw6cService = import ../services/gw6c { gw6cService = import ../../services/gw6c {
inherit (pkgs) stdenv gw6c coreutils inherit (pkgs) stdenv gw6c coreutils
procps upstart iputils gnused procps upstart iputils gnused
gnugrep seccureUser writeScript; gnugrep seccureUser writeScript;
@ -17,16 +115,26 @@ let
waitPingableBroker = cfg.waitPingableBroker; waitPingableBroker = cfg.waitPingableBroker;
}; };
in in
{
mkIf config.services.gw6c.enable {
require = [
options
];
services = {
extraJobs = [{
name = "gw6c"; name = "gw6c";
users = []; users = [];
groups = []; groups = [];
job = " job = ''
description \"Gateway6 client\" description \"Gateway6 client\"
start on ${ if cfg.autorun then "network-interfaces/started" else "never" } start on ${ if cfg.autorun then "network-interfaces/started" else "never" }
stop on network-interfaces/stop stop on network-interfaces/stop
respawn ${gw6cService}/bin/control start respawn ${gw6cService}/bin/control start
"; '';
}];
};
} }

View File

@ -1,29 +1,38 @@
{bash, event, utillinux}: {pkgs, config, ...}:
###### implementation
/* FIXME
assert event == "reboot" assert event == "reboot"
|| event == "halt" || event == "halt"
|| event == "system-halt" || event == "system-halt"
|| event == "power-off"; || event == "power-off";
*/
{ let
inherit (pkgs) bash utillinux;
jobFun = event : {
name = "sys-" + event; name = "sys-" + event;
job = " job = ''
start on ${event} 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
echo \"\" echo ""
echo \"<<< SYSTEM SHUTDOWN >>>\" echo "<<< SYSTEM SHUTDOWN >>>"
echo \"\" echo ""
export PATH=${utillinux}/bin:${utillinux}/sbin:$PATH export PATH=${utillinux}/bin:${utillinux}/sbin:$PATH
# Set the hardware clock to the system time. # Set the hardware clock to the system time.
echo \"Setting the hardware clock...\" echo "Setting the hardware clock..."
hwclock --systohc --utc || true hwclock --systohc --utc || true
@ -32,53 +41,53 @@ script
# Kill all remaining processes except init and this one. # Kill all remaining processes except init and this one.
echo \"Sending the TERM signal to all processes...\" echo "Sending the TERM signal to all processes..."
kill -TERM -1 || true kill -TERM -1 || true
sleep 1 # wait briefly sleep 1 # wait briefly
echo \"Sending the KILL signal to all processes...\" echo "Sending the KILL signal to all processes..."
kill -KILL -1 || true kill -KILL -1 || true
# Unmount helper functions. # Unmount helper functions.
getMountPoints() { getMountPoints() {
cat /proc/mounts \\ cat /proc/mounts \
| grep -v '^rootfs' \\ | grep -v '^rootfs' \
| sed 's|^[^ ]\\+ \\+\\([^ ]\\+\\).*|\\1|' \\ | sed 's|^[^ ]\+ \+\([^ ]\+\).*|\1|' \
| grep -v '/proc\\|/sys\\|/dev' | grep -v '/proc\|/sys\|/dev'
} }
getDevice() { getDevice() {
local mountPoint=$1 local mountPoint=$1
cat /proc/mounts \\ cat /proc/mounts \
| grep -v '^rootfs' \\ | grep -v '^rootfs' \
| grep \"^[^ ]\\+ \\+$mountPoint \\+\" \\ | grep "^[^ ]\+ \+$mountPoint \+" \
| sed 's|^\\([^ ]\\+\\).*|\\1|' | sed 's|^\([^ ]\+\).*|\1|'
} }
# Unmount file systems. We repeat this until no more file systems # Unmount file systems. We repeat this until no more file systems
# can be unmounted. This is to handle loopback devices, file # can be unmounted. This is to handle loopback devices, file
# systems mounted on other file systems and so on. # systems mounted on other file systems and so on.
tryAgain=1 tryAgain=1
while test -n \"$tryAgain\"; do while test -n "$tryAgain"; do
tryAgain= tryAgain=
for mp in $(getMountPoints); do for mp in $(getMountPoints); do
device=$(getDevice $mp) device=$(getDevice $mp)
echo \"unmounting $mp...\" echo "unmounting $mp..."
if umount -f -n \"$mp\"; then if umount -f -n "$mp"; then
if test \"$mp\" != /; then tryAgain=1; fi if test "$mp" != /; then tryAgain=1; fi
else else
mount -n -o remount,ro \"$mp\" || true mount -n -o remount,ro "$mp" || true
fi fi
# Hack: work around a bug in mount (mount -o remount on a # Hack: work around a bug in mount (mount -o remount on a
# loop device forgets the loop=/dev/loopN entry in # loop device forgets the loop=/dev/loopN entry in
# /etc/mtab). # /etc/mtab).
if echo \"$device\" | grep -q '/dev/loop'; then if echo "$device" | grep -q '/dev/loop'; then
echo \"removing loop device $device...\" echo "removing loop device $device..."
losetup -d \"$device\" || true losetup -d "$device" || true
fi fi
done done
done done
@ -97,7 +106,15 @@ script
exec halt -f -p exec halt -f -p
fi fi
end script end script
"; '';
};
in
{
services = {
extraJobs = map jobFun ["reboot" "halt" "system-halt" "power-off"];
};
} }

View File

@ -1,4 +1,14 @@
{config, pkgs, glibc, extraConfig}: {pkgs, config, ...}:
###### interface
let
inherit (pkgs.lib) mkOption mkIf;
# options have been moved to the apache-httpd/default.nix file
in
###### implementation
let let
@ -22,6 +32,11 @@ let
startingDependency = if config.services.gw6c.enable && config.services.gw6c.autorun then "gw6c" else "network-interfaces"; startingDependency = if config.services.gw6c.enable && config.services.gw6c.autorun then "gw6c" else "network-interfaces";
extraConfig = pkgs.lib.concatStringsSep "\n"
(pkgs.lib.catAttrs "extraHttpdConfig" config.services.extraJobs);
webServer = import ../../services/apache-httpd { webServer = import ../../services/apache-httpd {
inherit (pkgs) apacheHttpd coreutils; inherit (pkgs) apacheHttpd coreutils;
stdenv = pkgs.stdenv; stdenv = pkgs.stdenv;
@ -32,6 +47,7 @@ let
user group adminAddr logDir stateDir user group adminAddr logDir stateDir
applicationMappings; applicationMappings;
noUserDir = !cfg.enableUserDir; noUserDir = !cfg.enableUserDir;
extraDirectories = extraConfig + "\n" + cfg.extraConfig; extraDirectories = extraConfig + "\n" + cfg.extraConfig;
subServices = subServices =
@ -72,41 +88,47 @@ let
) )
) )
) )
) );
/* ++
(optional cfg.extraSubservices.enable
(map (service : service webServer pkgs) cfg.extraSubservices.services)
) */;
}; };
in in
{ mkIf (config.services.httpd.enable && !config.services.httpd.experimental) {
name = "httpd";
users = [ require = [
# options have been moved to the apache-httpd/default.nix file
];
users = {
extraUsers = [
{ name = user; { name = user;
description = "Apache httpd user"; description = "Apache httpd user";
} }
]; ];
groups = [ extraGroups = [
{ name = group; { name = group;
} }
]; ];
};
job = " services = {
description \"Apache HTTPD\" extraJobs = [{
name = "httpd";
start on ${startingDependency}/started job = ''
stop on ${startingDependency}/stop description \"Apache HTTPD\"
start script start on ${startingDependency}/started
stop on ${startingDependency}/stop
start script
${webServer}/bin/control prepare ${webServer}/bin/control prepare
end script end script
respawn ${webServer}/bin/control run respawn ${webServer}/bin/control run
"; '';
}];
};
} }

View File

@ -1,7 +1,42 @@
{ifplugd, config, writeScript, bash}: {pkgs, config, ...}:
###### interface
let
inherit (pkgs.lib) mkOption mkIf;
options = {
networking = {
interfaceMonitor = {
enable = mkOption {
default = false;
description = "
If <literal>true</literal>, monitor Ethernet interfaces for
cables being plugged in or unplugged. When this occurs, the
<command>dhclient</command> service is restarted to
automatically obtain a new IP address. This is useful for
roaming users (laptops).
";
};
beep = mkOption {
default = false;
description = "
If <literal>true</literal>, beep when an Ethernet cable is
plugged in or unplugged.
";
};
};
};
};
in
###### implementation
let let
inherit (pkgs) ifplugd writeScript bash;
# The ifplugd action script, which is called whenever the link # The ifplugd action script, which is called whenever the link
# status changes (i.e., a cable is plugged in or unplugged). We do # status changes (i.e., a cable is plugged in or unplugged). We do
# nothing when a cable is unplugged. When a cable is plugged in, we # nothing when a cable is unplugged. When a cable is plugged in, we
@ -17,19 +52,27 @@ let
in in
{ mkIf config.networking.interfaceMonitor.enable {
require = [
options
];
services = {
extraJobs = [{
name = "ifplugd"; name = "ifplugd";
extraPath = [ifplugd]; extraPath = [ifplugd];
job = " job = ''
description \"Network interface connectivity monitor\" description "Network interface connectivity monitor"
start on network-interfaces/started start on network-interfaces/started
stop on network-interfaces/stop stop on network-interfaces/stop
respawn ${ifplugd}/sbin/ifplugd --no-daemon --no-startup --no-shutdown \\
${if config.networking.interfaceMonitor.beep then "" else "--no-beep"} \\
--run ${plugScript}";
respawn ${ifplugd}/sbin/ifplugd --no-daemon --no-startup --no-shutdown \
${if config.networking.interfaceMonitor.beep then "" else "--no-beep"} \
--run ${plugScript}
'';
}];
};
} }

View File

@ -1,7 +1,90 @@
{config, pkgs}: {pkgs, config, ...}:
###### interface
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 ../services/ircd-hybrid { ircdService = import ../../services/ircd-hybrid {
stdenv = pkgs.stdenv; stdenv = pkgs.stdenv;
inherit (pkgs) ircdHybrid coreutils inherit (pkgs) ircdHybrid coreutils
su iproute gnugrep procps; su iproute gnugrep procps;
@ -20,19 +103,28 @@ let
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 = {
extraJobs = [{
name = "ircd-hybrid"; name = "ircd-hybrid";
users = [ { users = [ {
name = "ircd"; name = "ircd";
description = "IRCD owner."; description = "IRCD owner.";
} ]; } ];
groups = [{name = "ircd";}]; groups = [{name = "ircd";}];
job = " job = ''
description = \"IRCD Hybrid server.\" description = "IRCD Hybrid server."
start on ${startingDependency}/started start on ${startingDependency}/started
stop on ${startingDependency}/stop stop on ${startingDependency}/stop
respawn ${ircdService}/bin/control start respawn ${ircdService}/bin/control start
"; '';
}];
};
} }

View File

@ -1,21 +1,82 @@
args: with args; {pkgs, config, ...}:
###### interface
let
inherit (pkgs.lib) mkOption mkIf;
options = {
services = {
jboss = {
enable = mkOption {
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";
};
};
};
};
in
###### implementation
let let
cfg = config.services.jboss; cfg = config.services.jboss;
jbossService = import ../services/jboss { jbossService = import ../../services/jboss {
inherit (pkgs) stdenv jboss su; inherit (pkgs) stdenv jboss su;
inherit (cfg) tempDir logDir libUrl deployDir serverDir user useJK; inherit (cfg) tempDir logDir libUrl deployDir serverDir user useJK;
}; };
in in
{
mkIf config.services.jboss.enable {
require = [
options
];
services = {
extraJobs = [{
name = "jboss"; name = "jboss";
job = " job = ''
description \"JBoss server\" description \"JBoss server\"
stop on shutdown stop on shutdown
respawn ${jbossService}/bin/control start respawn ${jbossService}/bin/control start
"; '';
}];
};
} }

View File

@ -1,16 +1,44 @@
{glibc, kbd, gzip, ttyNumbers, defaultLocale, consoleFont, consoleKeyMap}: {pkgs, config, ...}:
let let
inherit (pkgs.lib) mkOption;
# think about where to put this chunk of code!
# required by other pieces as well
requiredTTYs = config.services.mingetty.ttys
++ config.boot.extraTTYs
++ [config.services.syslogd.tty];
ttyNumbers = requiredTTYs;
ttys = map (nr: "/dev/tty" + toString nr) ttyNumbers; ttys = map (nr: "/dev/tty" + toString nr) ttyNumbers;
defaultLocale = config.i18n.defaultLocale;
consoleFont = config.i18n.consoleFont;
consoleKeyMap = config.i18n.consoleKeyMap;
in in
###### implementation
# most options are defined in i18n.nix
{ {
inherit requiredTTYs; # pass them to upstart-job/default.nix
# dummy option so that requiredTTYs can be passed, see above (FIXME)
require = [
{
requiredTTYs = mkOption {
default = [];
};
}
];
services = {
extraJobs = [{
name = "kbd"; name = "kbd";
extraPath = [ extraPath = [
kbd pkgs.kbd
]; ];
job = " job = "
@ -21,7 +49,7 @@ in
script script
export LANG=${defaultLocale} export LANG=${defaultLocale}
export PATH=${gzip}/bin:$PATH # Needed by setfont export PATH=${pkgs.gzip}/bin:$PATH # Needed by setfont
set +e # continue in case of errors set +e # continue in case of errors
@ -30,7 +58,7 @@ in
# unicode_{start,stop}. # unicode_{start,stop}.
echo 'Enabling or disabling Unicode mode...' echo 'Enabling or disabling Unicode mode...'
charMap=$(${glibc}/bin/locale charmap) charMap=$(${pkgs.glibc}/bin/locale charmap)
if test \"$charMap\" = UTF-8; then if test \"$charMap\" = UTF-8; then
@ -43,7 +71,7 @@ in
done done
# Set the keyboard driver in UTF-8 mode. # Set the keyboard driver in UTF-8 mode.
${kbd}/bin/kbd_mode -u ${pkgs.kbd}/bin/kbd_mode -u
else else
@ -57,22 +85,25 @@ in
# Set the keyboard driver in ASCII (or any 8-bit character # Set the keyboard driver in ASCII (or any 8-bit character
# set) mode. # set) mode.
${kbd}/bin/kbd_mode -a ${pkgs.kbd}/bin/kbd_mode -a
fi fi
# Set the console font. # Set the console font.
for tty in ${toString ttys}; do for tty in ${toString ttys}; do
${kbd}/bin/setfont -C $tty ${consoleFont} ${pkgs.kbd}/bin/setfont -C $tty ${consoleFont}
done done
# Set the keymap. # Set the keymap.
${kbd}/bin/loadkeys '${consoleKeyMap}' ${pkgs.kbd}/bin/loadkeys '${consoleKeyMap}'
end script end script
"; ";
}];
};
} }

View File

@ -1,12 +1,17 @@
{sysklogd, writeText, config}: {pkgs, config, ...}:
###### implementation
let let
inherit (pkgs.lib);
klogdCmd = "${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";
in in
{ {
services = {
extraJobs = [{
name = "klogd"; name = "klogd";
job = '' job = ''
@ -23,4 +28,6 @@ in
respawn ${klogdCmd} -n respawn ${klogdCmd} -n
''; '';
}];
};
} }

View File

@ -0,0 +1,76 @@
{pkgs, config, ...}:
###### interface
let
inherit (pkgs.lib) mkOption mkIf;
options = {
users = {
ldap = {
enable = mkOption {
default = false;
description = "
Whether to enable authentication against an LDAP server.
";
};
server = mkOption {
example = "ldap://ldap.example.org/";
description = "
The URL of the LDAP server.
";
};
base = mkOption {
example = "dc=example,dc=org";
description = "
The distinguished name of the search base.
";
};
useTLS = mkOption {
default = false;
description = "
If enabled, use TLS (encryption) over an LDAP (port 389)
connection. The alternative is to specify an LDAPS server (port
636) in <option>users.ldap.server</option> or to forego
security.
";
};
};
};
};
in
###### implementation
mkIf config.users.ldap.enable {
require = [
options
];
# LDAP configuration.
environment = {
etc = [
# Careful: OpenLDAP seems to be very picky about the indentation of
# this file. Directives HAVE to start in the first column!
{ source = pkgs.writeText "ldap.conf" ''
uri ${config.users.ldap.server}
base ${config.users.ldap.base}
${
if config.users.ldap.useTLS then ''
ssl start_tls
tls_checkpeer no
'' else ""
}
'';
target = "ldap.conf";
}
];
};
}

View File

@ -1,25 +1,143 @@
{lsh, xauth, lib, nssModulesPath, lshdConfig}: {pkgs, config, ...}:
with builtins; ###### interface
with 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
inherit (pkgs) lsh;
inherit (pkgs.lib) concatStrings concatStringsSep head tail;
lshdConfig = config.services.lshd;
nssModules = config.system.nssModules.list;
nssModulesPath = config.system.nssModules.path;
in
mkIf config.services.lshd.enable {
require = [
options
];
services = {
extraJobs = [{
name = "lshd"; name = "lshd";
job = with lshdConfig; '' job = with lshdConfig; ''
description "GNU lshd SSH2 daemon" description "GNU lshd SSH2 daemon"
start on network-interfaces/started start on network-interfaces/started
stop on network-interfaces/stop stop on network-interfaces/stop
env LD_LIBRARY_PATH=${nssModulesPath} env LD_LIBRARY_PATH=${nssModulesPath}
start script start script
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
if ! test -f /var/spool/lsh/yarrow-seed-file if ! test -f /var/spool/lsh/yarrow-seed-file
then the
${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
@ -28,9 +146,9 @@ start script
${lsh}/bin/lsh-keygen --server | \ ${lsh}/bin/lsh-keygen --server | \
${lsh}/bin/lsh-writekey --server -o "${hostKey}" ${lsh}/bin/lsh-writekey --server -o "${hostKey}"
fi fi
end script end script
respawn ${lsh}/sbin/lshd --daemonic \ respawn ${lsh}/sbin/lshd --daemonic \
--password-helper="${lsh}/sbin/lsh-pam-checkpw" \ --password-helper="${lsh}/sbin/lsh-pam-checkpw" \
-p ${toString portNumber} \ -p ${toString portNumber} \
${if interfaces == [] then "" ${if interfaces == [] then ""
@ -49,6 +167,9 @@ respawn ${lsh}/sbin/lshd --daemonic \
(map (pair: (head pair) + "=" + (map (pair: (head pair) + "=" +
(head (tail pair))) (head (tail pair)))
subsystems)} subsystems)}
''; '';
}
];
};
} }

View File

@ -1,30 +1,41 @@
{modprobe, lvm2, devicemapper}: {pkgs, config, ...}:
###### implementation
let
modprobe = config.system.sbin.modprobe;
in
{ {
services = {
extraJobs = [{
name = "lvm"; name = "lvm";
job = " job = ''
start on udev start on udev
#start on new-devices #start on new-devices
script script
# Load the device mapper. # Load the device mapper.
${modprobe}/sbin/modprobe dm_mod || true ${modprobe}/sbin/modprobe dm_mod || true
${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
# and volume groups. # and volume groups.
${lvm2}/sbin/vgscan --mknodes ${pkgs.lvm2}/sbin/vgscan --mknodes
# Make all logical volumes on all volume groups available, i.e., # Make all logical volumes on all volume groups available, i.e.,
# make them appear in /dev. # make them appear in /dev.
${lvm2}/sbin/vgchange --available y ${pkgs.lvm2}/sbin/vgchange --available y
initctl emit new-devices initctl emit new-devices
end script end script
'';
"; }];
};
} }

View File

@ -1,19 +1,24 @@
{bash}: {pkgs, config, ...}:
###### implementation
{ {
services = {
extraJobs = [{
name = "maintenance-shell"; name = "maintenance-shell";
job = " job = ''
start on maintenance start on maintenance
start on stalled 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 ${bash}/bin/sh exec ${pkgs.bash}/bin/sh
end script end script
"; '';
}];
};
} }

View File

@ -1,10 +1,74 @@
{mingetty, ttyNumber, loginProgram}: {pkgs, config, ...}:
###### interface
let
inherit (pkgs.lib) mkOption mkIf;
options = {
services = {
mingetty = {
ttys = mkOption {
default = [1 2 3 4 5 6];
description = "
The list of tty (virtual console) devices on which to start a
login prompt.
";
};
waitOnMounts = mkOption {
default = false;
description = "
Whether the login prompts on the virtual consoles will be
started before or after all file systems have been mounted. By
default we don't wait, but if for example your /home is on a
separate partition, you may want to turn this on.
";
};
greetingLine = mkOption {
default = ''<<< Welcome to NixOS (\m) - Kernel \r (\l) >>>'';
description = "
Welcome line printed by mingetty.
";
};
helpLine = mkOption {
default = "";
description = "
Help line printed by mingetty below the welcome line.
Used by the installation CD to give some hints on
how to proceed.
";
};
};
};
};
in
###### implementation
let
ttyNumbers = config.services.mingetty.ttys;
loginProgram = "${pkgs.pam_login}/bin/login";
inherit (pkgs) mingetty;
in
{ {
require = [
options
];
services = {
extraJobs = map (ttyNumber : {
name = "tty" + toString ttyNumber; name = "tty" + toString ttyNumber;
job = " job = "
start on udev start on udev
stop on shutdown stop on shutdown
respawn ${mingetty}/sbin/mingetty --loginprog=${loginProgram} --noclear tty${toString ttyNumber} respawn ${mingetty}/sbin/mingetty --loginprog=${loginProgram} --noclear tty${toString ttyNumber}
"; ";
}) ttyNumbers;
};
} }

View File

@ -1,4 +1,49 @@
{pkgs, config}: {pkgs, config, ...}:
###### interface
let
inherit (pkgs.lib) mkOption mkIf;
options = {
services = {
mysql = {
enable = mkOption {
default = false;
description = "
Whether to enable the MySQL server.
";
};
port = mkOption {
default = "3306";
description = "Port of MySQL";
};
user = mkOption {
default = "mysql";
description = "User account under which MySQL runs";
};
dataDir = mkOption {
default = "/var/mysql";
description = "Location where MySQL stores its table files";
};
logError = mkOption {
default = "/var/log/mysql_err.log";
description = "Location of the MySQL error logfile";
};
pidDir = mkOption {
default = "/var/run/mysql";
description = "Location of the file which stores the PID of the MySQL server";
};
};
};
};
in
###### implementation
let let
@ -14,14 +59,24 @@ let
in in
{
name = "mysql";
users = [ mkIf config.services.mysql.enable {
require = [
options
];
users = {
extraUsers = [
{ name = "mysql"; { name = "mysql";
description = "MySQL server user"; description = "MySQL server user";
} }
]; ];
};
services = {
extraJobs = [{
name = "mysql";
extraPath = [mysql]; extraPath = [mysql];
@ -49,4 +104,6 @@ in
${mysql}/bin/mysql_waitpid "$pid" 1000 ${mysql}/bin/mysql_waitpid "$pid" 1000
end script end script
''; '';
}];
};
} }

View File

@ -1,7 +1,11 @@
{nettools, modprobe, wirelesstools, bash, writeText, config}: {pkgs, config, ...}:
###### implementation
let let
inherit (pkgs) nettools wirelesstools bash writeText;
cfg = config.networking; cfg = config.networking;
# !!! use XML # !!! use XML
@ -10,10 +14,14 @@ let
subnetMasks = map (i: if i ? subnetMask then i.subnetMask else "default") cfg.interfaces; subnetMasks = map (i: if i ? subnetMask then i.subnetMask else "default") cfg.interfaces;
essids = map (i: if i ? essid then i.essid else "default") cfg.interfaces; essids = map (i: if i ? essid then i.essid else "default") cfg.interfaces;
wepKeys = map (i: if i ? wepKey then i.wepKey else "nokey") cfg.interfaces; wepKeys = map (i: if i ? wepKey then i.wepKey else "nokey") cfg.interfaces;
modprobe = config.system.sbin.modprobe;
in in
{ {
services = {
extraJobs = [{
name = "network-interfaces"; name = "network-interfaces";
job = '' job = ''
@ -96,5 +104,6 @@ in
done done
end script end script
''; '';
}];
};
} }

View File

@ -1,31 +0,0 @@
{ path, thisConfig, config, lib, pkgs, upstartHelpers } : with upstartHelpers; {
options = {
description = "synergy client lets you use a shared keyboard, mouse and clipboard";
screenName = mkOption {
default = "";
description = "
use screen-name instead the hostname to identify
ourselfs to the server.
";
apply = x: "-n '${x}'";
};
address = mkOption {
default = "";
description = "server address to connect to";
};
};
jobs = [ ( rec {
name = "synergyc";
# TODO start only when X Server has started as well
job = "
description \"${name}\"
start on network-interfaces/started
stop on network-interfaces/stop
exec ${pkgs.synergy}/bin/synergyc -f ${configV "screenName"} ${configV "address"}
";
} ) ];
}

View File

@ -1,69 +0,0 @@
{ path, thisConfig, config, lib, pkgs, upstartHelpers } : with upstartHelpers; {
options = {
description = "synergy client lets you use a shared keyboard, mouse and clipboard";
configuration = mkOption {
description = "
The synergy server configuration file
";
};
screenName = mkOption {
default = "";
description = "
use screen-name instead the hostname to identify
this screen in the configuration.
";
apply = x: "-n '${x}'";
};
address = mkOption {
default = "";
description = "listen for clients on the given address";
apply = x: "-a '${x}'";
};
};
jobs =
[ ( rec {
name = "synergys";
extraEtc = [ (autoGeneratedEtcFile { name = name + ".conf"; content = thisConfig.configuration; }) ];
# TODO start only when X Server has started as well
job = "
description \"${name}\"
start on network-interfaces/started and xserver/started
stop on network-interfaces/stop or xserver/stop
exec ${pkgs.synergy}/bin/synergys -c /etc/${name}.conf -f ${configV "address"} ${configV "screenName"}
";
} ) ];
}
/* Example configuration
section: screens
laptop:
dm:
win:
end
section: aliases
laptop:
192.168.5.5
dm:
192.168.5.78
win:
192.168.5.54
end
section: links
laptop:
left = dm
dm:
right = laptop
left = win
win:
right = dm
end
*/

View File

@ -1,89 +0,0 @@
{ path, thisConfig, config, lib, pkgs, upstartHelpers } : with upstartHelpers; rec {
options = {
description = "tightvnc vnc server (share virtual desktop over network";
geometry = mkOption {
default = "-geometry 800x600";
example = "800x600";
description = ''
size of virtual screen
'';
apply = x : "-geometry '${x}'";
};
depth = mkOption {
default = "-depth 24";
description = ''
use screen-name instead the hostname to identify
this screen in the configuration.
value must be something between 8 and 32
'';
apply = x: "-depth '${x}'";
check = x: (__lessThan x 33) && (7 __lessThan x); # not yet used
};
display = mkOption {
default = ":8";
example = 8;
description = "display to use";
apply = x: ":${builtins.toString x}";
};
authFile = mkOption {
default = "-auth /etc/tightvnc-pwd";
description = ''
The file containing authentication passwords.
Can be created using vncpasswd
'';
apply = x: "-auth '${x}'";
check = __pathExists;
};
httpPort = mkOption {
default = "-httpport 5900";
example = 5901;
description = "http port to listen to (Java applet remote interface)";
apply = x: "-httpport '${builtins.toString x}'";
};
desktopName = mkOption {
description = ''
Set VNC desktop name ("x11" by default)
'';
apply = x: "-desktop '${x}'";
};
viewOnly = mkOption {
default = "";
description = ''
Don't accept keboard and pointer events from clients. All clients will be able to see
the desktop but won't be able to control it.
'';
apply = x: "-viewonly '${x}'";
};
interface = mkOption {
default = "";
description = ''
Listen for client connections only on the network interface with given ipaddr
'';
apply = x: "-interface '${x}'";
};
extras = mkOption {
default = "";
description = ''
additional params, see man Xvnc
'';
};
};
jobs = if (lib.getAttr ["services" "xfs" "enable"] false config) != true
then abort "you need to enable xfs services = { xfs = { enable = true; }; } within your nixos/configuration.nix file"
else
[ ( rec {
name = "tightvnc";
job = "
description \"${name}\"
start on network-interfaces/started and xserver/started
stop on network-interfaces/stop or xserver/stop
exec ${pkgs.tightvnc}/bin/Xvnc -fp unix/:7100 ${lib.concatStringsSep " " (lib.mapIf (x : x != "description") configV (__attrNames options ) ) }
";
} ) ];
}
#

227
upstart-jobs/nix.nix Normal file
View File

@ -0,0 +1,227 @@
{pkgs, config, ...}:
###### interface
let
inherit (pkgs.lib) mkOption mkIf;
options = {
nix = {
maxJobs = mkOption {
default = 1;
example = 2;
description = "
This option defines the maximum number of jobs that Nix will try
to build in parallel. The default is 1. You should generally
set it to the number of CPUs in your system (e.g., 2 on a Athlon
64 X2).
";
};
useChroot = mkOption {
default = false;
example = true;
description = "
If set, Nix will perform builds in a chroot-environment that it
will set up automatically for each build. This prevents
impurities in builds by disallowing access to dependencies
outside of the Nix store.
";
};
extraOptions = mkOption {
default = "";
example = "
gc-keep-outputs = true
gc-keep-derivations = true
";
description = "
This option allows to append lines to nix.conf.
";
};
distributedBuilds = mkOption {
default = false;
description = "
Whether to distribute builds to the machines listed in
<option>nix.buildMachines</option>.
";
};
buildMachines = mkOption {
example = [
{ hostName = "voila.labs.cs.uu.nl";
sshUser = "nix";
sshKey = "/root/.ssh/id_buildfarm";
system = "powerpc-darwin";
maxJobs = 1;
}
{ hostName = "linux64.example.org";
sshUser = "buildfarm";
sshKey = "/root/.ssh/id_buildfarm";
system = "x86_64-linux";
maxJobs = 2;
}
];
description = "
This option lists the machines to be used if distributed
builds are enabled (see
<option>nix.distributedBuilds</option>). Nix will perform
derivations on those machines via SSh by copying the inputs to
the Nix store on the remote machine, starting the build, then
copying the output back to the local Nix store. Each element
of the list should be an attribute set containing the
machine's host name (<varname>hostname</varname>), the user
name to be used for the SSH connection
(<varname>sshUser</varname>), the Nix system type
(<varname>system</varname>, e.g.,
<literal>\"i686-linux\"</literal>), the maximum number of jobs
to be run in parallel on that machine
(<varname>maxJobs</varname>), and the path to the SSH private
key to be used to connect (<varname>sshKey</varname>). The
SSH private key should not have a passphrase, and the
corresponding public key should be added to
<filename>~<replaceable>sshUser</replaceable>/authorized_keys</filename>
on the remote machine.
";
};
proxy = mkOption {
default = "";
description = "
This option specifies the proxy to use for fetchurl. The real effect
is just exporting http_proxy, https_proxy and ftp_proxy with that
value.
";
example = "http://127.0.0.1:3128";
};
# Environment variables for running Nix.
envVars = mkOption {
internal = true;
default = "";
description = "
Define the environment variables used by nix to
";
merge = pkgs.lib.mergeStringOption;
# other option should be used to define the content instead of using
# the apply function.
apply = conf: ''
export NIX_CONF_DIR=/nix/etc/nix
# Enable the copy-from-other-stores substituter, which allows builds
# to be sped up by copying build results from remote Nix stores. To
# do this, mount the remote file system on a subdirectory of
# /var/run/nix/remote-stores.
export NIX_OTHER_STORES=/var/run/nix/remote-stores/*/nix
'' + # */
(if config.nix.distributedBuilds then
''
export NIX_BUILD_HOOK=${config.environment.nix}/libexec/nix/build-remote.pl
export NIX_REMOTE_SYSTEMS=/etc/nix.machines
export NIX_CURRENT_LOAD=/var/run/nix/current-load
''
else "")
+
(if config.nix.proxy != "" then
''
export http_proxy=${config.nix.proxy}
export https_proxy=${config.nix.proxy}
export ftp_proxy=${config.nix.proxy}
''
else "")
+ conf;
};
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
###### implementation
let
binsh = config.system.build.binsh;
nixEnvVars = config.nix.envVars;
inherit (pkgs) nix;
in
{
require = [
options
];
environment = {
etc = [
{ # Nix configuration.
source =
let
# Tricky: if we're using a chroot for builds, then we need
# /bin/sh in the chroot (our own compromise to purity).
# However, since /bin/sh is a symlink to some path in the
# Nix store, which furthermore has runtime dependencies on
# other paths in the store, we need the closure of /bin/sh
# in `build-chroot-dirs' - otherwise any builder that uses
# /bin/sh won't work.
refs = pkgs.writeReferencesToFile binsh;
in
pkgs.runCommand "nix.conf" {} ''
binshDeps=$(for i in $(cat ${refs}); do if test -d $i; then echo $i; fi; done)
cat > $out <<END
# WARNING: this file is generated.
build-users-group = nixbld
build-max-jobs = ${toString (config.nix.maxJobs)}
build-use-chroot = ${if config.nix.useChroot then "true" else "false"}
build-chroot-dirs = /dev /dev/pts /proc /bin $(echo $binshDeps)
${config.nix.extraOptions}
END
'';
target = "nix.conf"; # will be symlinked from /nix/etc/nix/nix.conf in activate-configuration.sh.
}
];
};
services = {
extraJobs = [{
name = "nix-daemon";
job = ''
start on startup
stop on shutdown
respawn
script
export PATH=${if config.nix.distributedBuilds then "${pkgs.openssh}/bin:" else ""}${pkgs.openssl}/bin:${nix}/bin:$PATH
${nixEnvVars}
exec ${pkgs.nix}/bin/nix-worker --daemon > /dev/null 2>&1
end script
'';
}];
};
}

View File

@ -1,6 +1,14 @@
{glibc, nssModulesPath}: {pkgs, config, ...}:
###### implementation
let
nssModulesPath = config.system.nssModules.path;
in
{ {
services = {
extraJobs = [{
name = "nscd"; name = "nscd";
users = [ users = [
@ -10,26 +18,27 @@
} }
]; ];
job = " job = ''
description \"Name Service Cache Daemon\" description \"Name Service Cache Daemon\"
start on startup start on startup
stop on shutdown stop on shutdown
env LD_LIBRARY_PATH=${nssModulesPath} env LD_LIBRARY_PATH=${nssModulesPath}
start script start script
mkdir -m 0755 -p /var/run/nscd mkdir -m 0755 -p /var/run/nscd
mkdir -m 0755 -p /var/db/nscd mkdir -m 0755 -p /var/db/nscd
rm -f /var/db/nscd/* # for testing rm -f /var/db/nscd/* # for testing
end script end script
# !!! -d turns on debug info which probably makes nscd slower
# 2>/dev/null is to make it shut up
respawn ${glibc}/sbin/nscd -f ${./nscd.conf} -d 2> /dev/null
";
# !!! -d turns on debug info which probably makes nscd slower
# 2>/dev/null is to make it shut up
respawn ${pkgs.glibc}/sbin/nscd -f ${./nscd.conf} -d 2> /dev/null
'';
}];
};
} }

View File

@ -1,22 +1,70 @@
{ntp, modprobe, glibc, writeText, servers}: {pkgs, config, ...}:
###### interface
let
inherit (pkgs.lib) mkOption mkIf;
options = {
services = {
ntp = {
enable = mkOption {
default = true;
description = "
Whether to synchronise your machine's time using the NTP
protocol.
";
};
servers = mkOption {
default = [
"0.pool.ntp.org"
"1.pool.ntp.org"
"2.pool.ntp.org"
];
description = "
The set of NTP servers from which to synchronise.
";
};
};
};
};
in
###### implementation
let let
inherit (pkgs) writeText ntp;
stateDir = "/var/lib/ntp"; stateDir = "/var/lib/ntp";
ntpUser = "ntp"; ntpUser = "ntp";
config = writeText "ntp.conf" '' servers = config.services.ntp.servers;
modprobe = config.system.sbin.modprobe;
configFile = writeText "ntp.conf" ''
driftfile ${stateDir}/ntp.drift driftfile ${stateDir}/ntp.drift
${toString (map (server: "server " + server + "\n") servers)} ${toString (map (server: "server " + server + "\n") servers)}
''; '';
ntpFlags = "-c ${config} -u ${ntpUser}:nogroup -i ${stateDir}"; ntpFlags = "-c ${configFile} -u ${ntpUser}:nogroup -i ${stateDir}";
in in
{
mkIf config.services.ntp.enable {
require = [
options
];
services = {
extraJobs = [{
name = "ntpd"; name = "ntpd";
users = [ users = [
@ -48,5 +96,6 @@ in
respawn ${ntp}/bin/ntpd -n ${ntpFlags} respawn ${ntp}/bin/ntpd -n ${ntpFlags}
''; '';
}];
};
} }

View File

@ -1,7 +1,36 @@
{pkgs, config}: {pkgs, config, ...}:
assert config.services.openfire.usePostgreSQL -> config.services.postgresql.enable; ###### interface
let 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
# FIXME (see xfs)
# if (!(config.services.openfire.usePostgreSQL -> config.services.postgresql.enable)) then throw "openfire assertion failed" else
let
inherit (pkgs) jre openfire coreutils which gnugrep gawk gnused;
startDependency = if config.services.openfire.usePostgreSQL then startDependency = if config.services.openfire.usePostgreSQL then
"postgresql" "postgresql"
else else
@ -10,8 +39,15 @@ let
else else
"network-interfaces"; "network-interfaces";
in in
with pkgs;
{ mkIf config.services.openfire.enable {
require = [
options
];
services = {
extraJobs = [{
name = "openfire"; name = "openfire";
job = '' job = ''
description "OpenFire XMPP server" description "OpenFire XMPP server"
@ -32,4 +68,6 @@ with pkgs;
openfire start openfire start
end script end script
''; '';
}];
};
} }

View File

@ -1,12 +1,40 @@
{ makePortmap }: {pkgs, config, ...}:
###### interface
let
inherit (pkgs.lib) mkOption mkIf;
options = {
services = {
portmap = {
enable = mkOption {
default = false;
description = ''
Whether to enable `portmap', an ONC RPC directory service
notably used by NFS and NIS, and which can be queried
using the rpcinfo(1) command.
'';
};
};
};
};
in
###### implementation
let uid = (import ../system/ids.nix).uids.portmap; let uid = (import ../system/ids.nix).uids.portmap;
gid = (import ../system/ids.nix).gids.portmap; gid = (import ../system/ids.nix).gids.portmap;
in in
{
name = "portmap";
users = [ mkIf config.services.portmap.enable {
require = [
options
];
users = {
extraUsers = [
{ name = "portmap"; { name = "portmap";
inherit uid; inherit uid;
description = "portmap daemon user"; description = "portmap daemon user";
@ -14,22 +42,29 @@ in
} }
]; ];
groups = [ extraGroups = [
{ name = "portmap"; { name = "portmap";
inherit gid; inherit gid;
} }
]; ];
};
services = {
extraJobs = [{
name = "portmap";
job = job =
let portmap = makePortmap { daemonUID = uid; daemonGID = gid; }; let portmap = pkgs.makePortmap { daemonUID = uid; daemonGID = gid; };
in in
'' ''
description "ONC RPC portmap" description "ONC RPC portmap"
start on network-interfaces/started start on network-interfaces/started
stop on network-interfaces/stop stop on network-interfaces/stop
respawn ${portmap}/sbin/portmap
'';
respawn ${portmap}/sbin/portmap
'';
}];
};
} }

View File

@ -1,4 +1,154 @@
{config, pkgs} : {pkgs, config, ...}:
###### interface
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";
@ -103,9 +253,21 @@ let
mainCfFile = pkgs.writeText "postfix-main.cf" mainCf; mainCfFile = pkgs.writeText "postfix-main.cf" mainCf;
in in
{
name = "postfix"; mkIf config.services.postfix.enable {
users = [ require = [
options
];
environment = {
etc = [{
source = "/var/postfix/conf";
target = "postfix";
}];
};
users = {
extraUsers = [
{ name = user; { name = user;
description = "Postfix mail server user"; description = "Postfix mail server user";
uid = idList.uids.postfix; uid = idList.uids.postfix;
@ -113,7 +275,7 @@ in
} }
]; ];
groups = [ extraGroups = [
{ name = group; { name = group;
gid = idList.gids.postfix; gid = idList.gids.postfix;
} }
@ -121,6 +283,11 @@ in
gid = idList.gids.postdrop; gid = idList.gids.postdrop;
} }
]; ];
};
services = {
extraJobs = [{
name = "postfix";
# I copy _lots_ of shipped configuration filed # I copy _lots_ of shipped configuration filed
@ -156,9 +323,6 @@ in
end script end script
''; '';
extraEtc = [ }];
{ source = "/var/postfix/conf"; };
target = "postfix";
}
];
} }

View File

@ -1,4 +1,72 @@
{pkgs, config}: {pkgs, config, ...}:
###### interface
let
inherit (pkgs.lib) mkOption mkIf;
options = {
services = {
postgresql = {
enable = mkOption {
default = false;
description = "
Whether to run PostgreSQL.
";
};
port = mkOption {
default = "5432";
description = "
Port for PostgreSQL.
";
};
logDir = mkOption {
default = "/var/log/postgresql";
description = "
Log directory for PostgreSQL.
";
};
dataDir = mkOption {
default = "/var/db/postgresql";
description = "
Data directory for PostgreSQL.
";
};
subServices = mkOption {
default = [];
description = "
Subservices list. As it is already implememnted,
here is an interface...
";
};
authentication = mkOption {
default = ''
# Generated file; do not edit!
local all all ident sameuser
host all all 127.0.0.1/32 md5
host all all ::1/128 md5
'';
description = "
Hosts (except localhost), who you allow to connect.
";
};
allowedHosts = mkOption {
default = [];
description = "
Hosts (except localhost), who you allow to connect.
";
};
authMethod = mkOption {
default = " ident sameuser ";
description = "
How to authorize users.
Note: ident needs absolute trust to all allowed client hosts.";
};
};
};
};
in
###### implementation
let let
@ -13,18 +81,27 @@ let
in in
{ mkIf config.services.postgresql.enable {
name = "postgresql"; require = [
options
];
users = [
users = {
extraUsers = [
{ name = "postgres"; { name = "postgres";
description = "PostgreSQL server user"; description = "PostgreSQL server user";
} }
]; ];
groups = [ extraGroups = [
{ name = "postgres"; } { name = "postgres"; }
]; ];
};
services = {
extraJobs = [{
name = "postgresql";
extraPath = [postgresql]; extraPath = [postgresql];
@ -45,4 +122,6 @@ in
respawn ${run} -c '${postgresql}/bin/postgres -D ${cfg.dataDir}' respawn ${run} -c '${postgresql}/bin/postgres -D ${cfg.dataDir}'
''; '';
}];
};
} }

View File

@ -1,4 +1,26 @@
{pkgs, samba, glibc}: {pkgs, config, ...}:
###### interface
let
inherit (pkgs.lib) mkOption mkIf;
options = {
services = {
samba = {
enable = mkOption {
default = false;
description = "
Whether to enable the samba server. (to communicate with, and provide windows shares)
";
};
};
};
};
in
###### implementation
let let
@ -7,31 +29,43 @@ let
smbConfig = ./smb.conf ; smbConfig = ./smb.conf ;
inherit (pkgs) samba;
in in
{
name = "samba";
users = [
mkIf config.services.samba.enable {
require = [
options
];
users = {
extraUsers = [
{ name = user; { name = user;
description = "Samba service user"; description = "Samba service user";
group = group; group = group;
} }
]; ];
groups = [ extraGroups = [
{ name = group; { name = group;
} }
]; ];
};
job = " services = {
extraJobs = [{
name = "samba";
job = ''
description \"Samba Service\" description "Samba Service"
start on network-interfaces/started start on network-interfaces/started
stop on network-interfaces/stop stop on network-interfaces/stop
start script start script
if ! test -d /home/smbd ; then if ! test -d /home/smbd ; then
mkdir -p /home/smbd mkdir -p /home/smbd
@ -49,10 +83,11 @@ start script
ln -fs ${smbConfig} /var/samba/config ln -fs ${smbConfig} /var/samba/config
end script end script
respawn ${samba}/sbin/nmbd -D -s ${smbConfig} &; ${samba}/sbin/smbd -D -s ${smbConfig} &; ${samba}/sbin/winbindd -B & respawn ${samba}/sbin/nmbd -D -s ${smbConfig} &; ${samba}/sbin/smbd -D -s ${smbConfig} &; ${samba}/sbin/winbindd -B &
";
'';
}];
};
} }

View File

@ -1,14 +1,66 @@
{ writeText, openssh, glibc, xauth {pkgs, config, ...}:
, nssModulesPath
, forwardX11, allowSFTP, permitRootLogin, gatewayPorts
}:
assert permitRootLogin == "yes" ||
permitRootLogin == "without-password" ||
permitRootLogin == "forced-commands-only" ||
permitRootLogin == "no";
###### interface
let let
inherit (pkgs.lib) mkOption mkIf;
options = {
services = {
sshd = {
enable = mkOption {
default = false;
description = "
Whether to enable the Secure Shell daemon, which allows secure
remote logins.
";
};
forwardX11 = mkOption {
default = true;
description = "
Whether to enable sshd to forward X11 connections.
";
};
allowSFTP = mkOption {
default = true;
description = "
Whether to enable the SFTP subsystem in the SSH daemon. This
enables the use of commands such as <command>sftp</command> and
<command>sshfs</command>.
";
};
permitRootLogin = mkOption {
default = "yes";
description = "
Whether the root user can login using ssh. Valid options
are <command>yes</command>, <command>without-password</command>,
<command>forced-commands-only</command> or
<command>no</command>
";
};
gatewayPorts = mkOption {
default = "no";
description = "
Specifies whether remote hosts are allowed to connect to ports forwarded for the client. See man sshd_conf.
";
};
};
};
};
###### implementation
inherit (pkgs) writeText openssh;
cfg = (config.services.sshd);
nssModules = config.system.nssModules.list;
nssModulesPath = config.system.nssModules.path;
sshdConfig = writeText "sshd_config" '' sshdConfig = writeText "sshd_config" ''
@ -16,37 +68,51 @@ let
UsePAM yes UsePAM yes
${if forwardX11 then " ${if cfg.forwardX11 then "
X11Forwarding yes X11Forwarding yes
XAuthLocation ${xauth}/bin/xauth XAuthLocation ${pkgs.xlibs.xauth}/bin/xauth
" else " " else "
X11Forwarding no X11Forwarding no
"} "}
${if allowSFTP then " ${if cfg.allowSFTP then "
Subsystem sftp ${openssh}/libexec/sftp-server Subsystem sftp ${openssh}/libexec/sftp-server
" else " " else "
"} "}
PermitRootLogin ${permitRootLogin} PermitRootLogin ${cfg.permitRootLogin}
GatewayPorts ${gatewayPorts} GatewayPorts ${cfg.gatewayPorts}
''; '';
sshdUid = (import ../system/ids.nix).uids.sshd; sshdUid = (import ../system/ids.nix).uids.sshd;
assertion = cfg.permitRootLogin == "yes" ||
cfg.permitRootLogin == "without-password" ||
cfg.permitRootLogin == "forced-commands-only" ||
cfg.permitRootLogin == "no";
in in
{
name = "sshd";
users = [ mkIf config.services.sshd.enable {
require = [
options
];
users = {
extraUsers = [
{ name = "sshd"; { name = "sshd";
uid = (import ../system/ids.nix).uids.sshd; uid = (import ../system/ids.nix).uids.sshd;
description = "SSH privilege separation user"; description = "SSH privilege separation user";
home = "/var/empty"; home = "/var/empty";
} }
]; ];
};
services = {
extraJobs = [{
name = "sshd";
job = '' job = ''
description "SSH server" description "SSH server"
@ -66,5 +132,6 @@ in
respawn ${openssh}/sbin/sshd -D -h /etc/ssh/ssh_host_dsa_key -f ${sshdConfig} respawn ${openssh}/sbin/sshd -D -h /etc/ssh/ssh_host_dsa_key -f ${sshdConfig}
''; '';
}];
};
} }

View File

@ -1,7 +1,13 @@
{lib, utillinux, swapDevices}: {pkgs, config, ...}:
###### implementation
let let
inherit (pkgs) utillinux lib;
swapDevices = config.swapDevices;
devicesByPath = devicesByPath =
map (x: x.device) (lib.filter (x: x ? device) swapDevices); map (x: x.device) (lib.filter (x: x ? device) swapDevices);
@ -10,14 +16,17 @@ let
in in
{ {
services = {
extraJobs = [{
name = "swap"; name = "swap";
job = " job = "
start on startup start on startup
start on new-devices start on new-devices
script script
for device in ${toString devicesByPath}; do for device in ${toString devicesByPath}; do
${utillinux}/sbin/swapon \"$device\" || true ${utillinux}/sbin/swapon \"$device\" || true
done done
@ -38,7 +47,8 @@ script
# fi # fi
#done #done
end script end script
"; ";
}];
};
} }

View File

@ -1,19 +1,26 @@
{modprobe, mdadm}: {pkgs, config, ...}:
###### implementation
let let
tempConf = "/var/run/mdadm.conf"; tempConf = "/var/run/mdadm.conf";
modprobe = config.system.sbin.modprobe;
inherit (pkgs) mdadm;
in in
{ {
services = {
extraJobs = [{
name = "swraid"; name = "swraid";
job = " job = ''
start on udev start on udev
#start on new-devices #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?
@ -29,8 +36,9 @@ script
initctl emit new-devices initctl emit new-devices
end script end script
";
'';
}];
};
} }

View File

@ -1,8 +1,32 @@
{sysklogd, writeText, config}: {pkgs, config, ...}:
###### interface
let
inherit (pkgs.lib) mkOption mkIf;
options = {
services = {
syslogd = {
tty = mkOption {
default = 10;
description = "
The tty device on which syslogd will print important log
messages.
";
};
};
};
};
in
###### implementation
let let
syslogConf = writeText "syslog.conf" '' syslogConf = pkgs.writeText "syslog.conf" ''
kern.warning;*.err;authpriv.none /dev/tty10 kern.warning;*.err;authpriv.none /dev/tty10
# Send emergency messages to all users. # Send emergency messages to all users.
@ -22,6 +46,12 @@ let
in in
{ {
require = [
options
];
services = {
extraJobs = [{
name = "syslogd"; name = "syslogd";
job = '' job = ''
@ -32,6 +62,8 @@ in
env TZ=${config.time.timeZone} env TZ=${config.time.timeZone}
respawn ${sysklogd}/sbin/syslogd -n -f ${syslogConf} respawn ${pkgs.sysklogd}/sbin/syslogd -n -f ${syslogConf}
''; '';
}];
};
} }

View File

@ -1,10 +1,74 @@
args: with args; {pkgs, config, ...}:
###### interface
let
inherit (pkgs.lib) mkOption mkIf;
options = {
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.";
};
deployFrom = mkOption {
default = "";
description = "Location where webapplications are stored. Leave empty to use the baseDir.";
};
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";
};
sharedLibFrom = mkOption {
default = "";
description = "Location where shared libraries are stored. Leave empty to use the baseDir.";
};
commonLibFrom = mkOption {
default = "";
description = "Location where common libraries are stored. Leave empty to use the baseDir.";
};
contextXML = mkOption {
default = "";
description = "Location of the context.xml to use. Leave empty to use the default.";
};
};
};
};
in
###### implementation
let let
cfg = config.services.tomcat; cfg = config.services.tomcat;
in in
{ mkIf config.services.tomcat.enable {
require = [
options
];
services = {
extraJobs = [{
name = "tomcat"; name = "tomcat";
groups = [ groups = [
@ -106,4 +170,6 @@ in
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 end script
''; '';
}];
};
} }

View File

@ -1,12 +1,101 @@
{stdenv, splashutils, backgrounds}: {pkgs, config, ...}:
rec { ###### interface
name = "tty-backgrounds"; let
inherit (pkgs.lib) mkOption mkIf;
unpackTheme = theme: import ../helpers/unpack-theme.nix { options = {
inherit stdenv theme; services = {
ttyBackgrounds = {
enable = mkOption {
default = true;
description = "
Whether to enable graphical backgrounds for the virtual consoles.
";
}; };
defaultTheme = mkOption {
default = pkgs.fetchurl {
#url = http://www.bootsplash.de/files/themes/Theme-BabyTux.tar.bz2;
url = http://www.mirrorservice.org/sites/www.ibiblio.org/gentoo/distfiles/Theme-BabyTux.tar.bz2;
md5 = "a6d89d1c1cff3b6a08e2f526f2eab4e0";
};
description = "
The default theme for the virtual consoles. Themes can be found
at <link xlink:href='http://www.bootsplash.de/' />.
";
};
defaultSpecificThemes = mkOption {
default = [
/*
{ tty = 6;
theme = pkgs.fetchurl { # Yeah!
url = http://www.bootsplash.de/files/themes/Theme-Pativo.tar.bz2;
md5 = "9e13beaaadf88d43a5293e7ab757d569";
};
}
*/
{ tty = 10;
theme = pkgs.fetchurl {
#url = http://www.bootsplash.de/files/themes/Theme-GNU.tar.bz2;
url = http://www.mirrorservice.org/sites/www.ibiblio.org/gentoo/distfiles/Theme-GNU.tar.bz2;
md5 = "61969309d23c631e57b0a311102ef034";
};
}
];
description = "
This option sets specific themes for virtual consoles. If you
just want to set themes for additional consoles, use
<option>services.ttyBackgrounds.specificThemes</option>.
";
};
specificThemes = mkOption {
default = [
];
description = "
This option allows you to set specific themes for virtual
consoles.
";
};
};
};
};
in
###### implementation
let
inherit (pkgs) stdenv;
kernelPackages = config.boot.kernelPackages;
splashutils = kernelPackages.splashutils;
requiredTTYs = config.requiredTTYs;
backgrounds =
let
specificThemes =
config.services.ttyBackgrounds.defaultSpecificThemes
++ config.services.ttyBackgrounds.specificThemes;
overridenTTYs = map (x: x.tty) specificThemes;
# Use the default theme for all the mingetty ttys and for the
# syslog tty, except those for which a specific theme is
# specified.
defaultTTYs =
pkgs.lib.filter (x: !(pkgs.lib.elem x overridenTTYs)) requiredTTYs;
in
(map (ttyNumber: {
tty = ttyNumber;
theme = config.services.ttyBackgrounds.defaultTheme;
}) defaultTTYs)
++ specificThemes;
themesUnpacked = stdenv.mkDerivation { themesUnpacked = stdenv.mkDerivation {
name = "splash-themes"; name = "splash-themes";
builder = ./tty-backgrounds-combine.sh; builder = ./tty-backgrounds-combine.sh;
@ -15,11 +104,35 @@ rec {
themes = map (x: if x ? theme then (unpackTheme x.theme) else "default") backgrounds; themes = map (x: if x ? theme then (unpackTheme x.theme) else "default") backgrounds;
}; };
extraEtc = [ unpackTheme = theme: import ../helpers/unpack-theme.nix {
inherit stdenv theme;
};
in
# FIXME see xfs
# assert splashutils != null;
mkIf (config.services.ttyBackgrounds.enable && kernelPackages.splashutils != null) {
require = [
options
];
environment = {
etc = [
{ source = themesUnpacked; { source = themesUnpacked;
target = "splash"; target = "splash";
} }
]; ];
};
services = {
extraJobs = [ rec {
name = "tty-backgrounds";
job = '' job = ''
start on udev start on udev
@ -56,5 +169,6 @@ rec {
done done
end script end script
''; '';
}];
};
} }

View File

@ -1,12 +1,55 @@
{ stdenv, writeText, substituteAll, cleanSource, udev, procps, firmwareDirs, modprobe {pkgs, config, ...}:
, extraUdevPkgs ? []
, config ###### interface
}: let
inherit (pkgs.lib) mkOption mkIf;
options = {
services = {
udev = {
addFirmware = mkOption {
default = [];
example = ["/mnt/big-storage/firmware/"];
description = "
To specify firmware that is not too spread to ensure
a package, or have an interactive process of extraction
and cannot be redistributed.
";
merge = pkgs.lib.mergeListOption;
};
addUdevPkgs = mkOption {
default = [];
description = "
List of packages containing udev rules.
";
merge = pkgs.lib.mergeListOption;
};
sndMode = mkOption {
default = "0600";
example = "0666";
description = "
Permissions for /dev/snd/*, in case you have multiple
logged in users or if the devices belong to root for
some reason.
";
};
};
};
};
in
###### implementation
let let
inherit (pkgs) substituteAll stdenv writeText udev procps;
cfg = config.services.udev; cfg = config.services.udev;
firmwareLoader = substituteAll { firmwareLoader = substituteAll {
src = ./udev-firmware-loader.sh; src = ./udev-firmware-loader.sh;
path = "${stdenv.coreutils}/bin"; path = "${stdenv.coreutils}/bin";
@ -14,6 +57,11 @@ let
inherit firmwareDirs; inherit firmwareDirs;
}; };
firmwareDirs = config.services.udev.addFirmware;
extraUdevPkgs = config.services.udev.addUdevPkgs;
modprobe = config.system.sbin.modprobe;
nixRules = writeText "90-nix.rules" '' nixRules = writeText "90-nix.rules" ''
# Miscellaneous devices. # Miscellaneous devices.
@ -86,6 +134,13 @@ let
in in
{ {
require = [
options
];
services = {
extraJobs = [{
name = "udev"; name = "udev";
job = '' job = ''
@ -137,4 +192,6 @@ in
''; '';
passthru = {inherit udevRules;}; passthru = {inherit udevRules;};
}];
};
} }

View File

@ -1,80 +1,120 @@
{ vsftpd, anonymousUser {pkgs, config, ...}:
, anonymousUploadEnable, anonymousMkdirEnable, writeEnable
}:
{ ###### interface
name = "vsftpd"; let
inherit (pkgs.lib) mkOption mkIf;
groups = [ options = {
{ name = "ftp"; services = {
gid = (import ../system/ids.nix).gids.ftp; 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.
";
};
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.
";
};
};
};
};
in
###### implementation
let
inherit (config.services.vsftpd) anonymousUser writeEnable anonymousUploadEnable anonymousMkdirEnable;
inherit (pkgs) vsftpd;
yesNoOption = p : name :
"${name}=${if p then "YES" else "NO"}";
in
mkIf config.services.vsftpd.enable {
require = [
options
]; ];
users = [ users = {
extraUsers = [
{ name = "vsftpd"; { name = "vsftpd";
uid = (import ../system/ids.nix).uids.vsftpd; uid = (import ../system/ids.nix).uids.vsftpd;
description = "VSFTPD user"; description = "VSFTPD user";
home = "/homeless-shelter"; home = "/homeless-shelter";
} }
] ++ ] ++ pkgs.lib.optional anonymousUser
(if anonymousUser then [
{ name = "ftp"; { name = "ftp";
uid = (import ../system/ids.nix).uids.ftp; uid = (import ../system/ids.nix).uids.ftp;
group = "ftp"; group = "ftp";
description = "Anonymous ftp user"; description = "Anonymous ftp user";
home = "/home/ftp"; home = "/home/ftp";
};
extraGroups = [
{ name = "ftp";
gid = (import ../system/ids.nix).gids.ftp;
} }
] ];
else
[]);
job = " };
description \"vsftpd server\"
start on network-interfaces/started services = {
stop on network-interfaces/stop extraJobs = [{
name = "vsftpd";
start script job = ''
description "vsftpd server"
start on network-interfaces/started
stop on network-interfaces/stop
start script
cat > /etc/vsftpd.conf <<EOF cat > /etc/vsftpd.conf <<EOF
" + ${yesNoOption anonymousUser "anonymous_enable"}
(if anonymousUser then ${yesNoOption writeEnable "write_enable"}
"anonymous_enable=YES" ${yesNoOption anonymousUploadEnable "anon_upload_enable"}
else ${yesNoOption anonymousMkdirEnable "anon_mkdir_write_enable"}
"anonymous_enable=NO") + background=NO
(if writeEnable then listen=YES
" nopriv_user=vsftpd
write_enable=YES" secure_chroot_dir=/var/ftp/empty
else EOF
"
write_enable=NO"
) +
(if anonymousUploadEnable then
"
anon_upload_enable=YES"
else
"
anon_upload_enable=NO"
) +
(if anonymousMkdirEnable then
"
anon_mkdir_write_enable=YES"
else
"
anon_mkdir_write_enable=NO"
) +
"
background=NO
listen=YES
nopriv_user=vsftpd
secure_chroot_dir=/var/ftp/empty
EOF
mkdir -p /home/ftp && mkdir -p /home/ftp &&
chown -R ftp:ftp /home/ftp chown -R ftp:ftp /home/ftp
end script end script
respawn ${vsftpd}/sbin/vsftpd /etc/vsftpd.conf respawn ${vsftpd}/sbin/vsftpd /etc/vsftpd.conf
"; '';
}];
};
} }

View File

@ -1,20 +1,54 @@
{ {pkgs, config, ...}:
pkgs, config
}: ###### interface
if ! config.fonts.enableFontDir then abort "Please enable fontDir (fonts.enableFontDir) to use xfs." else let
inherit (pkgs.lib) mkOption mkIf;
options = {
services = {
xfs = {
enable = mkOption {
default = false;
description = "
Whether to enable the X Font Server.
";
};
};
};
};
in
###### implementation
# FIXME: enable this warning again. It's causing "infinite recursion encountered, why?"
# if ! config.fonts.enableFontDir then throw "Please enable fontDir (fonts.enableFontDir) to use xfs." else
let let
configFile = ./xfs.conf; configFile = ./xfs.conf;
startingDependency = if config.services.gw6c.enable && config.services.gw6c.autorun then "gw6c" else "network-interfaces"; startingDependency = if config.services.gw6c.enable && config.services.gw6c.autorun then "gw6c" else "network-interfaces";
in in
rec {
mkIf config.services.xfs.enable {
require = [
options
];
services = {
extraJobs = [ (rec {
name = "xfs"; name = "xfs";
groups = []; groups = [];
users = []; users = [];
job = " job = ''
description \"X Font Server\" description "X Font Server"
start on ${startingDependency}/started start on ${startingDependency}/started
stop on shutdown stop on shutdown
respawn ${pkgs.xorg.xfs}/bin/xfs -config ${configFile} respawn ${pkgs.xorg.xfs}/bin/xfs -config ${configFile}
"; '';
})];
};
} }

View File

@ -2,7 +2,7 @@
let let
inherit (pkgs.lib) mkOption mkIf; inherit (pkgs.lib) mkOption mkIf;
cfg = config.services.xserver.desktopManager.kde; cfg = config.services.xserver.desktopManager.kde4;
xorg = config.services.xserver.package; xorg = config.services.xserver.package;
options = { services = { xserver = { desktopManager = { options = { services = { xserver = { desktopManager = {