about summary refs log tree commit diff
path: root/nixpkgs/nixos/modules/services/system
diff options
context:
space:
mode:
Diffstat (limited to 'nixpkgs/nixos/modules/services/system')
-rw-r--r--nixpkgs/nixos/modules/services/system/cgmanager.nix27
-rw-r--r--nixpkgs/nixos/modules/services/system/cloud-init.nix182
-rw-r--r--nixpkgs/nixos/modules/services/system/dbus.nix117
-rw-r--r--nixpkgs/nixos/modules/services/system/earlyoom.nix96
-rw-r--r--nixpkgs/nixos/modules/services/system/kerberos/default.nix80
-rw-r--r--nixpkgs/nixos/modules/services/system/kerberos/heimdal.nix68
-rw-r--r--nixpkgs/nixos/modules/services/system/kerberos/mit.nix68
-rw-r--r--nixpkgs/nixos/modules/services/system/localtime.nix54
-rw-r--r--nixpkgs/nixos/modules/services/system/nscd.conf52
-rw-r--r--nixpkgs/nixos/modules/services/system/nscd.nix90
-rw-r--r--nixpkgs/nixos/modules/services/system/saslauthd.nix62
-rw-r--r--nixpkgs/nixos/modules/services/system/uptimed.nix55
12 files changed, 951 insertions, 0 deletions
diff --git a/nixpkgs/nixos/modules/services/system/cgmanager.nix b/nixpkgs/nixos/modules/services/system/cgmanager.nix
new file mode 100644
index 000000000000..59d3deced867
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/system/cgmanager.nix
@@ -0,0 +1,27 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.services.cgmanager;
+in {
+  meta.maintainers = [ maintainers.mic92 ];
+
+  ###### interface
+  options.services.cgmanager.enable = mkEnableOption "cgmanager";
+
+  ###### implementation
+  config = mkIf cfg.enable {
+    systemd.services.cgmanager = {
+      wantedBy = [ "multi-user.target" ];
+      after = [ "local-fs.target" ];
+      description = "Cgroup management daemon";
+      restartIfChanged = false;
+      serviceConfig = {
+        ExecStart = "${pkgs.cgmanager}/bin/cgmanager -m name=systemd";
+        KillMode = "process";
+        Restart = "on-failure";
+      };
+    };
+  };
+}
diff --git a/nixpkgs/nixos/modules/services/system/cloud-init.nix b/nixpkgs/nixos/modules/services/system/cloud-init.nix
new file mode 100644
index 000000000000..3ad555f78ef8
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/system/cloud-init.nix
@@ -0,0 +1,182 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let cfg = config.services.cloud-init;
+    path = with pkgs; [
+      cloud-init
+      iproute
+      nettools
+      openssh
+      shadow
+      utillinux
+    ] ++ optional cfg.btrfs.enable btrfs-progs
+      ++ optional cfg.ext4.enable e2fsprogs
+    ;
+in
+{
+  options = {
+    services.cloud-init = {
+      enable = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Enable the cloud-init service. This services reads
+          configuration metadata in a cloud environment and configures
+          the machine according to this metadata.
+
+          This configuration is not completely compatible with the
+          NixOS way of doing configuration, as configuration done by
+          cloud-init might be overriden by a subsequent nixos-rebuild
+          call. However, some parts of cloud-init fall outside of
+          NixOS's responsibility, like filesystem resizing and ssh
+          public key provisioning, and cloud-init is useful for that
+          parts. Thus, be wary that using cloud-init in NixOS might
+          come as some cost.
+        '';
+      };
+
+      btrfs.enable = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Allow the cloud-init service to operate `btrfs` filesystem.
+        '';
+      };
+
+      ext4.enable = mkOption {
+        type = types.bool;
+        default = true;
+        description = ''
+          Allow the cloud-init service to operate `ext4` filesystem.
+        '';
+      };
+
+      config = mkOption {
+        type = types.str;
+        default = ''
+          system_info:
+            distro: nixos
+          users:
+             - root
+
+          disable_root: false
+          preserve_hostname: false
+
+          cloud_init_modules:
+           - migrator
+           - seed_random
+           - bootcmd
+           - write-files
+           - growpart
+           - resizefs
+           - update_etc_hosts
+           - ca-certs
+           - rsyslog
+           - users-groups
+
+          cloud_config_modules:
+           - disk_setup
+           - mounts
+           - ssh-import-id
+           - set-passwords
+           - timezone
+           - disable-ec2-metadata
+           - runcmd
+           - ssh
+
+          cloud_final_modules:
+           - rightscale_userdata
+           - scripts-vendor
+           - scripts-per-once
+           - scripts-per-boot
+           - scripts-per-instance
+           - scripts-user
+           - ssh-authkey-fingerprints
+           - keys-to-console
+           - phone-home
+           - final-message
+           - power-state-change
+          '';
+        description = ''cloud-init configuration.'';
+      };
+
+    };
+
+  };
+
+  config = mkIf cfg.enable {
+
+    environment.etc."cloud/cloud.cfg".text = cfg.config;
+
+    systemd.services.cloud-init-local =
+      { description = "Initial cloud-init job (pre-networking)";
+        wantedBy = [ "multi-user.target" ];
+        wants = [ "local-fs.target" ];
+        after = [ "local-fs.target" ];
+        path = path;
+        serviceConfig =
+          { Type = "oneshot";
+            ExecStart = "${pkgs.cloud-init}/bin/cloud-init init --local";
+            RemainAfterExit = "yes";
+            TimeoutSec = "infinity";
+            StandardOutput = "journal+console";
+          };
+      };
+
+    systemd.services.cloud-init =
+      { description = "Initial cloud-init job (metadata service crawler)";
+        wantedBy = [ "multi-user.target" ];
+        wants = [ "local-fs.target" "network-online.target" "cloud-init-local.service"
+                  "sshd.service" "sshd-keygen.service" ];
+        after = [ "local-fs.target" "network-online.target" "cloud-init-local.service" ];
+        before = [ "sshd.service" "sshd-keygen.service" ];
+        requires = [ "network.target "];
+        path = path;
+        serviceConfig =
+          { Type = "oneshot";
+            ExecStart = "${pkgs.cloud-init}/bin/cloud-init init";
+            RemainAfterExit = "yes";
+            TimeoutSec = "infinity";
+            StandardOutput = "journal+console";
+          };
+      };
+
+    systemd.services.cloud-config =
+      { description = "Apply the settings specified in cloud-config";
+        wantedBy = [ "multi-user.target" ];
+        wants = [ "network-online.target" ];
+        after = [ "network-online.target" "syslog.target" "cloud-config.target" ];
+
+        path = path;
+        serviceConfig =
+          { Type = "oneshot";
+            ExecStart = "${pkgs.cloud-init}/bin/cloud-init modules --mode=config";
+            RemainAfterExit = "yes";
+            TimeoutSec = "infinity";
+            StandardOutput = "journal+console";
+          };
+      };
+
+    systemd.services.cloud-final =
+      { description = "Execute cloud user/final scripts";
+        wantedBy = [ "multi-user.target" ];
+        wants = [ "network-online.target" ];
+        after = [ "network-online.target" "syslog.target" "cloud-config.service" "rc-local.service" ];
+        requires = [ "cloud-config.target" ];
+        path = path;
+        serviceConfig =
+          { Type = "oneshot";
+            ExecStart = "${pkgs.cloud-init}/bin/cloud-init modules --mode=final";
+            RemainAfterExit = "yes";
+            TimeoutSec = "infinity";
+            StandardOutput = "journal+console";
+          };
+      };
+
+    systemd.targets.cloud-config =
+      { description = "Cloud-config availability";
+        requires = [ "cloud-init-local.service" "cloud-init.service" ];
+      };
+  };
+}
diff --git a/nixpkgs/nixos/modules/services/system/dbus.nix b/nixpkgs/nixos/modules/services/system/dbus.nix
new file mode 100644
index 000000000000..e04580218442
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/system/dbus.nix
@@ -0,0 +1,117 @@
+# D-Bus configuration and system bus daemon.
+
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+  cfg = config.services.dbus;
+
+  homeDir = "/run/dbus";
+
+  configDir = pkgs.makeDBusConf {
+    suidHelper = "${config.security.wrapperDir}/dbus-daemon-launch-helper";
+    serviceDirectories = cfg.packages;
+  };
+
+in
+
+{
+
+  ###### interface
+
+  options = {
+
+    services.dbus = {
+
+      enable = mkOption {
+        type = types.bool;
+        default = false;
+        internal = true;
+        description = ''
+          Whether to start the D-Bus message bus daemon, which is
+          required by many other system services and applications.
+        '';
+      };
+
+      packages = mkOption {
+        type = types.listOf types.path;
+        default = [ ];
+        description = ''
+          Packages whose D-Bus configuration files should be included in
+          the configuration of the D-Bus system-wide or session-wide
+          message bus.  Specifically, files in the following directories
+          will be included into their respective DBus configuration paths:
+          <filename><replaceable>pkg</replaceable>/etc/dbus-1/system.d</filename>
+          <filename><replaceable>pkg</replaceable>/share/dbus-1/system-services</filename>
+          <filename><replaceable>pkg</replaceable>/etc/dbus-1/session.d</filename>
+          <filename><replaceable>pkg</replaceable>/share/dbus-1/services</filename>
+        '';
+      };
+
+      socketActivated = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Make the user instance socket activated.
+        '';
+      };
+    };
+  };
+
+  ###### implementation
+
+  config = mkIf cfg.enable {
+
+    environment.systemPackages = [ pkgs.dbus.daemon pkgs.dbus ];
+
+    environment.etc = singleton
+      { source = configDir;
+        target = "dbus-1";
+      };
+
+    users.users.messagebus = {
+      uid = config.ids.uids.messagebus;
+      description = "D-Bus system message bus daemon user";
+      home = homeDir;
+      group = "messagebus";
+    };
+
+    users.groups.messagebus.gid = config.ids.gids.messagebus;
+
+    systemd.packages = [ pkgs.dbus.daemon ];
+
+    security.wrappers.dbus-daemon-launch-helper = {
+      source = "${pkgs.dbus.daemon}/libexec/dbus-daemon-launch-helper";
+      owner = "root";
+      group = "messagebus";
+      setuid = true;
+      setgid = false;
+      permissions = "u+rx,g+rx,o-rx";
+    };
+
+    services.dbus.packages = [
+      pkgs.dbus.out
+      config.system.path
+    ];
+
+    systemd.services.dbus = {
+      # Don't restart dbus-daemon. Bad things tend to happen if we do.
+      reloadIfChanged = true;
+      restartTriggers = [ configDir ];
+      environment = { LD_LIBRARY_PATH = config.system.nssModules.path; };
+    };
+
+    systemd.user = {
+      services.dbus = {
+        # Don't restart dbus-daemon. Bad things tend to happen if we do.
+        reloadIfChanged = true;
+        restartTriggers = [ configDir ];
+      };
+      sockets.dbus.wantedBy = mkIf cfg.socketActivated [ "sockets.target" ];
+    };
+
+    environment.pathsToLink = [ "/etc/dbus-1" "/share/dbus-1" ];
+  };
+}
diff --git a/nixpkgs/nixos/modules/services/system/earlyoom.nix b/nixpkgs/nixos/modules/services/system/earlyoom.nix
new file mode 100644
index 000000000000..daa46838bfa8
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/system/earlyoom.nix
@@ -0,0 +1,96 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  ecfg = config.services.earlyoom;
+in
+{
+  options = {
+    services.earlyoom = {
+
+      enable = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Enable early out of memory killing.
+        '';
+      };
+
+      freeMemThreshold = mkOption {
+        type = types.int;
+        default = 10;
+        description = ''
+          Minimum of availabe memory (in percent).
+          If the free memory falls below this threshold and the analog is true for
+          <option>services.earlyoom.freeSwapThreshold</option>
+          the killing begins.
+        '';
+      };
+
+      freeSwapThreshold = mkOption {
+        type = types.int;
+        default = 10;
+        description = ''
+          Minimum of availabe swap space (in percent).
+          If the available swap space falls below this threshold and the analog
+          is true for <option>services.earlyoom.freeMemThreshold</option>
+          the killing begins.
+        '';
+      };
+
+      useKernelOOMKiller= mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Use kernel OOM killer instead of own user-space implementation.
+        '';
+      };
+
+      ignoreOOMScoreAdjust = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Ignore oom_score_adjust values of processes.
+          User-space implementation only.
+        '';
+      };
+
+      enableDebugInfo = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Enable debugging messages.
+        '';
+      };
+    };
+  };
+
+  config = mkIf ecfg.enable {
+    assertions = [
+      { assertion = ecfg.freeMemThreshold > 0 && ecfg.freeMemThreshold <= 100;
+        message = "Needs to be a positive percentage"; }
+      { assertion = ecfg.freeSwapThreshold > 0 && ecfg.freeSwapThreshold <= 100;
+        message = "Needs to be a positive percentage"; }
+      { assertion = !ecfg.useKernelOOMKiller || !ecfg.ignoreOOMScoreAdjust;
+        message = "Both options in conjunction do not make sense"; }
+    ];
+
+    systemd.services.earlyoom = {
+      description = "Early OOM Daemon for Linux";
+      wantedBy = [ "multi-user.target" ];
+      serviceConfig = {
+        StandardOutput = "null";
+        StandardError = "syslog";
+        ExecStart = ''
+          ${pkgs.earlyoom}/bin/earlyoom \
+          -m ${toString ecfg.freeMemThreshold} \
+          -s ${toString ecfg.freeSwapThreshold} \
+          ${optionalString ecfg.useKernelOOMKiller "-k"} \
+          ${optionalString ecfg.ignoreOOMScoreAdjust "-i"} \
+          ${optionalString ecfg.enableDebugInfo "-d"}
+        '';
+      };
+    };
+  };
+}
diff --git a/nixpkgs/nixos/modules/services/system/kerberos/default.nix b/nixpkgs/nixos/modules/services/system/kerberos/default.nix
new file mode 100644
index 000000000000..26ac85de402f
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/system/kerberos/default.nix
@@ -0,0 +1,80 @@
+{pkgs, config, lib, ...}:
+
+let
+  inherit (lib) mkOption mkIf types length attrNames;
+  cfg = config.services.kerberos_server;
+  kerberos = config.krb5.kerberos;
+
+  aclEntry = {
+    options = {
+      principal = mkOption {
+        type = types.str;
+        description = "Which principal the rule applies to";
+      };
+      access = mkOption {
+        type = types.either
+          (types.listOf (types.enum ["add" "cpw" "delete" "get" "list" "modify"]))
+          (types.enum ["all"]);
+        default = "all";
+        description = "The changes the principal is allowed to make.";
+      };
+      target = mkOption {
+        type = types.str;
+        default = "*";
+        description = "The principals that 'access' applies to.";
+      };
+    };
+  };
+
+  realm = {
+    options = {
+      acl = mkOption {
+        type = types.listOf (types.submodule aclEntry);
+        default = [
+          { principal = "*/admin"; access = "all"; }
+          { principal = "admin"; access = "all"; }
+        ];
+        description = ''
+          The privileges granted to a user.
+        '';
+      };
+    };
+  };
+in
+
+{
+  imports = [
+    ./mit.nix
+    ./heimdal.nix
+  ];
+
+  ###### interface
+  options = {
+    services.kerberos_server = {
+      enable = mkOption {
+        default = false;
+        description = ''
+          Enable the kerberos authentification server.
+        '';
+      };
+
+      realms = mkOption {
+        type = types.attrsOf (types.submodule realm);
+        description = ''
+          The realm(s) to serve keys for.
+        '';
+      };
+    };
+  };
+
+
+  ###### implementation
+
+  config = mkIf cfg.enable {
+    environment.systemPackages = [ kerberos ];
+    assertions = [{
+      assertion = length (attrNames cfg.realms) <= 1;
+      message = "Only one realm per server is currently supported.";
+    }];
+  };
+}
diff --git a/nixpkgs/nixos/modules/services/system/kerberos/heimdal.nix b/nixpkgs/nixos/modules/services/system/kerberos/heimdal.nix
new file mode 100644
index 000000000000..d0f470f836ed
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/system/kerberos/heimdal.nix
@@ -0,0 +1,68 @@
+{ pkgs, config, lib, ... } :
+
+let
+  inherit (lib) mkIf concatStringsSep concatMapStrings toList mapAttrs
+    mapAttrsToList attrValues;
+  cfg = config.services.kerberos_server;
+  kerberos = config.krb5.kerberos;
+  stateDir = "/var/heimdal";
+  aclFiles = mapAttrs
+    (name: {acl, ...}: pkgs.writeText "${name}.acl" (concatMapStrings ((
+      {principal, access, target, ...} :
+      "${principal}\t${concatStringsSep "," (toList access)}\t${target}\n"
+    )) acl)) cfg.realms;
+
+  kdcConfigs = mapAttrsToList (name: value: ''
+    database = {
+      dbname = ${stateDir}/heimdal
+      acl_file = ${value}
+    }
+  '') aclFiles;
+  kdcConfFile = pkgs.writeText "kdc.conf" ''
+    [kdc]
+    ${concatStringsSep "\n" kdcConfigs}
+  '';
+in
+
+{
+  # No documentation about correct triggers, so guessing at them.
+
+  config = mkIf (cfg.enable && kerberos == pkgs.heimdalFull) {
+    systemd.services.kadmind = {
+      description = "Kerberos Administration Daemon";
+      wantedBy = [ "multi-user.target" ];
+      preStart = ''
+        mkdir -m 0755 -p ${stateDir}
+      '';
+      serviceConfig.ExecStart =
+        "${kerberos}/libexec/heimdal/kadmind --config-file=/etc/heimdal-kdc/kdc.conf";
+      restartTriggers = [ kdcConfFile ];
+    };
+
+    systemd.services.kdc = {
+      description = "Key Distribution Center daemon";
+      wantedBy = [ "multi-user.target" ];
+      preStart = ''
+        mkdir -m 0755 -p ${stateDir}
+      '';
+      serviceConfig.ExecStart =
+        "${kerberos}/libexec/heimdal/kdc --config-file=/etc/heimdal-kdc/kdc.conf";
+      restartTriggers = [ kdcConfFile ];
+    };
+
+    systemd.services.kpasswdd = {
+      description = "Kerberos Password Changing daemon";
+      wantedBy = [ "multi-user.target" ];
+      preStart = ''
+        mkdir -m 0755 -p ${stateDir}
+      '';
+      serviceConfig.ExecStart = "${kerberos}/libexec/heimdal/kpasswdd";
+      restartTriggers = [ kdcConfFile ];
+    };
+
+    environment.etc = {
+      # Can be set via the --config-file option to KDC
+      "heimdal-kdc/kdc.conf".source = kdcConfFile;
+    };
+  };
+}
diff --git a/nixpkgs/nixos/modules/services/system/kerberos/mit.nix b/nixpkgs/nixos/modules/services/system/kerberos/mit.nix
new file mode 100644
index 000000000000..a53d9dd0c6b5
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/system/kerberos/mit.nix
@@ -0,0 +1,68 @@
+{ pkgs, config, lib, ... } :
+
+let
+  inherit (lib) mkIf concatStrings concatStringsSep concatMapStrings toList
+    mapAttrs mapAttrsToList attrValues;
+  cfg = config.services.kerberos_server;
+  kerberos = config.krb5.kerberos;
+  stateDir = "/var/lib/krb5kdc";
+  PIDFile = "/run/kdc.pid";
+  aclMap = {
+    add = "a"; cpw = "c"; delete = "d"; get = "i"; list = "l"; modify = "m";
+    all = "*";
+  };
+  aclFiles = mapAttrs
+    (name: {acl, ...}: (pkgs.writeText "${name}.acl" (concatMapStrings (
+      {principal, access, target, ...} :
+      let access_code = map (a: aclMap.${a}) (toList access); in
+      "${principal} ${concatStrings access_code} ${target}\n"
+    ) acl))) cfg.realms;
+  kdcConfigs = mapAttrsToList (name: value: ''
+    ${name} = {
+      acl_file = ${value}
+    }
+  '') aclFiles;
+  kdcConfFile = pkgs.writeText "kdc.conf" ''
+    [realms]
+    ${concatStringsSep "\n" kdcConfigs}
+  '';
+  env = {
+    # What Debian uses, could possibly link directly to Nix store?
+    KRB5_KDC_PROFILE = "/etc/krb5kdc/kdc.conf";
+  };
+in
+
+{
+  config = mkIf (cfg.enable && kerberos == pkgs.krb5Full) {
+    systemd.services.kadmind = {
+      description = "Kerberos Administration Daemon";
+      wantedBy = [ "multi-user.target" ];
+      preStart = ''
+        mkdir -m 0755 -p ${stateDir}
+      '';
+      serviceConfig.ExecStart = "${kerberos}/bin/kadmind -nofork";
+      restartTriggers = [ kdcConfFile ];
+      environment = env;
+    };
+
+    systemd.services.kdc = {
+      description = "Key Distribution Center daemon";
+      wantedBy = [ "multi-user.target" ];
+      preStart = ''
+        mkdir -m 0755 -p ${stateDir}
+      '';
+      serviceConfig = {
+        Type = "forking";
+        PIDFile = PIDFile;
+        ExecStart = "${kerberos}/bin/krb5kdc -P ${PIDFile}";
+      };
+      restartTriggers = [ kdcConfFile ];
+      environment = env;
+    };
+
+    environment.etc = {
+      "krb5kdc/kdc.conf".source = kdcConfFile;
+    };
+    environment.variables = env;
+  };
+}
diff --git a/nixpkgs/nixos/modules/services/system/localtime.nix b/nixpkgs/nixos/modules/services/system/localtime.nix
new file mode 100644
index 000000000000..c7e897c96448
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/system/localtime.nix
@@ -0,0 +1,54 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.services.localtime;
+in {
+  options = {
+    services.localtime = {
+      enable = mkOption {
+        default = false;
+        description = ''
+          Enable <literal>localtime</literal>, simple daemon for keeping the system
+          timezone up-to-date based on the current location. It uses geoclue2 to
+          determine the current location and systemd-timedated to actually set
+          the timezone.
+        '';
+      };
+    };
+  };
+
+  config = mkIf cfg.enable {
+    services.geoclue2.enable = true;
+
+    # so polkit will pick up the rules
+    environment.systemPackages = [ pkgs.localtime ];
+
+    users.users = [{
+      name = "localtimed";
+      description = "Taskserver user";
+    }];
+
+    systemd.services.localtime = {
+      description = "localtime service";
+      wantedBy = [ "multi-user.target" ];
+      partOf = [ "geoclue.service "];
+
+      serviceConfig = {
+        Restart                 = "on-failure";
+        # TODO: make it work with dbus
+        #DynamicUser             = true;
+        Nice                    = 10;
+        User                    = "localtimed";
+        PrivateTmp              = "yes";
+        PrivateDevices          = true;
+        PrivateNetwork          = "yes";
+        NoNewPrivileges         = "yes";
+        ProtectSystem           = "strict";
+        ProtectHome             = true;
+        ExecStart               = "${pkgs.localtime}/bin/localtimed";
+      };
+    };
+  };
+}
diff --git a/nixpkgs/nixos/modules/services/system/nscd.conf b/nixpkgs/nixos/modules/services/system/nscd.conf
new file mode 100644
index 000000000000..603a5d01acce
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/system/nscd.conf
@@ -0,0 +1,52 @@
+# We basically use nscd as a proxy for forwarding nss requests to appropriate
+# nss modules, as we run nscd with LD_LIBRARY_PATH set to the directory
+# containing all such modules
+# Note that we can not use `enable-cache no` As this will actually cause nscd
+# to just reject the nss requests it receives, which then causes glibc to
+# fallback to trying to handle the request by itself. Which won't work as glibc
+# is not aware of the path in which the nss modules live.  As a workaround, we
+# have `enable-cache yes` with an explicit ttl of 0
+server-user             nscd
+threads                 1
+paranoia                no
+debug-level             0
+
+enable-cache            passwd          yes
+positive-time-to-live   passwd          0
+negative-time-to-live   passwd          0
+suggested-size          passwd          211
+check-files             passwd          yes
+persistent              passwd          no
+shared                  passwd          yes
+
+enable-cache            group           yes
+positive-time-to-live   group           0
+negative-time-to-live   group           0
+suggested-size          group           211
+check-files             group           yes
+persistent              group           no
+shared                  group           yes
+
+enable-cache            netgroup        yes
+positive-time-to-live   netgroup        0
+negative-time-to-live   netgroup        0
+suggested-size          netgroup        211
+check-files             netgroup        yes
+persistent              netgroup        no
+shared                  netgroup        yes
+
+enable-cache            hosts           yes
+positive-time-to-live   hosts           600
+negative-time-to-live   hosts           0
+suggested-size          hosts           211
+check-files             hosts           yes
+persistent              hosts           no
+shared                  hosts           yes
+
+enable-cache            services        yes
+positive-time-to-live   services        0
+negative-time-to-live   services        0
+suggested-size          services        211
+check-files             services        yes
+persistent              services        no
+shared                  services        yes
diff --git a/nixpkgs/nixos/modules/services/system/nscd.nix b/nixpkgs/nixos/modules/services/system/nscd.nix
new file mode 100644
index 000000000000..fd1570d11980
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/system/nscd.nix
@@ -0,0 +1,90 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+  nssModulesPath = config.system.nssModules.path;
+  cfg = config.services.nscd;
+
+in
+
+{
+
+  ###### interface
+
+  options = {
+
+    services.nscd = {
+
+      enable = mkOption {
+        type = types.bool;
+        default = true;
+        description = "Whether to enable the Name Service Cache Daemon.";
+      };
+
+      config = mkOption {
+        type = types.lines;
+        default = builtins.readFile ./nscd.conf;
+        description = "Configuration to use for Name Service Cache Daemon.";
+      };
+
+    };
+
+  };
+
+
+  ###### implementation
+
+  config = mkIf cfg.enable {
+    environment.etc."nscd.conf".text = cfg.config;
+
+    users.users.nscd =
+      { isSystemUser = true;
+        description = "Name service cache daemon user";
+      };
+
+    systemd.services.nscd =
+      { description = "Name Service Cache Daemon";
+
+        wantedBy = [ "nss-lookup.target" "nss-user-lookup.target" ];
+
+        environment = { LD_LIBRARY_PATH = nssModulesPath; };
+
+        preStart =
+          ''
+            mkdir -m 0755 -p /run/nscd
+            rm -f /run/nscd/nscd.pid
+            mkdir -m 0755 -p /var/db/nscd
+          '';
+
+        restartTriggers = [
+          config.environment.etc.hosts.source
+          config.environment.etc."nsswitch.conf".source
+          config.environment.etc."nscd.conf".source
+        ];
+
+        serviceConfig =
+          { ExecStart = "@${pkgs.glibc.bin}/sbin/nscd nscd";
+            Type = "forking";
+            PIDFile = "/run/nscd/nscd.pid";
+            Restart = "always";
+            ExecReload =
+              [ "${pkgs.glibc.bin}/sbin/nscd --invalidate passwd"
+                "${pkgs.glibc.bin}/sbin/nscd --invalidate group"
+                "${pkgs.glibc.bin}/sbin/nscd --invalidate hosts"
+              ];
+          };
+
+        # Urgggggh... Nscd forks before opening its socket and writing
+        # its pid. So wait until it's ready.
+        postStart =
+          ''
+            while ! ${pkgs.glibc.bin}/sbin/nscd -g > /dev/null; do
+              sleep 0.2
+            done
+          '';
+      };
+
+  };
+}
diff --git a/nixpkgs/nixos/modules/services/system/saslauthd.nix b/nixpkgs/nixos/modules/services/system/saslauthd.nix
new file mode 100644
index 000000000000..8fcf4fb91fc4
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/system/saslauthd.nix
@@ -0,0 +1,62 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+  cfg = config.services.saslauthd;
+
+in
+
+{
+
+  ###### interface
+
+  options = {
+
+    services.saslauthd = {
+
+      enable = mkEnableOption "saslauthd, the Cyrus SASL authentication daemon";
+
+      package = mkOption {
+        default = pkgs.cyrus_sasl.bin;
+        defaultText = "pkgs.cyrus_sasl.bin";
+        type = types.package;
+        description = "Cyrus SASL package to use.";
+      };
+
+      mechanism = mkOption {
+        type = types.str;
+        default = "pam";
+        description = "Auth mechanism to use";
+      };
+
+      config = mkOption {
+        type = types.lines;
+        default = "";
+        description = "Configuration to use for Cyrus SASL authentication daemon.";
+      };
+
+    };
+
+  };
+
+
+  ###### implementation
+
+  config = mkIf cfg.enable {
+
+    systemd.services.saslauthd = {
+      description = "Cyrus SASL authentication daemon";
+
+      wantedBy = [ "multi-user.target" ];
+
+      serviceConfig = {
+        ExecStart = "@${cfg.package}/sbin/saslauthd saslauthd -a ${cfg.mechanism} -O ${pkgs.writeText "saslauthd.conf" cfg.config}";
+        Type = "forking";
+        PIDFile = "/run/saslauthd/saslauthd.pid";
+        Restart = "always";
+      };
+    };
+  };
+}
diff --git a/nixpkgs/nixos/modules/services/system/uptimed.nix b/nixpkgs/nixos/modules/services/system/uptimed.nix
new file mode 100644
index 000000000000..3c9978ab2269
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/system/uptimed.nix
@@ -0,0 +1,55 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.services.uptimed;
+  stateDir = "/var/spool/uptimed";
+in
+{
+  options = {
+    services.uptimed = {
+      enable = mkOption {
+        default = false;
+        description = ''
+          Enable <literal>uptimed</literal>, allowing you to track
+          your highest uptimes.
+        '';
+      };
+    };
+  };
+
+  config = mkIf cfg.enable {
+    users.users.uptimed = {
+      description = "Uptimed daemon user";
+      home        = stateDir;
+      createHome  = true;
+      uid         = config.ids.uids.uptimed;
+    };
+
+    systemd.services.uptimed = {
+      unitConfig.Documentation = "man:uptimed(8) man:uprecords(1)";
+      description = "uptimed service";
+      wantedBy    = [ "multi-user.target" ];
+
+      serviceConfig = {
+        Restart                 = "on-failure";
+        User                    = "uptimed";
+        Nice                    = 19;
+        IOSchedulingClass       = "idle";
+        PrivateTmp              = "yes";
+        PrivateNetwork          = "yes";
+        NoNewPrivileges         = "yes";
+        ReadWriteDirectories    = stateDir;
+        InaccessibleDirectories = "/home";
+        ExecStart               = "${pkgs.uptimed}/sbin/uptimed -f -p ${stateDir}/pid";
+      };
+
+      preStart = ''
+        if ! test -f ${stateDir}/bootid ; then
+          ${pkgs.uptimed}/sbin/uptimed -b
+        fi
+      '';
+    };
+  };
+}