* 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 = {
enable = true;
experimental = true;
adminAddr = "admin@example.org";
subservices = {

View file

@ -129,32 +129,6 @@ let
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).
source = ./skel/bashrc;
target = "skel/.bashrc";
@ -187,15 +161,6 @@ let
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.
++ (map
(program:
@ -241,13 +206,6 @@ let
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

View file

@ -3,7 +3,8 @@
let
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:
textClosureOverridable steps (
@ -44,8 +45,9 @@ in
Activate the new configuration (i.e., update /etc, make accounts,
and so on).
'';
merge = mergeTypedOption "script" builtins.isAttrs mergeAttrs;
apply = set: let lib = addAttributeName set; in {
merge = mergeTypedOption "script" builtins.isAttrs (fold mergeAttrs {});
apply = set:
let lib = addAttributeName set; in {
inherit lib; # used to fetch dependencies.
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;
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
{
@ -157,7 +160,7 @@ in
activationScripts = {
users = FullDepEntry ''
while true; do
cat ${usersFile} | while true; do
read name || break
read description
read uid
@ -198,9 +201,7 @@ in
''${home:+--home "$home"} \
--shell "$shell"
fi
done <<EndOfUserList
${concatStringsSep "\n" (map serializedUser users)}
EndOfUserList
done
'' [
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, ...}:
###### interface
let
inherit (pkgs.lib) mkOption mkIf;
options = {
powerManagement = {
enable = mkOption {
default = false;
description = "Whether to enable power management (ACPI daemon)";
};
};
};
in
###### implementation
let
acpiConfDir = pkgs.runCommand "acpi-events" {}
@ -17,9 +34,7 @@ let
in pkgs.lib.concatMapStrings f events
}
'';
events = [powerEvent lidEvent acEvent];
# Called when the power button is pressed.
powerEvent =
{ name = "power-button";
@ -29,7 +44,7 @@ let
#! ${pkgs.bash}/bin/sh
'';
};
# Called when the laptop lid is opened/closed.
lidEvent =
{ name = "lid";
@ -47,7 +62,7 @@ let
fi
'';
};
# Called when the AC power is connected or disconnected.
acEvent =
{ name = "ac-power";
@ -64,20 +79,27 @@ let
'';
};
events = [powerEvent lidEvent acEvent];
in
{
name = "acpid";
extraPath = [pkgs.acpid];
job = ''
description "ACPI daemon"
mkIf config.powerManagement.enable {
require = [
options
];
start on udev
stop on shutdown
services = {
extraJobs = [{
name = "acpid";
respawn ${pkgs.acpid}/sbin/acpid --foreground --confdir ${acpiConfDir}
'';
job = ''
description "ACPI daemon"
start on udev
stop on shutdown
respawn ${pkgs.acpid}/sbin/acpid --foreground --confdir ${acpiConfDir}
'';
}];
};
}

View file

@ -1,6 +1,209 @@
{config, pkgs}:
{pkgs, config, ...}:
###### interface
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;
@ -361,65 +564,75 @@ let
in
{
name = "httpd";
users = [
{ name = mainCfg.user;
description = "Apache httpd user";
}
mkIf (config.services.httpd.enable && config.services.httpd.experimental) {
require = [
options
];
groups = [
{ name = mainCfg.group;
}
];
users = {
extraUsers = [
{ name = mainCfg.user;
description = "Apache httpd user";
}
];
extraGroups = [
{ name = mainCfg.group;
}
];
};
extraPath = [httpd] ++ concatMap (svc: svc.extraPath) allSubservices;
services = {
extraJobs = [{
name = "httpd";
# Statically verify the syntactic correctness of the generated
# httpd.conf. !!! this is impure! It doesn't just check for
# syntax, but also whether the Apache user/group exist, whether SSL
# keys exist, etc.
buildHook = ''
echo
echo '=== Checking the generated Apache configuration file ==='
${httpd}/bin/httpd -f ${httpdConf} -t || true
'';
extraPath = [httpd] ++ concatMap (svc: svc.extraPath) allSubservices;
job = ''
description "Apache HTTPD"
# Statically verify the syntactic correctness of the generated
# httpd.conf. !!! this is impure! It doesn't just check for
# syntax, but also whether the Apache user/group exist, whether SSL
# keys exist, etc.
buildHook = ''
echo
echo '=== Checking the generated Apache configuration file ==='
${httpd}/bin/httpd -f ${httpdConf} -t || true
'';
start on ${startingDependency}/started
stop on shutdown
job = ''
description "Apache HTTPD"
start script
mkdir -m 0700 -p ${mainCfg.stateDir}
mkdir -m 0700 -p ${mainCfg.logDir}
start on ${startingDependency}/started
stop on shutdown
# Get rid of old semaphores. These tend to accumulate across
# server restarts, eventually preventing it from restarting
# succesfully.
for i in $(${pkgs.utillinux}/bin/ipcs -s | grep ' ${mainCfg.user} ' | cut -f2 -d ' '); do
${pkgs.utillinux}/bin/ipcrm -s $i
done
start script
mkdir -m 0700 -p ${mainCfg.stateDir}
mkdir -m 0700 -p ${mainCfg.logDir}
# Run the startup hooks for the subservices.
for i in ${toString (map (svn: svn.startupScript) allSubservices)}; do
echo Running Apache startup hook $i...
$i
done
end script
# Get rid of old semaphores. These tend to accumulate across
# server restarts, eventually preventing it from restarting
# succesfully.
for i in $(${pkgs.utillinux}/bin/ipcs -s | grep ' ${mainCfg.user} ' | cut -f2 -d ' '); do
${pkgs.utillinux}/bin/ipcrm -s $i
done
${
let f = {name, value}: "env ${name}=${value}\n";
in concatMapStrings f (pkgs.lib.concatMap (svc: svc.globalEnvVars) allSubservices)
}
# Run the startup hooks for the subservices.
for i in ${toString (map (svn: svn.startupScript) allSubservices)}; do
echo Running Apache startup hook $i...
$i
done
end script
env PATH=${pkgs.coreutils}/bin:${pkgs.gnugrep}/bin:${pkgs.lib.concatStringsSep ":" (pkgs.lib.concatMap (svc: svc.extraServerPath) allSubservices)}
${
let f = {name, value}: "env ${name}=${value}\n";
in concatMapStrings f (pkgs.lib.concatMap (svc: svc.globalEnvVars) allSubservices)
}
respawn ${httpd}/bin/httpd -f ${httpdConf} -DNO_DETACH
'';
env PATH=${pkgs.coreutils}/bin:${pkgs.gnugrep}/bin:${pkgs.lib.concatStringsSep ":" (pkgs.lib.concatMap (svc: svc.extraServerPath) allSubservices)}
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
startingDependency = if config.services.gw6c.enable then "gw6c" else "network-interfaces";
cfg = config.services.bind;
@ -52,15 +100,24 @@ let
confFile = pkgs.writeText "named.conf" namedConf;
in
{
name = "bind";
job = ''
description "BIND name server job"
start script
${pkgs.coreutils}/bin/mkdir -p /var/run/named
end script
mkIf config.services.bind.enable {
require = [
options
];
respawn ${pkgs.bind}/sbin/named -c ${confFile} -f
'';
}
services = {
extraJobs = [{
name = "bind";
job = ''
description "BIND name server job"
start script
${pkgs.coreutils}/bin/mkdir -p /var/run/named
end script
respawn ${pkgs.bind}/sbin/named -c ${confFile} -f
'';
}];
};
}

View file

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

View file

@ -1,12 +1,20 @@
{
name = "ctrl-alt-delete";
job = "
on ctrlaltdel
{pkgs, config, ...}:
script
shutdown -r now 'Ctrl-Alt-Delete pressed'
end script
";
###### implementation
{
services = {
extraJobs = [{
name = "ctrl-alt-delete";
job = ''
on ctrlaltdel
script
shutdown -r now 'Ctrl-Alt-Delete pressed'
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
@ -7,6 +29,8 @@ let
inherit (pkgs) cups;
modprobe = config.system.sbin.modprobe;
# 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
@ -101,37 +125,45 @@ let
in
{
name = "cupsd";
extraPath = [cups];
extraEtc = [
# CUPS expects the following files in its ServerRoot.
{ source = "${cups}/etc/cups/mime.convs";
target = "cups/mime.convs";
}
{ source = "${cups}/etc/cups/mime.types";
target = "cups/mime.types";
}
mkIf config.services.pulseaudio.enable {
require = [
options
];
job = ''
description "CUPS printing daemon"
start on network-interfaces/started
stop on network-interfaces/stop
services = {
extraJobs = [{
name = "cupsd";
start script
mkdir -m 0755 -p ${logDir}
mkdir -m 0700 -p /var/cache/cups
mkdir -m 0700 -p /var/spool/cups
extraPath = [cups];
# Make USB printers show up.
${modprobe}/sbin/modprobe usblp || true
end script
extraEtc = [
# CUPS expects the following files in its ServerRoot.
{ source = "${cups}/etc/cups/mime.convs";
target = "cups/mime.convs";
}
{ source = "${cups}/etc/cups/mime.types";
target = "cups/mime.types";
}
];
job = ''
description "CUPS printing daemon"
respawn ${cups}/sbin/cupsd -c ${cupsdConfig} -F
'';
start on network-interfaces/started
stop on network-interfaces/stop
start script
mkdir -m 0755 -p ${logDir}
mkdir -m 0700 -p /var/cache/cups
mkdir -m 0700 -p /var/spool/cups
# Make USB printers show up.
${modprobe}/sbin/modprobe usblp || true
end script
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"
'';
} ];
# should have some checks to everify the syntax
# should have some checks to verify the syntax
merge = pkgs.lib.mergeListOption;
description = "
Additional Upstart jobs.
@ -66,373 +66,9 @@ let
optional = cond: service: pkgs.lib.optional cond (makeJob service);
requiredTTYs =
config.services.mingetty.ttys
++ config.boot.extraTTYs
++ [config.services.syslogd.tty];
requiredTTYs = config.requiredTTYs;
# looks for a job file foreach attr name found in services from config
# 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;
})
jobs = map makeJob []
# User-defined events.
++ (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
@ -25,26 +100,34 @@ let
in
{
name = "dhcpd";
job = ''
description "DHCP server"
start on network-interfaces/started
stop on network-interfaces/stop
mkIf config.services.dhcpd.enable {
require = [
options
];
script
services = {
extraJobs = [{
name = "dhcpd";
job = ''
description "DHCP server"
mkdir -m 755 -p ${stateDir}
start on network-interfaces/started
stop on network-interfaces/stop
touch ${stateDir}/dhcpd.leases
script
exec ${pkgs.dhcp}/sbin/dhcpd -f -cf ${configFile} \
-lf ${stateDir}/dhcpd.leases \
${toString cfg.interfaces}
mkdir -m 755 -p ${stateDir}
end script
'';
touch ${stateDir}/dhcpd.leases
exec ${pkgs.dhcp}/sbin/dhcpd -f -cf ${configFile} \
-lf ${stateDir}/dhcpd.leases \
${toString cfg.interfaces}
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
startingDependency = if config.services.gw6c.enable then "gw6c" else "network-interfaces";
@ -54,36 +95,51 @@ let
'';
in
{
name = "dovecot";
users = [{
name = cfg.user;
uid = idList.uids.dovecot;
description = "Dovecot user";
group = cfg.group;
}];
groups = [{
name = cfg.group;
gid = idList.gids.dovecot;
}];
job = ''
description "Dovecot IMAP/POP3 server"
mkIf config.services.dovecot.enable {
start on ${startingDependency}/started
stop on never
require = [
options
];
start script
${pkgs.coreutils}/bin/mkdir -p /var/run/dovecot /var/run/dovecot/login
${pkgs.coreutils}/bin/chown -R ${cfg.user}.${cfg.group} /var/run/dovecot
end script
environment = {
etc = [{
source = pamdFile;
target = "pam.d/dovecot";
}];
};
respawn ${pkgs.dovecot}/sbin/dovecot -F -c ${confFile}
'';
users = {
extraUsers = [{
name = cfg.user;
uid = idList.uids.dovecot;
description = "Dovecot user";
group = cfg.group;
}];
extraGroups = [{
name = cfg.group;
gid = idList.gids.dovecot;
}];
};
extraEtc = [{
source = pamdFile;
target = "pam.d/dovecot";
}];
services = {
extraJobs = [{
name = "dovecot";
job = ''
description "Dovecot IMAP/POP3 server"
start on ${startingDependency}/started
stop on never
start script
${pkgs.coreutils}/bin/mkdir -p /var/run/dovecot /var/run/dovecot/login
${pkgs.coreutils}/bin/chown -R ${cfg.user}.${cfg.group} /var/run/dovecot
end script
respawn ${pkgs.dovecot}/sbin/dovecot -F -c ${confFile}
'';
}];
};
}

View file

@ -1,36 +1,85 @@
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
cfg = config.services.ejabberd;
in
{
name = "ejabberd";
job = ''
description "EJabberd server"
start on network-interface/started
stop on network-interfaces/stop
start script
# Initialise state data
mkdir -p ${cfg.logsDir}
if ! test -d ${cfg.spoolDir}
then
cp -av ${pkgs.ejabberd}/var/lib/ejabberd /var/lib
fi
mkdir -p ${cfg.confDir}
sed -e 's|{hosts, \["localhost"\]}.|{hosts, \[${cfg.virtualHosts}\]}.|' ${pkgs.ejabberd}/etc/ejabberd/ejabberd.cfg > ${cfg.confDir}/ejabberd.cfg
end script
mkIf config.services.ejabberd.enable {
require = [
options
];
services = {
extraJobs = [{
name = "ejabberd";
job = ''
description "EJabberd server"
start on network-interface/started
stop on network-interfaces/stop
respawn ${pkgs.bash}/bin/sh -c 'export PATH=$PATH:${pkgs.ejabberd}/sbin; cd ~; ejabberdctl --logs ${cfg.logsDir} --spool ${cfg.spoolDir} --config ${cfg.confDir}/ejabberd.cfg start; sleep 1d'
stop script
${pkgs.ejabberd}/sbin/ejabberdctl stop
end script
'';
start script
# Initialise state data
mkdir -p ${cfg.logsDir}
if ! test -d ${cfg.spoolDir}
then
cp -av ${pkgs.ejabberd}/var/lib/ejabberd /var/lib
fi
mkdir -p ${cfg.confDir}
sed -e 's|{hosts, \["localhost"\]}.|{hosts, \[${cfg.virtualHosts}\]}.|' ${pkgs.ejabberd}/etc/ejabberd/ejabberd.cfg > ${cfg.confDir}/ejabberd.cfg
end script
respawn ${pkgs.bash}/bin/sh -c 'export PATH=$PATH:${pkgs.ejabberd}/sbin; cd ~; ejabberdctl --logs ${cfg.logsDir} --spool ${cfg.spoolDir} --config ${cfg.confDir}/ejabberd.cfg start; sleep 1d'
stop script
${pkgs.ejabberd}/sbin/ejabberdctl stop
end script
'';
}];
};
}

View file

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

View file

@ -1,64 +1,218 @@
{ gnunet, gnunetConfig, lib, writeText }:
{pkgs, config, ...}:
assert gnunetConfig.enable;
###### interface
let
inherit (pkgs.lib) mkOption mkIf;
{
name = "gnunetd";
options = {
services = {
gnunet = {
enable = mkOption {
default = false;
description = ''
Whether to run the GNUnet daemon. GNUnet is GNU's anonymous
peer-to-peer communication and file sharing framework.
'';
};
users = [
{ name = "gnunetd";
uid = (import ../system/ids.nix).uids.gnunetd;
description = "GNUnet Daemon User";
home = "/var/empty";
}
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
];
job =
with gnunetConfig;
let configFile = writeText "gnunetd.conf" ''
[PATHS]
GNUNETD_HOME = ${home}
users = {
extraUsers = [
{ name = "gnunetd";
uid = (import ../system/ids.nix).uids.gnunetd;
description = "GNUnet Daemon User";
home = "/var/empty";
}
];
};
[GNUNETD]
HOSTLISTURL = ${lib.concatStringsSep " " hostLists}
APPLICATIONS = ${lib.concatStringsSep " " applications}
TRANSPORTS = ${lib.concatStringsSep " " transports}
services = {
extraJobs = [{
name = "gnunetd";
[LOAD]
MAXNETDOWNBPSTOTAL = ${toString load.maxNetDownBandwidth}
MAXNETUPBPSTOTAL = ${toString load.maxNetUpBandwidth}
HARDUPLIMIT = ${toString load.hardNetUpBandwidth}
MAXCPULOAD = ${toString load.maxCPULoad}
INTERFACES = ${lib.concatStringsSep " " load.interfaces}
job =
with config.services.gnunet;
let
inherit (pkgs) lib gnunet;
configFile = pkgs.writeText "gnunetd.conf" ''
[PATHS]
GNUNETD_HOME = ${home}
[FS]
QUOTA = ${toString fileSharing.quota}
ACTIVEMIGRATION = ${if fileSharing.activeMigration then "YES" else "NO"}
[GNUNETD]
HOSTLISTURL = ${lib.concatStringsSep " " hostLists}
APPLICATIONS = ${lib.concatStringsSep " " applications}
TRANSPORTS = ${lib.concatStringsSep " " transports}
[MODULES]
sqstore = sqstore_sqlite
dstore = dstore_sqlite
topology = topology_default
[LOAD]
MAXNETDOWNBPSTOTAL = ${toString load.maxNetDownBandwidth}
MAXNETUPBPSTOTAL = ${toString load.maxNetUpBandwidth}
HARDUPLIMIT = ${toString load.hardNetUpBandwidth}
MAXCPULOAD = ${toString load.maxCPULoad}
INTERFACES = ${lib.concatStringsSep " " load.interfaces}
${extraOptions}
'';
[FS]
QUOTA = ${toString fileSharing.quota}
ACTIVEMIGRATION = ${if fileSharing.activeMigration then "YES" else "NO"}
in ''
description "The GNUnet Daemon"
[MODULES]
sqstore = sqstore_sqlite
dstore = dstore_sqlite
topology = topology_default
start on network-interfaces/started
stop on network-interfaces/stop
${extraOptions}
'';
in ''
description "The GNUnet Daemon"
start script
test -d "${home}" || \
( mkdir -m 755 -p "${home}" && chown -R gnunetd:users "${home}")
end script
start on network-interfaces/started
stop on network-interfaces/stop
respawn ${gnunet}/bin/gnunetd \
${if debug then "--debug" else "" } \
--user="gnunetd" \
--config="${configFile}" \
--log="${logLevel}"
'';
start script
test -d "${home}" || \
( mkdir -m 755 -p "${home}" && chown -R gnunetd:users "${home}")
end script
respawn ${gnunet}/bin/gnunetd \
${if debug then "--debug" else "" } \
--user="gnunetd" \
--config="${configFile}" \
--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
cfg = config.services.gw6c;
procps = pkgs.procps;
gw6cService = import ../services/gw6c {
gw6cService = import ../../services/gw6c {
inherit (pkgs) stdenv gw6c coreutils
procps upstart iputils gnused
gnugrep seccureUser writeScript;
@ -17,16 +115,26 @@ let
waitPingableBroker = cfg.waitPingableBroker;
};
in
{
mkIf config.services.gw6c.enable {
require = [
options
];
services = {
extraJobs = [{
name = "gw6c";
users = [];
groups = [];
job = "
description \"Gateway6 client\"
job = ''
description \"Gateway6 client\"
start on ${ if cfg.autorun then "network-interfaces/started" else "never" }
stop on network-interfaces/stop
start on ${ if cfg.autorun then "network-interfaces/started" else "never" }
stop on network-interfaces/stop
respawn ${gw6cService}/bin/control start
";
respawn ${gw6cService}/bin/control start
'';
}];
};
}

View file

@ -1,103 +1,120 @@
{bash, event, utillinux}:
{pkgs, config, ...}:
###### implementation
/* FIXME
assert event == "reboot"
|| event == "halt"
|| event == "system-halt"
|| event == "power-off";
*/
let
inherit (pkgs) bash utillinux;
jobFun = event : {
name = "sys-" + event;
job = ''
start on ${event}
script
set +e # continue in case of errors
exec < /dev/tty1 > /dev/tty1 2>&1
echo ""
echo "<<< SYSTEM SHUTDOWN >>>"
echo ""
export PATH=${utillinux}/bin:${utillinux}/sbin:$PATH
# Set the hardware clock to the system time.
echo "Setting the hardware clock..."
hwclock --systohc --utc || true
# Do an initial sync just in case.
sync || true
# Kill all remaining processes except init and this one.
echo "Sending the TERM signal to all processes..."
kill -TERM -1 || true
sleep 1 # wait briefly
echo "Sending the KILL signal to all processes..."
kill -KILL -1 || true
# Unmount helper functions.
getMountPoints() {
cat /proc/mounts \
| grep -v '^rootfs' \
| sed 's|^[^ ]\+ \+\([^ ]\+\).*|\1|' \
| grep -v '/proc\|/sys\|/dev'
}
getDevice() {
local mountPoint=$1
cat /proc/mounts \
| grep -v '^rootfs' \
| grep "^[^ ]\+ \+$mountPoint \+" \
| sed 's|^\([^ ]\+\).*|\1|'
}
# Unmount file systems. We repeat this until no more file systems
# can be unmounted. This is to handle loopback devices, file
# systems mounted on other file systems and so on.
tryAgain=1
while test -n "$tryAgain"; do
tryAgain=
for mp in $(getMountPoints); do
device=$(getDevice $mp)
echo "unmounting $mp..."
if umount -f -n "$mp"; then
if test "$mp" != /; then tryAgain=1; fi
else
mount -n -o remount,ro "$mp" || true
fi
# Hack: work around a bug in mount (mount -o remount on a
# loop device forgets the loop=/dev/loopN entry in
# /etc/mtab).
if echo "$device" | grep -q '/dev/loop'; then
echo "removing loop device $device..."
losetup -d "$device" || true
fi
done
done
cat /proc/mounts
# Final sync.
sync || true
# Right now all events above power off the system.
if test ${event} = reboot; then
exec reboot -f
else
exec halt -f -p
fi
end script
'';
};
in
{
name = "sys-" + event;
job = "
start on ${event}
script
set +e # continue in case of errors
exec < /dev/tty1 > /dev/tty1 2>&1
echo \"\"
echo \"<<< SYSTEM SHUTDOWN >>>\"
echo \"\"
export PATH=${utillinux}/bin:${utillinux}/sbin:$PATH
# Set the hardware clock to the system time.
echo \"Setting the hardware clock...\"
hwclock --systohc --utc || true
# Do an initial sync just in case.
sync || true
# Kill all remaining processes except init and this one.
echo \"Sending the TERM signal to all processes...\"
kill -TERM -1 || true
sleep 1 # wait briefly
echo \"Sending the KILL signal to all processes...\"
kill -KILL -1 || true
# Unmount helper functions.
getMountPoints() {
cat /proc/mounts \\
| grep -v '^rootfs' \\
| sed 's|^[^ ]\\+ \\+\\([^ ]\\+\\).*|\\1|' \\
| grep -v '/proc\\|/sys\\|/dev'
}
getDevice() {
local mountPoint=$1
cat /proc/mounts \\
| grep -v '^rootfs' \\
| grep \"^[^ ]\\+ \\+$mountPoint \\+\" \\
| sed 's|^\\([^ ]\\+\\).*|\\1|'
}
# Unmount file systems. We repeat this until no more file systems
# can be unmounted. This is to handle loopback devices, file
# systems mounted on other file systems and so on.
tryAgain=1
while test -n \"$tryAgain\"; do
tryAgain=
for mp in $(getMountPoints); do
device=$(getDevice $mp)
echo \"unmounting $mp...\"
if umount -f -n \"$mp\"; then
if test \"$mp\" != /; then tryAgain=1; fi
else
mount -n -o remount,ro \"$mp\" || true
fi
# Hack: work around a bug in mount (mount -o remount on a
# loop device forgets the loop=/dev/loopN entry in
# /etc/mtab).
if echo \"$device\" | grep -q '/dev/loop'; then
echo \"removing loop device $device...\"
losetup -d \"$device\" || true
fi
done
done
cat /proc/mounts
# Final sync.
sync || true
# Right now all events above power off the system.
if test ${event} = reboot; then
exec reboot -f
else
exec halt -f -p
fi
end script
";
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
@ -21,6 +31,11 @@ let
applicationMappings = cfg.mod_jk.applicationMappings;
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 {
inherit (pkgs) apacheHttpd coreutils;
@ -32,6 +47,7 @@ let
user group adminAddr logDir stateDir
applicationMappings;
noUserDir = !cfg.enableUserDir;
extraDirectories = extraConfig + "\n" + cfg.extraConfig;
subServices =
@ -72,41 +88,47 @@ let
)
)
)
)
/* ++
(optional cfg.extraSubservices.enable
(map (service : service webServer pkgs) cfg.extraSubservices.services)
) */;
);
};
in
{
name = "httpd";
users = [
{ name = user;
description = "Apache httpd user";
}
mkIf (config.services.httpd.enable && !config.services.httpd.experimental) {
require = [
# options have been moved to the apache-httpd/default.nix file
];
groups = [
{ name = group;
}
];
job = "
description \"Apache HTTPD\"
start on ${startingDependency}/started
stop on ${startingDependency}/stop
start script
${webServer}/bin/control prepare
end script
respawn ${webServer}/bin/control run
";
users = {
extraUsers = [
{ name = user;
description = "Apache httpd user";
}
];
extraGroups = [
{ name = group;
}
];
};
services = {
extraJobs = [{
name = "httpd";
job = ''
description \"Apache HTTPD\"
start on ${startingDependency}/started
stop on ${startingDependency}/stop
start script
${webServer}/bin/control prepare
end script
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
inherit (pkgs) ifplugd writeScript bash;
# The ifplugd action script, which is called whenever the link
# 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
@ -17,19 +52,27 @@ let
in
{
name = "ifplugd";
mkIf config.networking.interfaceMonitor.enable {
require = [
options
];
extraPath = [ifplugd];
job = "
description \"Network interface connectivity monitor\"
services = {
extraJobs = [{
name = "ifplugd";
start on network-interfaces/started
stop on network-interfaces/stop
extraPath = [ifplugd];
job = ''
description "Network interface connectivity monitor"
respawn ${ifplugd}/sbin/ifplugd --no-daemon --no-startup --no-shutdown \\
${if config.networking.interfaceMonitor.beep then "" else "--no-beep"} \\
--run ${plugScript}";
start on network-interfaces/started
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}
'';
}];
};
}

View file

@ -1,38 +1,130 @@
{config, pkgs}:
{pkgs, config, ...}:
###### interface
let
cfg = config.services.ircdHybrid;
ircdService = import ../services/ircd-hybrid {
stdenv = pkgs.stdenv;
inherit (pkgs) ircdHybrid coreutils
su iproute gnugrep procps;
serverName = cfg.serverName;
sid = cfg.sid;
description = cfg.description;
rsaKey = cfg.rsaKey;
certificate = cfg.certificate;
adminEmail = cfg.adminEmail;
extraIPs = cfg.extraIPs;
extraPort = cfg.extraPort;
gw6cEnabled = (config.services.gw6c.enable) &&
(config.services.gw6c.autorun);
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
cfg = config.services.ircdHybrid;
ircdService = import ../../services/ircd-hybrid {
stdenv = pkgs.stdenv;
inherit (pkgs) ircdHybrid coreutils
su iproute gnugrep procps;
serverName = cfg.serverName;
sid = cfg.sid;
description = cfg.description;
rsaKey = cfg.rsaKey;
certificate = cfg.certificate;
adminEmail = cfg.adminEmail;
extraIPs = cfg.extraIPs;
extraPort = cfg.extraPort;
gw6cEnabled = (config.services.gw6c.enable) &&
(config.services.gw6c.autorun);
};
startingDependency = if config.services.gw6c.enable then "gw6c" else "network-interfaces";
in
{
name = "ircd-hybrid";
users = [ {
name = "ircd";
description = "IRCD owner.";
} ];
groups = [{name = "ircd";}];
job = "
description = \"IRCD Hybrid server.\"
start on ${startingDependency}/started
stop on ${startingDependency}/stop
mkIf config.services.ircdHybrid.enable {
require = [
options
];
respawn ${ircdService}/bin/control start
";
services = {
extraJobs = [{
name = "ircd-hybrid";
users = [ {
name = "ircd";
description = "IRCD owner.";
} ];
groups = [{name = "ircd";}];
job = ''
description = "IRCD Hybrid server."
start on ${startingDependency}/started
stop on ${startingDependency}/stop
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
cfg = config.services.jboss;
jbossService = import ../services/jboss {
jbossService = import ../../services/jboss {
inherit (pkgs) stdenv jboss su;
inherit (cfg) tempDir logDir libUrl deployDir serverDir user useJK;
};
in
{
name = "jboss";
job = "
description \"JBoss server\"
stop on shutdown
mkIf config.services.jboss.enable {
require = [
options
];
respawn ${jbossService}/bin/control start
";
services = {
extraJobs = [{
name = "jboss";
job = ''
description \"JBoss server\"
stop on shutdown
respawn ${jbossService}/bin/control start
'';
}];
};
}

View file

@ -1,78 +1,109 @@
{glibc, kbd, gzip, ttyNumbers, defaultLocale, consoleFont, consoleKeyMap}:
{pkgs, config, ...}:
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;
defaultLocale = config.i18n.defaultLocale;
consoleFont = config.i18n.consoleFont;
consoleKeyMap = config.i18n.consoleKeyMap;
in
###### implementation
# most options are defined in i18n.nix
{
name = "kbd";
extraPath = [
kbd
inherit requiredTTYs; # pass them to upstart-job/default.nix
# dummy option so that requiredTTYs can be passed, see above (FIXME)
require = [
{
requiredTTYs = mkOption {
default = [];
};
}
];
job = "
description \"Keyboard / console initialisation\"
start on udev
script
export LANG=${defaultLocale}
export PATH=${gzip}/bin:$PATH # Needed by setfont
set +e # continue in case of errors
services = {
extraJobs = [{
name = "kbd";
extraPath = [
pkgs.kbd
];
# Enable or disable UTF-8 mode. This is based on
# unicode_{start,stop}.
echo 'Enabling or disabling Unicode mode...'
job = "
description \"Keyboard / console initialisation\"
charMap=$(${glibc}/bin/locale charmap)
start on udev
if test \"$charMap\" = UTF-8; then
script
for tty in ${toString ttys}; do
export LANG=${defaultLocale}
export PATH=${pkgs.gzip}/bin:$PATH # Needed by setfont
# Tell the console output driver that the bytes arriving are
# UTF-8 encoded multibyte sequences.
echo -n -e '\\033%G' > $tty
set +e # continue in case of errors
done
# Enable or disable UTF-8 mode. This is based on
# unicode_{start,stop}.
echo 'Enabling or disabling Unicode mode...'
# Set the keyboard driver in UTF-8 mode.
${kbd}/bin/kbd_mode -u
charMap=$(${pkgs.glibc}/bin/locale charmap)
else
if test \"$charMap\" = UTF-8; then
for tty in ${toString ttys}; do
for tty in ${toString ttys}; do
# Tell the console output driver that the bytes arriving are
# UTF-8 encoded multibyte sequences.
echo -n -e '\\033%@' > $tty
# Tell the console output driver that the bytes arriving are
# UTF-8 encoded multibyte sequences.
echo -n -e '\\033%G' > $tty
done
done
# Set the keyboard driver in ASCII (or any 8-bit character
# set) mode.
${kbd}/bin/kbd_mode -a
# Set the keyboard driver in UTF-8 mode.
${pkgs.kbd}/bin/kbd_mode -u
fi
else
for tty in ${toString ttys}; do
# Tell the console output driver that the bytes arriving are
# UTF-8 encoded multibyte sequences.
echo -n -e '\\033%@' > $tty
done
# Set the keyboard driver in ASCII (or any 8-bit character
# set) mode.
${pkgs.kbd}/bin/kbd_mode -a
fi
# Set the console font.
for tty in ${toString ttys}; do
${kbd}/bin/setfont -C $tty ${consoleFont}
done
# Set the console font.
for tty in ${toString ttys}; do
${pkgs.kbd}/bin/setfont -C $tty ${consoleFont}
done
# Set the keymap.
${kbd}/bin/loadkeys '${consoleKeyMap}'
# Set the keymap.
${pkgs.kbd}/bin/loadkeys '${consoleKeyMap}'
end script
";
end script
";
}];
};
}

View file

@ -1,26 +1,33 @@
{sysklogd, writeText, config}:
{pkgs, config, ...}:
###### implementation
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
{
name = "klogd";
job = ''
description "Kernel log daemon"
start on syslogd
stop on shutdown
start script
# !!! this hangs for some reason (it blocks reading from
# /proc/kmsg).
#${klogdCmd} -o
end script
services = {
extraJobs = [{
name = "klogd";
job = ''
description "Kernel log daemon"
start on syslogd
stop on shutdown
respawn ${klogdCmd} -n
'';
start script
# !!! this hangs for some reason (it blocks reading from
# /proc/kmsg).
#${klogdCmd} -o
end script
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,54 +1,175 @@
{lsh, xauth, lib, nssModulesPath, lshdConfig}:
{pkgs, config, ...}:
with builtins;
with lib;
###### interface
let
inherit (pkgs.lib) mkOption mkIf;
{
name = "lshd";
job = with lshdConfig; ''
description "GNU lshd SSH2 daemon"
options = {
services = {
lshd = {
start on network-interfaces/started
stop on network-interfaces/stop
enable = mkOption {
default = false;
description = ''
Whether to enable the GNU lshd SSH2 daemon, which allows
secure remote login.
'';
};
env LD_LIBRARY_PATH=${nssModulesPath}
portNumber = mkOption {
default = 22;
description = ''
The port on which to listen for connections.
'';
};
start script
test -d /etc/lsh || mkdir -m 0755 -p /etc/lsh
test -d /var/spool/lsh || mkdir -m 0755 -p /var/spool/lsh
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" ];
};
if ! test -f /var/spool/lsh/yarrow-seed-file
then
${lsh}/bin/lsh-make-seed -o /var/spool/lsh/yarrow-seed-file
fi
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.
'';
};
if ! test -f "${hostKey}"
then
${lsh}/bin/lsh-keygen --server | \
${lsh}/bin/lsh-writekey --server -o "${hostKey}"
fi
end script
syslog = mkOption {
default = true;
description = ''Whether to enable syslog output.'';
};
respawn ${lsh}/sbin/lshd --daemonic \
--password-helper="${lsh}/sbin/lsh-pam-checkpw" \
-p ${toString portNumber} \
${if interfaces == [] then ""
else (concatStrings (map (i: "--interface=\"${i}\"")
interfaces))} \
-h "${hostKey}" \
${if !syslog then "--no-syslog" else ""} \
${if passwordAuthentication then "--password" else "--no-password" } \
${if publicKeyAuthentication then "--publickey" else "--no-publickey" } \
${if rootLogin then "--root-login" else "--no-root-login" } \
${if loginShell != null then "--login-shell=\"${loginShell}\"" else "" } \
${if srpKeyExchange then "--srp-keyexchange" else "--no-srp-keyexchange" } \
${if !tcpForwarding then "--no-tcpip-forward" else "--tcpip-forward"} \
${if x11Forwarding then "--x11-forward" else "--no-x11-forward" } \
--subsystems=${concatStringsSep ","
(map (pair: (head pair) + "=" +
(head (tail pair)))
subsystems)}
'';
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";
job = with lshdConfig; ''
description "GNU lshd SSH2 daemon"
start on network-interfaces/started
stop on network-interfaces/stop
env LD_LIBRARY_PATH=${nssModulesPath}
start script
test -d /etc/lsh || mkdir -m 0755 -p /etc/lsh
test -d /var/spool/lsh || mkdir -m 0755 -p /var/spool/lsh
if ! test -f /var/spool/lsh/yarrow-seed-file
the
${lsh}/bin/lsh-make-seed -o /var/spool/lsh/yarrow-seed-file
fi
if ! test -f "${hostKey}"
then
${lsh}/bin/lsh-keygen --server | \
${lsh}/bin/lsh-writekey --server -o "${hostKey}"
fi
end script
respawn ${lsh}/sbin/lshd --daemonic \
--password-helper="${lsh}/sbin/lsh-pam-checkpw" \
-p ${toString portNumber} \
${if interfaces == [] then ""
else (concatStrings (map (i: "--interface=\"${i}\"")
interfaces))} \
-h "${hostKey}" \
${if !syslog then "--no-syslog" else ""} \
${if passwordAuthentication then "--password" else "--no-password" } \
${if publicKeyAuthentication then "--publickey" else "--no-publickey" } \
${if rootLogin then "--root-login" else "--no-root-login" } \
${if loginShell != null then "--login-shell=\"${loginShell}\"" else "" } \
${if srpKeyExchange then "--srp-keyexchange" else "--no-srp-keyexchange" } \
${if !tcpForwarding then "--no-tcpip-forward" else "--tcpip-forward"} \
${if x11Forwarding then "--x11-forward" else "--no-x11-forward" } \
--subsystems=${concatStringsSep ","
(map (pair: (head pair) + "=" +
(head (tail pair)))
subsystems)}
'';
}
];
};
}

View file

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

View file

@ -1,19 +1,24 @@
{bash}:
{pkgs, config, ...}:
###### implementation
{
name = "maintenance-shell";
job = "
start on maintenance
start on stalled
script
exec < /dev/tty1 > /dev/tty1 2>&1
echo \"\"
echo \"<<< MAINTENANCE SHELL >>>\"
echo \"\"
exec ${bash}/bin/sh
end script
";
services = {
extraJobs = [{
name = "maintenance-shell";
job = ''
start on maintenance
start on stalled
script
exec < /dev/tty1 > /dev/tty1 2>&1
echo \"\"
echo \"<<< MAINTENANCE SHELL >>>\"
echo \"\"
exec ${pkgs.bash}/bin/sh
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
{
name = "tty" + toString ttyNumber;
job = "
start on udev
stop on shutdown
respawn ${mingetty}/sbin/mingetty --loginprog=${loginProgram} --noclear tty${toString ttyNumber}
";
require = [
options
];
services = {
extraJobs = map (ttyNumber : {
name = "tty" + toString ttyNumber;
job = "
start on udev
stop on shutdown
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
@ -14,39 +59,51 @@ let
in
{
name = "mysql";
users = [
{ name = "mysql";
description = "MySQL server user";
}
mkIf config.services.mysql.enable {
require = [
options
];
extraPath = [mysql];
job = ''
description "MySQL server"
users = {
extraUsers = [
{ name = "mysql";
description = "MySQL server user";
}
];
};
stop on shutdown
services = {
extraJobs = [{
name = "mysql";
start script
if ! test -e ${cfg.dataDir}; then
mkdir -m 0700 -p ${cfg.dataDir}
chown -R ${cfg.user} ${cfg.dataDir}
${mysql}/bin/mysql_install_db ${mysqldOptions}
fi
extraPath = [mysql];
job = ''
description "MySQL server"
mkdir -m 0700 -p ${cfg.pidDir}
chown -R ${cfg.user} ${cfg.pidDir}
end script
stop on shutdown
respawn ${mysql}/bin/mysqld ${mysqldOptions}
start script
if ! test -e ${cfg.dataDir}; then
mkdir -m 0700 -p ${cfg.dataDir}
chown -R ${cfg.user} ${cfg.dataDir}
${mysql}/bin/mysql_install_db ${mysqldOptions}
fi
stop script
pid=$(cat ${pidFile})
kill "$pid"
${mysql}/bin/mysql_waitpid "$pid" 1000
end script
'';
mkdir -m 0700 -p ${cfg.pidDir}
chown -R ${cfg.user} ${cfg.pidDir}
end script
respawn ${mysql}/bin/mysqld ${mysqldOptions}
stop script
pid=$(cat ${pidFile})
kill "$pid"
${mysql}/bin/mysql_waitpid "$pid" 1000
end script
'';
}];
};
}

View file

@ -1,7 +1,11 @@
{nettools, modprobe, wirelesstools, bash, writeText, config}:
{pkgs, config, ...}:
###### implementation
let
inherit (pkgs) nettools wirelesstools bash writeText;
cfg = config.networking;
# !!! use XML
@ -10,91 +14,96 @@ let
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;
wepKeys = map (i: if i ? wepKey then i.wepKey else "nokey") cfg.interfaces;
modprobe = config.system.sbin.modprobe;
in
{
name = "network-interfaces";
job = ''
start on udev
stop on shutdown
start script
export PATH=${modprobe}/sbin:$PATH
modprobe af_packet || true
for i in $(cd /sys/class/net && ls -d *); do
echo "Bringing up network device $i..."
${nettools}/sbin/ifconfig $i up || true
done
# Configure the manually specified interfaces.
names=(${toString names})
ipAddresses=(${toString ipAddresses})
subnetMasks=(${toString subnetMasks})
essids=(${toString essids})
wepKeys=(${toString wepKeys})
for ((n = 0; n < ''${#names[*]}; n++)); do
name=''${names[$n]}
ipAddress=''${ipAddresses[$n]}
subnetMask=''${subnetMasks[$n]}
essid=''${essids[$n]}
wepKey=''${wepKeys[$n]}
# Set wireless networking stuff.
if test "$essid" != default; then
${wirelesstools}/sbin/iwconfig "$name" essid "$essid" || true
fi
if test "$wepKey" != nokey; then
${wirelesstools}/sbin/iwconfig "$name" key "$(cat "$wepKey")" || true
fi
# Set IP address / netmask.
if test "$ipAddress" != dhcp; then
echo "Configuring interface $name..."
extraFlags=
if test "$subnetMask" != default; then
extraFlags="$extraFlags netmask $subnetMask"
fi
${nettools}/sbin/ifconfig "$name" "$ipAddress" $extraFlags || true
fi
done
# Set the nameservers.
if test -n "${toString cfg.nameservers}"; then
rm -f /etc/resolv.conf
if test -n "${cfg.domain}"; then
echo "domain ${cfg.domain}" >> /etc/resolv.conf
fi
for i in ${toString cfg.nameservers}; do
echo "nameserver $i" >> /etc/resolv.conf
done
fi
# Set the default gateway.
if test -n "${cfg.defaultGateway}"; then
${nettools}/sbin/route add default gw "${cfg.defaultGateway}" || true
fi
# Run any user-specified commands.
${bash}/bin/sh ${writeText "local-net-cmds" cfg.localCommands} || true
end script
# Hack: Upstart doesn't yet support what we want: a service that
# doesn't have a running process associated with it.
respawn sleep 100000
stop script
for i in $(cd /sys/class/net && ls -d *); do
echo "Taking down network device $i..."
${nettools}/sbin/ifconfig $i down || true
done
end script
'';
services = {
extraJobs = [{
name = "network-interfaces";
job = ''
start on udev
stop on shutdown
start script
export PATH=${modprobe}/sbin:$PATH
modprobe af_packet || true
for i in $(cd /sys/class/net && ls -d *); do
echo "Bringing up network device $i..."
${nettools}/sbin/ifconfig $i up || true
done
# Configure the manually specified interfaces.
names=(${toString names})
ipAddresses=(${toString ipAddresses})
subnetMasks=(${toString subnetMasks})
essids=(${toString essids})
wepKeys=(${toString wepKeys})
for ((n = 0; n < ''${#names[*]}; n++)); do
name=''${names[$n]}
ipAddress=''${ipAddresses[$n]}
subnetMask=''${subnetMasks[$n]}
essid=''${essids[$n]}
wepKey=''${wepKeys[$n]}
# Set wireless networking stuff.
if test "$essid" != default; then
${wirelesstools}/sbin/iwconfig "$name" essid "$essid" || true
fi
if test "$wepKey" != nokey; then
${wirelesstools}/sbin/iwconfig "$name" key "$(cat "$wepKey")" || true
fi
# Set IP address / netmask.
if test "$ipAddress" != dhcp; then
echo "Configuring interface $name..."
extraFlags=
if test "$subnetMask" != default; then
extraFlags="$extraFlags netmask $subnetMask"
fi
${nettools}/sbin/ifconfig "$name" "$ipAddress" $extraFlags || true
fi
done
# Set the nameservers.
if test -n "${toString cfg.nameservers}"; then
rm -f /etc/resolv.conf
if test -n "${cfg.domain}"; then
echo "domain ${cfg.domain}" >> /etc/resolv.conf
fi
for i in ${toString cfg.nameservers}; do
echo "nameserver $i" >> /etc/resolv.conf
done
fi
# Set the default gateway.
if test -n "${cfg.defaultGateway}"; then
${nettools}/sbin/route add default gw "${cfg.defaultGateway}" || true
fi
# Run any user-specified commands.
${bash}/bin/sh ${writeText "local-net-cmds" cfg.localCommands} || true
end script
# Hack: Upstart doesn't yet support what we want: a service that
# doesn't have a running process associated with it.
respawn sleep 100000
stop script
for i in $(cd /sys/class/net && ls -d *); do
echo "Taking down network device $i..."
${nettools}/sbin/ifconfig $i down || true
done
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,35 +1,44 @@
{glibc, nssModulesPath}:
{pkgs, config, ...}:
###### implementation
let
nssModulesPath = config.system.nssModules.path;
in
{
name = "nscd";
users = [
{ name = "nscd";
uid = (import ../system/ids.nix).uids.nscd;
description = "Name service cache daemon user";
}
];
job = "
description \"Name Service Cache Daemon\"
start on startup
stop on shutdown
env LD_LIBRARY_PATH=${nssModulesPath}
start script
mkdir -m 0755 -p /var/run/nscd
mkdir -m 0755 -p /var/db/nscd
rm -f /var/db/nscd/* # for testing
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
";
services = {
extraJobs = [{
name = "nscd";
users = [
{ name = "nscd";
uid = (import ../system/ids.nix).uids.nscd;
description = "Name service cache daemon user";
}
];
job = ''
description \"Name Service Cache Daemon\"
start on startup
stop on shutdown
env LD_LIBRARY_PATH=${nssModulesPath}
start script
mkdir -m 0755 -p /var/run/nscd
mkdir -m 0755 -p /var/db/nscd
rm -f /var/db/nscd/* # for testing
end script
# !!! -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,52 +1,101 @@
{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
inherit (pkgs) writeText ntp;
stateDir = "/var/lib/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
${toString (map (server: "server " + server + "\n") servers)}
'';
ntpFlags = "-c ${config} -u ${ntpUser}:nogroup -i ${stateDir}";
ntpFlags = "-c ${configFile} -u ${ntpUser}:nogroup -i ${stateDir}";
in
{
name = "ntpd";
users = [
{ name = ntpUser;
uid = (import ../system/ids.nix).uids.ntp;
description = "NTP daemon user";
home = stateDir;
}
mkIf config.services.ntp.enable {
require = [
options
];
job = ''
description "NTP daemon"
start on ip-up
stop on ip-down
stop on shutdown
services = {
extraJobs = [{
start script
name = "ntpd";
users = [
{ name = ntpUser;
uid = (import ../system/ids.nix).uids.ntp;
description = "NTP daemon user";
home = stateDir;
}
];
job = ''
description "NTP daemon"
mkdir -m 0755 -p ${stateDir}
chown ${ntpUser} ${stateDir}
start on ip-up
stop on ip-down
stop on shutdown
# Needed to run ntpd as an unprivileged user.
${modprobe}/sbin/modprobe capability || true
start script
${ntp}/bin/ntpd -q -g ${ntpFlags}
mkdir -m 0755 -p ${stateDir}
chown ${ntpUser} ${stateDir}
end script
# Needed to run ntpd as an unprivileged user.
${modprobe}/sbin/modprobe capability || true
respawn ${ntp}/bin/ntpd -n ${ntpFlags}
'';
${ntp}/bin/ntpd -q -g ${ntpFlags}
end script
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
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
"postgresql"
else
@ -10,26 +39,35 @@ let
else
"network-interfaces";
in
with pkgs;
{
name = "openfire";
job = ''
description "OpenFire XMPP server"
start on ${startDependency}/started
stop on shutdown
mkIf config.services.openfire.enable {
require = [
options
];
script
export PATH=${jre}/bin:${openfire}/bin:${coreutils}/bin:${which}/bin:${gnugrep}/bin:${gawk}/bin:${gnused}/bin
export HOME=/tmp
mkdir /var/log/openfire || true
mkdir /etc/openfire || true
for i in ${openfire}/conf.inst/*; do
if ! test -f /etc/openfire/$(basename $i); then
cp $i /etc/openfire/
fi
done
openfire start
end script
'';
services = {
extraJobs = [{
name = "openfire";
job = ''
description "OpenFire XMPP server"
start on ${startDependency}/started
stop on shutdown
script
export PATH=${jre}/bin:${openfire}/bin:${coreutils}/bin:${which}/bin:${gnugrep}/bin:${gawk}/bin:${gnused}/bin
export HOME=/tmp
mkdir /var/log/openfire || true
mkdir /etc/openfire || true
for i in ${openfire}/conf.inst/*; do
if ! test -f /etc/openfire/$(basename $i); then
cp $i /etc/openfire/
fi
done
openfire start
end script
'';
}];
};
}

View file

@ -1,35 +1,70 @@
{ 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;
gid = (import ../system/ids.nix).gids.portmap;
in
{
name = "portmap";
users = [
{ name = "portmap";
inherit uid;
description = "portmap daemon user";
home = "/var/empty";
}
mkIf config.services.portmap.enable {
require = [
options
];
groups = [
{ name = "portmap";
inherit gid;
}
];
job =
let portmap = makePortmap { daemonUID = uid; daemonGID = gid; };
in
''
description "ONC RPC portmap"
users = {
extraUsers = [
{ name = "portmap";
inherit uid;
description = "portmap daemon user";
home = "/var/empty";
}
];
start on network-interfaces/started
stop on network-interfaces/stop
extraGroups = [
{ name = "portmap";
inherit gid;
}
];
};
respawn ${portmap}/sbin/portmap
'';
services = {
extraJobs = [{
name = "portmap";
job =
let portmap = pkgs.makePortmap { daemonUID = uid; daemonGID = gid; };
in
''
description "ONC RPC portmap"
start on network-interfaces/started
stop on network-interfaces/stop
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
startingDependency = if config.services.gw6c.enable then "gw6c" else "network-interfaces";
@ -103,62 +253,76 @@ let
mainCfFile = pkgs.writeText "postfix-main.cf" mainCf;
in
{
name = "postfix";
users = [
{ name = user;
description = "Postfix mail server user";
uid = idList.uids.postfix;
group = group;
}
mkIf config.services.postfix.enable {
require = [
options
];
groups = [
{ name = group;
gid = idList.gids.postfix;
}
{ name = setgidGroup;
gid = idList.gids.postdrop;
}
];
# I copy _lots_ of shipped configuration filed
# that can be left as is. I am afraid the exact
# will list slightly change in next Postfix
# release, so listing them all one-by-one in an
# accurate way is unlikely to be better.
job = ''
description "Postfix mail server job"
start on ${startingDependency}/started
stop on never
script
if ! [ -d /var/spool/postfix ]; then
${pkgs.coreutils}/bin/mkdir -p /var/spool/mail /var/postfix/conf /var/postfix/queue
fi
${pkgs.coreutils}/bin/chown -R ${user}.${group} /var/postfix
${pkgs.coreutils}/bin/chown -R ${user}.${setgidGroup} /var/postfix/queue
${pkgs.coreutils}/bin/chmod -R ug+rwX /var/postfix/queue
${pkgs.coreutils}/bin/chown root.root /var/spool/mail
${pkgs.coreutils}/bin/chmod a+rwxt /var/spool/mail
ln -sf ${pkgs.postfix}/share/postfix/conf/* /var/postfix/conf
ln -sf ${aliasesFile} /var/postfix/conf/aliases
ln -sf ${mainCfFile} /var/postfix/conf/main.cf
${pkgs.postfix}/sbin/postalias -c /var/postfix/conf /var/postfix/conf/aliases
${pkgs.postfix}/sbin/postfix -c /var/postfix/conf start
end script
'';
extraEtc = [
{ source = "/var/postfix/conf";
environment = {
etc = [{
source = "/var/postfix/conf";
target = "postfix";
}
];
}];
};
users = {
extraUsers = [
{ name = user;
description = "Postfix mail server user";
uid = idList.uids.postfix;
group = group;
}
];
extraGroups = [
{ name = group;
gid = idList.gids.postfix;
}
{ name = setgidGroup;
gid = idList.gids.postdrop;
}
];
};
services = {
extraJobs = [{
name = "postfix";
# I copy _lots_ of shipped configuration filed
# that can be left as is. I am afraid the exact
# will list slightly change in next Postfix
# release, so listing them all one-by-one in an
# accurate way is unlikely to be better.
job = ''
description "Postfix mail server job"
start on ${startingDependency}/started
stop on never
script
if ! [ -d /var/spool/postfix ]; then
${pkgs.coreutils}/bin/mkdir -p /var/spool/mail /var/postfix/conf /var/postfix/queue
fi
${pkgs.coreutils}/bin/chown -R ${user}.${group} /var/postfix
${pkgs.coreutils}/bin/chown -R ${user}.${setgidGroup} /var/postfix/queue
${pkgs.coreutils}/bin/chmod -R ug+rwX /var/postfix/queue
${pkgs.coreutils}/bin/chown root.root /var/spool/mail
${pkgs.coreutils}/bin/chmod a+rwxt /var/spool/mail
ln -sf ${pkgs.postfix}/share/postfix/conf/* /var/postfix/conf
ln -sf ${aliasesFile} /var/postfix/conf/aliases
ln -sf ${mainCfFile} /var/postfix/conf/main.cf
${pkgs.postfix}/sbin/postalias -c /var/postfix/conf /var/postfix/conf/aliases
${pkgs.postfix}/sbin/postfix -c /var/postfix/conf start
end script
'';
}];
};
}

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
@ -13,36 +81,47 @@ let
in
{
name = "postgresql";
users = [
{ name = "postgres";
description = "PostgreSQL server user";
}
mkIf config.services.postgresql.enable {
require = [
options
];
groups = [
{ name = "postgres"; }
];
extraPath = [postgresql];
users = {
extraUsers = [
{ name = "postgres";
description = "PostgreSQL server user";
}
];
job = ''
description "PostgreSQL server"
extraGroups = [
{ name = "postgres"; }
];
};
start on ${startDependency}/started
stop on shutdown
start script
if ! test -e ${cfg.dataDir}; then
mkdir -m 0700 -p ${cfg.dataDir}
chown -R postgres ${cfg.dataDir}
${run} -c '${postgresql}/bin/initdb -D ${cfg.dataDir} -U root'
fi
cp -f ${pkgs.writeText "pg_hba.conf" cfg.authentication} ${cfg.dataDir}/pg_hba.conf
end script
services = {
extraJobs = [{
name = "postgresql";
respawn ${run} -c '${postgresql}/bin/postgres -D ${cfg.dataDir}'
'';
extraPath = [postgresql];
job = ''
description "PostgreSQL server"
start on ${startDependency}/started
stop on shutdown
start script
if ! test -e ${cfg.dataDir}; then
mkdir -m 0700 -p ${cfg.dataDir}
chown -R postgres ${cfg.dataDir}
${run} -c '${postgresql}/bin/initdb -D ${cfg.dataDir} -U root'
fi
cp -f ${pkgs.writeText "pg_hba.conf" cfg.authentication} ${cfg.dataDir}/pg_hba.conf
end script
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
@ -7,52 +29,65 @@ let
smbConfig = ./smb.conf ;
inherit (pkgs) samba;
in
{
name = "samba";
users = [
{ name = user;
description = "Samba service user";
group = group;
}
];
groups = [
{ name = group;
}
mkIf config.services.samba.enable {
require = [
options
];
job = "
description \"Samba Service\"
users = {
extraUsers = [
{ name = user;
description = "Samba service user";
group = group;
}
];
extraGroups = [
{ name = group;
}
];
};
start on network-interfaces/started
stop on network-interfaces/stop
services = {
extraJobs = [{
name = "samba";
job = ''
start script
description "Samba Service"
if ! test -d /home/smbd ; then
mkdir -p /home/smbd
chown ${user} /home/smbd
chmod a+rwx /home/smbd
fi
start on network-interfaces/started
stop on network-interfaces/stop
if ! test -d /var/samba ; then
mkdir -p /var/samba/locks /var/samba/cores/nmbd /var/samba/cores/smbd /var/samba/cores/winbindd
fi
start script
${samba}/sbin/nmbd -D -s ${smbConfig} &
${samba}/sbin/smbd -D -s ${smbConfig} &
${samba}/sbin/winbindd -B -s ${smbConfig} &
if ! test -d /home/smbd ; then
mkdir -p /home/smbd
chown ${user} /home/smbd
chmod a+rwx /home/smbd
fi
ln -fs ${smbConfig} /var/samba/config
if ! test -d /var/samba ; then
mkdir -p /var/samba/locks /var/samba/cores/nmbd /var/samba/cores/smbd /var/samba/cores/winbindd
fi
end script
${samba}/sbin/nmbd -D -s ${smbConfig} &
${samba}/sbin/smbd -D -s ${smbConfig} &
${samba}/sbin/winbindd -B -s ${smbConfig} &
respawn ${samba}/sbin/nmbd -D -s ${smbConfig} &; ${samba}/sbin/smbd -D -s ${smbConfig} &; ${samba}/sbin/winbindd -B &
ln -fs ${smbConfig} /var/samba/config
";
end script
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
, nssModulesPath
, forwardX11, allowSFTP, permitRootLogin, gatewayPorts
}:
{pkgs, config, ...}:
assert permitRootLogin == "yes" ||
permitRootLogin == "without-password" ||
permitRootLogin == "forced-commands-only" ||
permitRootLogin == "no";
###### interface
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" ''
@ -16,55 +68,70 @@ let
UsePAM yes
${if forwardX11 then "
${if cfg.forwardX11 then "
X11Forwarding yes
XAuthLocation ${xauth}/bin/xauth
XAuthLocation ${pkgs.xlibs.xauth}/bin/xauth
" else "
X11Forwarding no
"}
${if allowSFTP then "
${if cfg.allowSFTP then "
Subsystem sftp ${openssh}/libexec/sftp-server
" else "
"}
PermitRootLogin ${permitRootLogin}
GatewayPorts ${gatewayPorts}
PermitRootLogin ${cfg.permitRootLogin}
GatewayPorts ${cfg.gatewayPorts}
'';
sshdUid = (import ../system/ids.nix).uids.sshd;
assertion = cfg.permitRootLogin == "yes" ||
cfg.permitRootLogin == "without-password" ||
cfg.permitRootLogin == "forced-commands-only" ||
cfg.permitRootLogin == "no";
in
{
name = "sshd";
users = [
{ name = "sshd";
uid = (import ../system/ids.nix).uids.sshd;
description = "SSH privilege separation user";
home = "/var/empty";
}
mkIf config.services.sshd.enable {
require = [
options
];
job = ''
description "SSH server"
start on network-interfaces/started
stop on network-interfaces/stop
users = {
extraUsers = [
{ name = "sshd";
uid = (import ../system/ids.nix).uids.sshd;
description = "SSH privilege separation user";
home = "/var/empty";
}
];
};
env LD_LIBRARY_PATH=${nssModulesPath}
services = {
extraJobs = [{
name = "sshd";
start script
mkdir -m 0755 -p /etc/ssh
job = ''
description "SSH server"
if ! test -f /etc/ssh/ssh_host_dsa_key; then
${openssh}/bin/ssh-keygen -t dsa -b 1024 -f /etc/ssh/ssh_host_dsa_key -N ""
fi
end script
start on network-interfaces/started
stop on network-interfaces/stop
respawn ${openssh}/sbin/sshd -D -h /etc/ssh/ssh_host_dsa_key -f ${sshdConfig}
'';
env LD_LIBRARY_PATH=${nssModulesPath}
start script
mkdir -m 0755 -p /etc/ssh
if ! test -f /etc/ssh/ssh_host_dsa_key; then
${openssh}/bin/ssh-keygen -t dsa -b 1024 -f /etc/ssh/ssh_host_dsa_key -N ""
fi
end script
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
inherit (pkgs) utillinux lib;
swapDevices = config.swapDevices;
devicesByPath =
map (x: x.device) (lib.filter (x: x ? device) swapDevices);
@ -10,35 +16,39 @@ let
in
{
name = "swap";
job = "
start on startup
start on new-devices
script
for device in ${toString devicesByPath}; do
${utillinux}/sbin/swapon \"$device\" || true
done
for label in ${toString devicesByLabel}; do
${utillinux}/sbin/swapon -L \"$label\" || true
done
# Remove swap devices not listed in swapDevices.
# !!! disabled because it doesn't work with labels
#for used in $(cat /proc/swaps | grep '^/' | sed 's/ .*//'); do
# found=
# for device in $ {toString swapDevices}; do
# if test \"$used\" = \"$device\"; then found=1; fi
# done
# if test -z \"$found\"; then
# ${utillinux}/sbin/swapoff \"$used\" || true
# fi
#done
end script
";
services = {
extraJobs = [{
name = "swap";
job = "
start on startup
start on new-devices
script
for device in ${toString devicesByPath}; do
${utillinux}/sbin/swapon \"$device\" || true
done
for label in ${toString devicesByLabel}; do
${utillinux}/sbin/swapon -L \"$label\" || true
done
# Remove swap devices not listed in swapDevices.
# !!! disabled because it doesn't work with labels
#for used in $(cat /proc/swaps | grep '^/' | sed 's/ .*//'); do
# found=
# for device in $ {toString swapDevices}; do
# if test \"$used\" = \"$device\"; then found=1; fi
# done
# if test -z \"$found\"; then
# ${utillinux}/sbin/swapoff \"$used\" || true
# fi
#done
end script
";
}];
};
}

View file

@ -1,36 +1,44 @@
{modprobe, mdadm}:
{pkgs, config, ...}:
###### implementation
let
tempConf = "/var/run/mdadm.conf";
modprobe = config.system.sbin.modprobe;
inherit (pkgs) mdadm;
in
{
name = "swraid";
job = "
start on udev
#start on new-devices
script
# Load the necessary RAID personalities.
# !!! hm, doesn't the kernel load these automatically?
for mod in raid0 raid1 raid5; do
${modprobe}/sbin/modprobe $mod || true
done
# Scan /proc/partitions for RAID devices.
${mdadm}/sbin/mdadm --examine --brief --scan -c partitions > ${tempConf}
# Activate each device found.
${mdadm}/sbin/mdadm --assemble -c ${tempConf} --scan
initctl emit new-devices
end script
";
services = {
extraJobs = [{
name = "swraid";
job = ''
start on udev
#start on new-devices
script
# Load the necessary RAID personalities.
# !!! hm, doesn't the kernel load these automatically?
for mod in raid0 raid1 raid5; do
${modprobe}/sbin/modprobe $mod || true
done
# Scan /proc/partitions for RAID devices.
${mdadm}/sbin/mdadm --examine --brief --scan -c partitions > ${tempConf}
# Activate each device found.
${mdadm}/sbin/mdadm --assemble -c ${tempConf} --scan
initctl emit new-devices
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
syslogConf = writeText "syslog.conf" ''
syslogConf = pkgs.writeText "syslog.conf" ''
kern.warning;*.err;authpriv.none /dev/tty10
# Send emergency messages to all users.
@ -22,16 +46,24 @@ let
in
{
name = "syslogd";
job = ''
description "Syslog daemon"
start on udev
stop on shutdown
require = [
options
];
env TZ=${config.time.timeZone}
respawn ${sysklogd}/sbin/syslogd -n -f ${syslogConf}
'';
services = {
extraJobs = [{
name = "syslogd";
job = ''
description "Syslog daemon"
start on udev
stop on shutdown
env TZ=${config.time.timeZone}
respawn ${pkgs.sysklogd}/sbin/syslogd -n -f ${syslogConf}
'';
}];
};
}

View file

@ -1,109 +1,175 @@
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
cfg = config.services.tomcat;
in
{
name = "tomcat";
groups = [
{ name = "tomcat";
gid = (import ../system/ids.nix).gids.tomcat;
}
mkIf config.services.tomcat.enable {
require = [
options
];
users = [
{ name = "tomcat";
uid = (import ../system/ids.nix).uids.tomcat;
description = "Tomcat user";
home = "/homeless-shelter";
}
];
job = ''
description "Apache Tomcat server"
start on network-interface/started
stop on network-interfaces/stop
start script
# Create initial state data
services = {
extraJobs = [{
name = "tomcat";
groups = [
{ name = "tomcat";
gid = (import ../system/ids.nix).gids.tomcat;
}
];
users = [
{ name = "tomcat";
uid = (import ../system/ids.nix).uids.tomcat;
description = "Tomcat user";
home = "/homeless-shelter";
}
];
job = ''
description "Apache Tomcat server"
start on network-interface/started
stop on network-interfaces/stop
if ! test -d ${cfg.baseDir}
then
mkdir -p ${cfg.baseDir}/webapps
mkdir -p ${cfg.baseDir}/shared
mkdir -p ${cfg.baseDir}/lib
cp -av ${pkgs.tomcat6}/{conf,temp,logs} ${cfg.baseDir}
fi
# Deploy context.xml
if test "${cfg.contextXML}" = ""
then
cp ${pkgs.tomcat6}/conf/context.xml.default ${cfg.baseDir}/conf/context.xml
else
cp ${cfg.contextXML} ${cfg.baseDir}/conf/context.xml
fi
# Deploy all webapplications
if ! test "${cfg.deployFrom}" = ""
then
rm -rf ${cfg.baseDir}/webapps
mkdir -p ${cfg.baseDir}/webapps
for i in ${cfg.deployFrom}/*
start script
# Create initial state data
if ! test -d ${cfg.baseDir}
then
mkdir -p ${cfg.baseDir}/webapps
mkdir -p ${cfg.baseDir}/shared
mkdir -p ${cfg.baseDir}/lib
cp -av ${pkgs.tomcat6}/{conf,temp,logs} ${cfg.baseDir}
fi
# Deploy context.xml
if test "${cfg.contextXML}" = ""
then
cp ${pkgs.tomcat6}/conf/context.xml.default ${cfg.baseDir}/conf/context.xml
else
cp ${cfg.contextXML} ${cfg.baseDir}/conf/context.xml
fi
# Deploy all webapplications
if ! test "${cfg.deployFrom}" = ""
then
rm -rf ${cfg.baseDir}/webapps
mkdir -p ${cfg.baseDir}/webapps
for i in ${cfg.deployFrom}/*
do
cp -rL $i ${cfg.baseDir}/webapps
done
fi
# Fix permissions
chown -R ${cfg.user} ${cfg.baseDir}
for i in `find ${cfg.baseDir} -type d`
do
cp -rL $i ${cfg.baseDir}/webapps
chmod -v 755 $i
done
for i in `find ${cfg.baseDir} -type f`
do
chmod -v 644 $i
done
fi
# Fix permissions
chown -R ${cfg.user} ${cfg.baseDir}
for i in `find ${cfg.baseDir} -type d`
do
chmod -v 755 $i
done
for i in `find ${cfg.baseDir} -type f`
do
chmod -v 644 $i
done
# Deploy all common libraries
rm -rf ${cfg.baseDir}/lib/*
if test "${cfg.commonLibFrom}" = ""
then
commonLibFrom="${pkgs.tomcat6}/lib";
else
commonLibFrom="${cfg.commonLibFrom}";
fi
for i in $commonLibFrom/*.jar
do
ln -s $i ${cfg.baseDir}/lib
done
# Deploy all common libraries
rm -rf ${cfg.baseDir}/lib/*
if test "${cfg.commonLibFrom}" = ""
then
commonLibFrom="${pkgs.tomcat6}/lib";
else
commonLibFrom="${cfg.commonLibFrom}";
fi
for i in $commonLibFrom/*.jar
do
ln -s $i ${cfg.baseDir}/lib
done
# Deploy all shared libraries
# Deploy all shared libraries
if ! test "${cfg.sharedLibFrom}" = ""
then
rm -f ${cfg.baseDir}/shared/lib
ln -s ${cfg.sharedLibFrom} ${cfg.baseDir}/shared/lib
fi
end script
if ! test "${cfg.sharedLibFrom}" = ""
then
rm -f ${cfg.baseDir}/shared/lib
ln -s ${cfg.sharedLibFrom} ${cfg.baseDir}/shared/lib
fi
end script
respawn ${pkgs.su}/bin/su -s ${pkgs.bash}/bin/sh ${cfg.user} -c 'CATALINA_BASE=${cfg.baseDir} JAVA_HOME=${pkgs.jdk} JAVA_OPTS="${cfg.javaOpts}" CATALINA_OPTS="${cfg.catalinaOpts}" ${pkgs.tomcat6}/bin/startup.sh; sleep 1000d'
stop script
echo "Stopping tomcat..."
CATALINA_BASE=${cfg.baseDir} JAVA_HOME=${pkgs.jdk} ${pkgs.su}/bin/su -s ${pkgs.bash}/bin/sh ${cfg.user} -c ${pkgs.tomcat6}/bin/shutdown.sh
end script
'';
respawn ${pkgs.su}/bin/su -s ${pkgs.bash}/bin/sh ${cfg.user} -c 'CATALINA_BASE=${cfg.baseDir} JAVA_HOME=${pkgs.jdk} JAVA_OPTS="${cfg.javaOpts}" CATALINA_OPTS="${cfg.catalinaOpts}" ${pkgs.tomcat6}/bin/startup.sh; sleep 1000d'
stop script
echo "Stopping tomcat..."
CATALINA_BASE=${cfg.baseDir} JAVA_HOME=${pkgs.jdk} ${pkgs.su}/bin/su -s ${pkgs.bash}/bin/sh ${cfg.user} -c ${pkgs.tomcat6}/bin/shutdown.sh
end script
'';
}];
};
}

View file

@ -1,11 +1,100 @@
{stdenv, splashutils, backgrounds}:
{pkgs, config, ...}:
rec {
name = "tty-backgrounds";
###### interface
let
inherit (pkgs.lib) mkOption mkIf;
unpackTheme = theme: import ../helpers/unpack-theme.nix {
inherit stdenv theme;
options = {
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 {
name = "splash-themes";
@ -15,46 +104,71 @@ rec {
themes = map (x: if x ? theme then (unpackTheme x.theme) else "default") backgrounds;
};
extraEtc = [
{ source = themesUnpacked;
target = "splash";
}
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
];
job = ''
start on udev
start script
environment = {
etc = [
{ source = themesUnpacked;
target = "splash";
}
];
};
# Critical: tell the kernel where to find splash_helper. It calls
# this program every time we switch between consoles.
helperProcFile=${splashutils.helperProcFile}
if test -e /proc/sys/fbcondecor; then helperProcFile=/proc/sys/fbcondecor; fi
echo ${splashutils}/${splashutils.helperName} > $helperProcFile
# For each console...
for tty in ${toString (map (x: x.tty) backgrounds)}; do
# Make sure that the console exists.
echo -n "" > /dev/tty$tty
services = {
extraJobs = [ rec {
name = "tty-backgrounds";
# Set the theme as determined by tty-backgrounds-combine.sh
# above.
theme=$(readlink ${themesUnpacked}/$tty)
${splashutils}/${splashutils.controlName} --tty $tty -c setcfg -t $theme || true
${splashutils}/${splashutils.controlName} --tty $tty -c setpic -t $theme || true
${splashutils}/${splashutils.controlName} --tty $tty -c on || true
done
job = ''
start on udev
end script
start script
respawn sleep 10000 # !!! Hack
# Critical: tell the kernel where to find splash_helper. It calls
# this program every time we switch between consoles.
helperProcFile=${splashutils.helperProcFile}
if test -e /proc/sys/fbcondecor; then helperProcFile=/proc/sys/fbcondecor; fi
echo ${splashutils}/${splashutils.helperName} > $helperProcFile
stop script
# Disable the theme on each console.
for tty in ${toString (map (x: x.tty) backgrounds)}; do
${splashutils}/${splashutils.controlName} --tty $tty -c off || true
done
end script
'';
# For each console...
for tty in ${toString (map (x: x.tty) backgrounds)}; do
# Make sure that the console exists.
echo -n "" > /dev/tty$tty
# Set the theme as determined by tty-backgrounds-combine.sh
# above.
theme=$(readlink ${themesUnpacked}/$tty)
${splashutils}/${splashutils.controlName} --tty $tty -c setcfg -t $theme || true
${splashutils}/${splashutils.controlName} --tty $tty -c setpic -t $theme || true
${splashutils}/${splashutils.controlName} --tty $tty -c on || true
done
end script
respawn sleep 10000 # !!! Hack
stop script
# Disable the theme on each console.
for tty in ${toString (map (x: x.tty) backgrounds)}; do
${splashutils}/${splashutils.controlName} --tty $tty -c off || true
done
end script
'';
}];
};
}

View file

@ -1,18 +1,66 @@
{ stdenv, writeText, substituteAll, cleanSource, udev, procps, firmwareDirs, modprobe
, extraUdevPkgs ? []
, config
}:
{pkgs, 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
inherit (pkgs) substituteAll stdenv writeText udev procps;
cfg = config.services.udev;
firmwareLoader = substituteAll {
src = ./udev-firmware-loader.sh;
path = "${stdenv.coreutils}/bin";
isExecutable = true;
inherit firmwareDirs;
};
firmwareDirs = config.services.udev.addFirmware;
extraUdevPkgs = config.services.udev.addUdevPkgs;
modprobe = config.system.sbin.modprobe;
nixRules = writeText "90-nix.rules" ''
@ -86,55 +134,64 @@ let
in
{
name = "udev";
job = ''
start on startup
stop on shutdown
env UDEV_CONFIG_FILE=${conf}
require = [
options
];
start script
echo "" > /proc/sys/kernel/hotplug
services = {
extraJobs = [{
name = "udev";
job = ''
start on startup
stop on shutdown
# Get rid of possible old udev processes.
${procps}/bin/pkill -u root "^udevd$" || true
env UDEV_CONFIG_FILE=${conf}
# Do the loading of additional stage 2 kernel modules.
# Maybe this isn't the best place...
for i in ${toString config.boot.kernelModules}; do
echo "Loading kernel module $i..."
${modprobe}/sbin/modprobe $i || true
done
start script
echo "" > /proc/sys/kernel/hotplug
# Start udev.
${udev}/sbin/udevd --daemon
# Get rid of possible old udev processes.
${procps}/bin/pkill -u root "^udevd$" || true
# Let udev create device nodes for all modules that have already
# been loaded into the kernel (or for which support is built into
# the kernel).
if ! test -e ${devicesCreated}; then
${udev}/sbin/udevadm trigger
${udev}/sbin/udevadm settle # wait for udev to finish
touch ${devicesCreated}
fi
# Do the loading of additional stage 2 kernel modules.
# Maybe this isn't the best place...
for i in ${toString config.boot.kernelModules}; do
echo "Loading kernel module $i..."
${modprobe}/sbin/modprobe $i || true
done
# Kill udev, let Upstart restart and monitor it. (This is nasty,
# but we have to run `udevadm trigger' first. Maybe we can use
# Upstart's `binary' keyword, but it isn't implemented yet.)
if ! ${procps}/bin/pkill -u root "^udevd$"; then
echo "couldn't stop udevd"
fi
# Start udev.
${udev}/sbin/udevd --daemon
while ${procps}/bin/pgrep -u root "^udevd$"; do
sleep 1
done
# Let udev create device nodes for all modules that have already
# been loaded into the kernel (or for which support is built into
# the kernel).
if ! test -e ${devicesCreated}; then
${udev}/sbin/udevadm trigger
${udev}/sbin/udevadm settle # wait for udev to finish
touch ${devicesCreated}
fi
initctl emit new-devices
end script
# Kill udev, let Upstart restart and monitor it. (This is nasty,
# but we have to run `udevadm trigger' first. Maybe we can use
# Upstart's `binary' keyword, but it isn't implemented yet.)
if ! ${procps}/bin/pkill -u root "^udevd$"; then
echo "couldn't stop udevd"
fi
respawn ${udev}/sbin/udevd
'';
while ${procps}/bin/pgrep -u root "^udevd$"; do
sleep 1
done
passthru = {inherit udevRules;};
initctl emit new-devices
end script
respawn ${udev}/sbin/udevd
'';
passthru = {inherit udevRules;};
}];
};
}

View file

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

View file

@ -1,20 +1,54 @@
{
pkgs, config
}:
if ! config.fonts.enableFontDir then abort "Please enable fontDir (fonts.enableFontDir) to use xfs." else
{pkgs, config, ...}:
###### interface
let
configFile = ./xfs.conf;
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
configFile = ./xfs.conf;
startingDependency = if config.services.gw6c.enable && config.services.gw6c.autorun then "gw6c" else "network-interfaces";
in
rec {
name = "xfs";
groups = [];
users = [];
job = "
description \"X Font Server\"
start on ${startingDependency}/started
stop on shutdown
respawn ${pkgs.xorg.xfs}/bin/xfs -config ${configFile}
";
mkIf config.services.xfs.enable {
require = [
options
];
services = {
extraJobs = [ (rec {
name = "xfs";
groups = [];
users = [];
job = ''
description "X Font Server"
start on ${startingDependency}/started
stop on shutdown
respawn ${pkgs.xorg.xfs}/bin/xfs -config ${configFile}
'';
})];
};
}

View file

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