about summary refs log tree commit diff
path: root/nixos/modules/services
diff options
context:
space:
mode:
authorVladimír Čunát <vcunat@gmail.com>2016-02-03 16:54:03 +0100
committerVladimír Čunát <vcunat@gmail.com>2016-02-03 16:57:19 +0100
commitae74c356d94b795eb07dfe9978788b49b70f5959 (patch)
treec13c6894b75f95d3a4dc4627efef508bb03dfba8 /nixos/modules/services
parentc9790126312119ce5a2a8ac946d9f086e7ea9f55 (diff)
parent53e0f8b1cdf36574bfede6e62e2ac2739c3ef804 (diff)
downloadnixlib-ae74c356d94b795eb07dfe9978788b49b70f5959.tar
nixlib-ae74c356d94b795eb07dfe9978788b49b70f5959.tar.gz
nixlib-ae74c356d94b795eb07dfe9978788b49b70f5959.tar.bz2
nixlib-ae74c356d94b795eb07dfe9978788b49b70f5959.tar.lz
nixlib-ae74c356d94b795eb07dfe9978788b49b70f5959.tar.xz
nixlib-ae74c356d94b795eb07dfe9978788b49b70f5959.tar.zst
nixlib-ae74c356d94b795eb07dfe9978788b49b70f5959.zip
Merge recent 'staging' into closure-size
Let's get rid of those merge conflicts.
Diffstat (limited to 'nixos/modules/services')
-rw-r--r--nixos/modules/services/mail/dovecot.nix104
-rw-r--r--nixos/modules/services/mail/postfix.nix37
-rw-r--r--nixos/modules/services/misc/ihaskell.nix2
-rw-r--r--nixos/modules/services/misc/nix-daemon.nix2
-rw-r--r--nixos/modules/services/monitoring/bosun.nix18
-rw-r--r--nixos/modules/services/monitoring/dd-agent.nix2
-rw-r--r--nixos/modules/services/networking/ddclient.nix2
-rw-r--r--nixos/modules/services/networking/gale.nix12
-rw-r--r--nixos/modules/services/networking/gateone.nix4
-rw-r--r--nixos/modules/services/networking/softether.nix31
-rw-r--r--nixos/modules/services/printing/cupsd.nix188
-rw-r--r--nixos/modules/services/search/elasticsearch.nix4
-rw-r--r--nixos/modules/services/system/uptimed.nix71
-rw-r--r--nixos/modules/services/x11/display-managers/default.nix9
-rw-r--r--nixos/modules/services/x11/display-managers/sddm.nix11
-rw-r--r--nixos/modules/services/x11/window-managers/i3.nix2
-rw-r--r--nixos/modules/services/x11/xserver.nix9
17 files changed, 294 insertions, 214 deletions
diff --git a/nixos/modules/services/mail/dovecot.nix b/nixos/modules/services/mail/dovecot.nix
index 36bdcaca47a3..11e8b26c75ef 100644
--- a/nixos/modules/services/mail/dovecot.nix
+++ b/nixos/modules/services/mail/dovecot.nix
@@ -9,16 +9,10 @@ let
   baseDir = "/run/dovecot2";
   stateDir = "/var/lib/dovecot";
 
-  protocols = concatStrings [
-    (optionalString cfg.enableImap "imap")
-    (optionalString cfg.enablePop3 "pop3")
-    (optionalString cfg.enableLmtp "lmtp")
-  ];
-
   dovecotConf = concatStrings [
     ''
       base_dir = ${baseDir}
-      protocols = ${protocols}
+      protocols = ${concatStringsSep " " cfg.protocols}
     ''
 
     (if isNull cfg.sslServerCert then ''
@@ -33,6 +27,8 @@ let
 
     ''
       default_internal_user = ${cfg.user}
+      ${optionalString (cfg.mailUser != null) "mail_uid = ${cfg.mailUser}"}
+      ${optionalString (cfg.mailGroup != null) "mail_gid = ${cfg.mailGroup}"}
 
       mail_location = ${cfg.mailLocation}
 
@@ -57,11 +53,17 @@ let
       }
     '')
 
+    (optionalString (cfg.sieveScripts != {}) ''
+      plugin {
+        ${concatStringsSep "\n" (mapAttrsToList (to: from: "sieve_${to} = ${stateDir}/sieve/${to}") cfg.sieveScripts)}
+      }
+    '')
+
     cfg.extraConfig
   ];
 
   modulesDir = pkgs.symlinkJoin "dovecot-modules"
-    (map (module: "${module}/lib/dovecot") cfg.modules);
+    (map (pkg: "${pkg}/lib/dovecot") ([ dovecotPkg ] ++ map (module: module.override { dovecot = dovecotPkg; }) cfg.modules));
 
 in
 {
@@ -87,6 +89,12 @@ in
       description = "Start the LMTP listener (when Dovecot is enabled).";
     };
 
+    protocols = mkOption {
+      type = types.listOf types.str;
+      default = [ ];
+      description = "Additional listeners to start when Dovecot is enabled.";
+    };
+
     package = mkOption {
       type = types.package;
       default = pkgs.dovecot22;
@@ -129,13 +137,25 @@ in
       '';
     };
 
+    mailUser = mkOption {
+      type = types.nullOr types.str;
+      default = null;
+      description = "Default user to store mail for virtual users.";
+    };
+
+    mailGroup = mkOption {
+      type = types.nullOr types.str;
+      default = null;
+      description = "Default group to store mail for virtual users.";
+    };
+
     modules = mkOption {
       type = types.listOf types.package;
       default = [];
       example = literalExample "[ pkgs.dovecot_pigeonhole ]";
       description = ''
         Symlinks the contents of lib/dovecot of every given package into
-        /var/lib/dovecot/modules. This will make the given modules available
+        /etc/dovecot/modules. This will make the given modules available
         if a dovecot package with the module_dir patch applied (like
         pkgs.dovecot22, the default) is being used.
       '';
@@ -162,7 +182,13 @@ in
     enablePAM = mkOption {
       type = types.bool;
       default = true;
-      description = "Wether to create a own Dovecot PAM service and configure PAM user logins.";
+      description = "Whether to create a own Dovecot PAM service and configure PAM user logins.";
+    };
+
+    sieveScripts = mkOption {
+      type = types.attrsOf types.path;
+      default = {};
+      description = "Sieve scripts to be executed. Key is a sequence, e.g. 'before2', 'after' etc.";
     };
 
     showPAMFailure = mkOption {
@@ -177,23 +203,31 @@ in
 
     security.pam.services.dovecot2 = mkIf cfg.enablePAM {};
 
+    services.dovecot2.protocols =
+     optional cfg.enableImap "imap"
+     ++ optional cfg.enablePop3 "pop3"
+     ++ optional cfg.enableLmtp "lmtp";
+
     users.extraUsers = [
-      { name = cfg.user;
-        uid = config.ids.uids.dovecot2;
-        description = "Dovecot user";
-        group = cfg.group;
-      }
       { name = "dovenull";
         uid = config.ids.uids.dovenull2;
         description = "Dovecot user for untrusted logins";
         group = cfg.group;
       }
-    ];
+    ] ++ optional (cfg.user == "dovecot2")
+         { name = "dovecot2";
+           uid = config.ids.uids.dovecot2;
+           description = "Dovecot user";
+           group = cfg.group;
+         };
+
+    users.extraGroups = optional (cfg.group == "dovecot2")
+      { name = "dovecot2";
+        gid = config.ids.gids.dovecot2;
+      };
 
-    users.extraGroups = singleton {
-      name = cfg.group;
-      gid = config.ids.gids.dovecot2;
-    };
+    environment.etc."dovecot/modules".source = modulesDir;
+    environment.etc."dovecot/dovecot.conf".source = cfg.configFile;
 
     systemd.services.dovecot2 = {
       description = "Dovecot IMAP/POP3 server";
@@ -201,26 +235,38 @@ in
       after = [ "keys.target" "network.target" ];
       wants = [ "keys.target" ];
       wantedBy = [ "multi-user.target" ];
-
-      preStart = ''
-        mkdir -p "${baseDir}/login"
-        chown -R ${cfg.user}:${cfg.group} "${baseDir}"
-        rm -f "${stateDir}/modules"
-        ln -s "${modulesDir}" "${stateDir}/modules"
-      '';
+      restartTriggers = [ cfg.configFile ];
 
       serviceConfig = {
-        ExecStart = "${dovecotPkg}/sbin/dovecot -F -c ${cfg.configFile}";
+        ExecStart = "${dovecotPkg}/sbin/dovecot -F";
+        ExecReload = "${dovecotPkg}/sbin/doveadm reload";
         Restart = "on-failure";
         RestartSec = "1s";
         StartLimitInterval = "1min";
+        RuntimeDirectory = [ "dovecot2" ];
       };
+
+      preStart = ''
+        rm -rf ${stateDir}/sieve
+      '' + optionalString (cfg.sieveScripts != {}) ''
+        mkdir -p ${stateDir}/sieve
+        ${concatStringsSep "\n" (mapAttrsToList (to: from: ''
+          if [ -d '${from}' ]; then
+            mkdir '${stateDir}/sieve/${to}'
+            cp ${from}/*.sieve '${stateDir}/sieve/${to}'
+          else
+            cp '${from}' '${stateDir}/sieve/${to}'
+          fi
+           ${pkgs.dovecot_pigeonhole}/bin/sievec '${stateDir}/sieve/${to}'
+        '') cfg.sieveScripts)}
+        chown -R '${cfg.mailUser}:${cfg.mailGroup}' '${stateDir}/sieve'
+      '';
     };
 
     environment.systemPackages = [ dovecotPkg ];
 
     assertions = [
-      { assertion = cfg.enablePop3 || cfg.enableImap;
+      { assertion = intersectLists cfg.protocols [ "pop3" "imap" ] != [];
         message = "dovecot needs at least one of the IMAP or POP3 listeners enabled";
       }
       { assertion = isNull cfg.sslServerCert == isNull cfg.sslServerKey
diff --git a/nixos/modules/services/mail/postfix.nix b/nixos/modules/services/mail/postfix.nix
index 6c5d7e92702b..f2d8189de6ef 100644
--- a/nixos/modules/services/mail/postfix.nix
+++ b/nixos/modules/services/mail/postfix.nix
@@ -20,6 +20,23 @@ let
       mail_owner = ${user}
       default_privs = nobody
 
+      # NixOS specific locations
+      data_directory = /var/lib/postfix/data
+      queue_directory = /var/lib/postfix/queue
+
+      # Default location of everything in package
+      meta_directory = ${pkgs.postfix}/etc/postfix
+      command_directory = ${pkgs.postfix}/bin
+      sample_directory = /etc/postfix
+      newaliases_path = ${pkgs.postfix}/bin/newaliases
+      mailq_path = ${pkgs.postfix}/bin/mailq
+      readme_directory = no
+      sendmail_path = ${pkgs.postfix}/bin/sendmail
+      daemon_directory = ${pkgs.postfix}/libexec/postfix
+      manpage_directory = ${pkgs.postfix}/share/man
+      html_directory = ${pkgs.postfix}/share/postfix/doc/html
+      shlib_directory = no
+
     ''
     + optionalString config.networking.enableIPv6 ''
       inet_protocols = all
@@ -435,31 +452,35 @@ in
               mkdir -p /var/lib
               mv /var/postfix /var/lib/postfix
             fi
-            mkdir -p /var/lib/postfix/data /var/lib/postfix/queue/{pid,public,maildrop}
 
-            chown -R ${user}:${group} /var/lib/postfix
-            chown root /var/lib/postfix/queue
-            chown root /var/lib/postfix/queue/pid
-            chgrp -R ${setgidGroup} /var/lib/postfix/queue/{public,maildrop}
-            chmod 770 /var/lib/postfix/queue/{public,maildrop}
+            # All permissions set according ${pkgs.postfix}/etc/postfix/postfix-files script
+            mkdir -p /var/lib/postfix /var/lib/postfix/queue/{pid,public,maildrop}
+            chmod 0755 /var/lib/postfix
+            chown root:root /var/lib/postfix
 
             rm -rf /var/lib/postfix/conf
             mkdir -p /var/lib/postfix/conf
+            chmod 0755 /var/lib/postfix/conf
+            ln -sf ${pkgs.postfix}/etc/postfix/postfix-files
             ln -sf ${mainCfFile} /var/lib/postfix/conf/main.cf
             ln -sf ${masterCfFile} /var/lib/postfix/conf/master.cf
+
             ${concatStringsSep "\n" (mapAttrsToList (to: from: ''
               ln -sf ${from} /var/lib/postfix/conf/${to}
-              postalias /var/lib/postfix/conf/${to}
+              ${pkgs.postfix}/bin/postalias /var/lib/postfix/conf/${to}
             '') cfg.aliasFiles)}
             ${concatStringsSep "\n" (mapAttrsToList (to: from: ''
               ln -sf ${from} /var/lib/postfix/conf/${to}
-              postmap /var/lib/postfix/conf/${to}
+              ${pkgs.postfix}/bin/postmap /var/lib/postfix/conf/${to}
             '') cfg.mapFiles)}
 
             mkdir -p /var/spool/mail
             chown root:root /var/spool/mail
             chmod a+rwxt /var/spool/mail
             ln -sf /var/spool/mail /var/
+
+            #Finally delegate to postfix checking remain directories in /var/lib/postfix and set permissions on them
+            ${pkgs.postfix}/bin/postfix set-permissions config_directory=/var/lib/postfix/conf
           '';
         };
     }
diff --git a/nixos/modules/services/misc/ihaskell.nix b/nixos/modules/services/misc/ihaskell.nix
index 1927922909ee..d0e9b839e754 100644
--- a/nixos/modules/services/misc/ihaskell.nix
+++ b/nixos/modules/services/misc/ihaskell.nix
@@ -6,7 +6,6 @@ let
 
   cfg = config.services.ihaskell;
   ihaskell = pkgs.ihaskell.override {
-    inherit (cfg.haskellPackages) ihaskell ghcWithPackages;
     packages = self: cfg.extraPackages self;
   };
 
@@ -22,7 +21,6 @@ in
       };
 
       haskellPackages = mkOption {
-        type = types.attrsOf types.package;
         default = pkgs.haskellPackages;
         defaultText = "pkgs.haskellPackages";
         example = literalExample "pkgs.haskell.packages.ghc784";
diff --git a/nixos/modules/services/misc/nix-daemon.nix b/nixos/modules/services/misc/nix-daemon.nix
index 60e826bafd1e..24ae515a6b87 100644
--- a/nixos/modules/services/misc/nix-daemon.nix
+++ b/nixos/modules/services/misc/nix-daemon.nix
@@ -364,7 +364,7 @@ in
           ++ optionals cfg.distributedBuilds [ pkgs.gzip ];
 
         environment = cfg.envVars
-          // { CURL_CA_BUNDLE = "/etc/ssl/certs/ca-bundle.crt"; }
+          // { CURL_CA_BUNDLE = "/etc/ssl/certs/ca-certificates.crt"; }
           // config.networking.proxy.envVars;
 
         serviceConfig =
diff --git a/nixos/modules/services/monitoring/bosun.nix b/nixos/modules/services/monitoring/bosun.nix
index 46273fc12187..51d38e8db4de 100644
--- a/nixos/modules/services/monitoring/bosun.nix
+++ b/nixos/modules/services/monitoring/bosun.nix
@@ -129,17 +129,19 @@ in {
       description = "bosun metrics collector (part of Bosun)";
       wantedBy = [ "multi-user.target" ];
 
-      preStart =
-        ''
-        mkdir -p `dirname ${cfg.stateFile}`;
-        touch ${cfg.stateFile}
-        touch ${cfg.stateFile}.tmp
+      preStart = ''
+        mkdir -p "$(dirname "${cfg.stateFile}")";
+        touch "${cfg.stateFile}"
+        touch "${cfg.stateFile}.tmp"
+
+        mkdir -p "${cfg.ledisDir}";
 
         if [ "$(id -u)" = 0 ]; then
-          chown ${cfg.user}:${cfg.group} ${cfg.stateFile}
-          chown ${cfg.user}:${cfg.group} ${cfg.stateFile}.tmp
+          chown ${cfg.user}:${cfg.group} "${cfg.stateFile}"
+          chown ${cfg.user}:${cfg.group} "${cfg.stateFile}.tmp"
+          chown ${cfg.user}:${cfg.group} "${cfg.ledisDir}"
         fi
-        '';
+      '';
 
       serviceConfig = {
         PermissionsStartOnly = true;
diff --git a/nixos/modules/services/monitoring/dd-agent.nix b/nixos/modules/services/monitoring/dd-agent.nix
index 8c847af3bfc0..ed9be73ba65b 100644
--- a/nixos/modules/services/monitoring/dd-agent.nix
+++ b/nixos/modules/services/monitoring/dd-agent.nix
@@ -183,7 +183,7 @@ in {
         Restart = "always";
         RestartSec = 2;
       };
-      environment.SSL_CERT_FILE = "/etc/ssl/certs/ca-bundle.crt";
+      environment.SSL_CERT_FILE = "/etc/ssl/certs/ca-certificates.crt";
       restartTriggers = [ pkgs.dd-agent ddConf diskConfig networkConfig postgresqlConfig nginxConfig mongoConfig ];
     };
 
diff --git a/nixos/modules/services/networking/ddclient.nix b/nixos/modules/services/networking/ddclient.nix
index ee06dfbbca3a..e60520c742bd 100644
--- a/nixos/modules/services/networking/ddclient.nix
+++ b/nixos/modules/services/networking/ddclient.nix
@@ -127,7 +127,7 @@ in
       wantedBy = [ "multi-user.target" ];
       after = [ "network.target" ];
 
-      environment.SSL_CERT_FILE = "/etc/ssl/certs/ca-bundle.crt";
+      environment.SSL_CERT_FILE = "/etc/ssl/certs/ca-certificates.crt";
       serviceConfig = {
         # Uncomment this if too many problems occur:
         # Type = "forking";
diff --git a/nixos/modules/services/networking/gale.nix b/nixos/modules/services/networking/gale.nix
index 3a5d9bd63c7b..bc975159cdfd 100644
--- a/nixos/modules/services/networking/gale.nix
+++ b/nixos/modules/services/networking/gale.nix
@@ -76,7 +76,7 @@ in
 
        system.activationScripts.gale = mkIf cfg.enable (
          stringAfter [ "users" "groups" ] ''
-           chmod -R 755 ${home}
+           chmod 755 ${home}
            mkdir -m 0777 -p ${home}/auth/cache
            mkdir -m 1777 -p ${home}/auth/local # GALE_DOMAIN.gpub
            mkdir -m 0700 -p ${home}/auth/private # ROOT.gpub
@@ -86,7 +86,8 @@ in
            mkdir -m 0700 -p ${home}/.gale/auth/private # GALE_DOMAIN.gpri
 
            ln -sf ${pkgs.gale}/etc/gale/auth/trusted/ROOT "${home}/auth/trusted/ROOT"
-           chown -R ${cfg.user}:${cfg.group} ${home}
+           chown ${cfg.user}:${cfg.group} ${home} ${home}/auth ${home}/auth/*
+           chown ${cfg.user}:${cfg.group} ${home}/.gale ${home}/.gale/auth ${home}/.gale/auth/private
          ''
        );
 
@@ -149,10 +150,9 @@ in
          after = [ "network.target" ];
 
          preStart = ''
-           install -m 0640 ${keyPath}/${cfg.domain}.gpri "${home}/.gale/auth/private/"
-           install -m 0644 ${gpubFile} "${home}/.gale/auth/private/${cfg.domain}.gpub"
-           install -m 0644 ${gpubFile} "${home}/auth/local/${cfg.domain}.gpub"
-           chown -R ${cfg.user}:${cfg.group} ${home}
+           install -m 0640 -o ${cfg.user} -g ${cfg.group} ${keyPath}/${cfg.domain}.gpri "${home}/.gale/auth/private/"
+           install -m 0644 -o ${cfg.user} -g ${cfg.group} ${gpubFile} "${home}/.gale/auth/private/${cfg.domain}.gpub"
+           install -m 0644 -o ${cfg.user} -g ${cfg.group} ${gpubFile} "${home}/auth/local/${cfg.domain}.gpub"
          '';
 
          serviceConfig = {
diff --git a/nixos/modules/services/networking/gateone.nix b/nixos/modules/services/networking/gateone.nix
index 93273837181e..78ff0b76198c 100644
--- a/nixos/modules/services/networking/gateone.nix
+++ b/nixos/modules/services/networking/gateone.nix
@@ -21,7 +21,7 @@ options = {
 };
 config = mkIf cfg.enable {
   environment.systemPackages = with pkgs.pythonPackages; [
-    gateone pkgs.openssh pkgs.procps pkgs.coreutils ];
+    gateone pkgs.openssh pkgs.procps pkgs.coreutils pkgs.cacert];
 
   users.extraUsers.gateone = {
     description = "GateOne privilege separation user";
@@ -49,8 +49,6 @@ config = mkIf cfg.enable {
       User = "gateone";
       Group = "gateone";
       WorkingDirectory = cfg.settingsDir;
-      PermissionsStartOnly = true;
-
     };
 
     wantedBy = [ "multi-user.target" ];
diff --git a/nixos/modules/services/networking/softether.nix b/nixos/modules/services/networking/softether.nix
index a421b32f02c2..5e49efc3aa3a 100644
--- a/nixos/modules/services/networking/softether.nix
+++ b/nixos/modules/services/networking/softether.nix
@@ -61,11 +61,14 @@ in
             dataDir = cfg.dataDir;
           }))
         ];
-      systemd.services.softether = {
-        description = "SoftEther VPN services initial job";
-        after = [ "network-interfaces.target" ];
-        wantedBy = [ "multi-user.target" ];
-        preStart = ''
+      systemd.services."softether-init" = {
+        description = "SoftEther VPN services initial task";
+        wantedBy = [ "network-interfaces.target" ];
+        serviceConfig = {
+          Type = "oneshot";
+          RemainAfterExit = false;
+        };
+        script = ''
             for d in vpnserver vpnbridge vpnclient vpncmd; do
                 if ! test -e ${cfg.dataDir}/$d; then
                     ${pkgs.coreutils}/bin/mkdir -m0700 -p ${cfg.dataDir}/$d
@@ -81,12 +84,12 @@ in
     (mkIf (cfg.vpnserver.enable) {
       systemd.services.vpnserver = {
         description = "SoftEther VPN Server";
-        after = [ "network-interfaces.target" ];
-        wantedBy = [ "multi-user.target" ];
+        after = [ "softether-init.service" ];
+        wantedBy = [ "network-interfaces.target" ];
         serviceConfig = {
+          Type = "forking";
           ExecStart = "${pkg}/bin/vpnserver start";
           ExecStop = "${pkg}/bin/vpnserver stop";
-          Type = "forking";
         };
         preStart = ''
             rm -rf ${cfg.dataDir}/vpnserver/vpnserver
@@ -101,12 +104,12 @@ in
     (mkIf (cfg.vpnbridge.enable) {
       systemd.services.vpnbridge = {
         description = "SoftEther VPN Bridge";
-        after = [ "network-interfaces.target" ];
-        wantedBy = [ "multi-user.target" ];
+        after = [ "softether-init.service" ];
+        wantedBy = [ "network-interfaces.target" ];
         serviceConfig = {
+          Type = "forking";
           ExecStart = "${pkg}/bin/vpnbridge start";
           ExecStop = "${pkg}/bin/vpnbridge stop";
-          Type = "forking";
         };
         preStart = ''
             rm -rf ${cfg.dataDir}/vpnbridge/vpnbridge
@@ -121,12 +124,12 @@ in
     (mkIf (cfg.vpnclient.enable) {
       systemd.services.vpnclient = {
         description = "SoftEther VPN Client";
-        after = [ "network-interfaces.target" ];
-        wantedBy = [ "multi-user.target" ];
+        after = [ "softether-init.service" ];
+        wantedBy = [ "network-interfaces.target" ];
         serviceConfig = {
+          Type = "forking";
           ExecStart = "${pkg}/bin/vpnclient start";
           ExecStop = "${pkg}/bin/vpnclient stop";
-          Type = "forking";
         };
         preStart = ''
             rm -rf ${cfg.dataDir}/vpnclient/vpnclient
diff --git a/nixos/modules/services/printing/cupsd.nix b/nixos/modules/services/printing/cupsd.nix
index ba288a5d0611..9411a225beb3 100644
--- a/nixos/modules/services/printing/cupsd.nix
+++ b/nixos/modules/services/printing/cupsd.nix
@@ -4,10 +4,13 @@ with lib;
 
 let
 
-  inherit (pkgs) cups cups_filters;
+  inherit (pkgs) cups cups-pk-helper cups_filters gutenprint;
 
   cfg = config.services.printing;
 
+  avahiEnabled = config.services.avahi.enable;
+  polkitEnabled = config.security.polkit.enable;
+
   additionalBackends = pkgs.runCommand "additional-cups-backends" { }
     ''
       mkdir -p $out
@@ -30,12 +33,75 @@ let
   # cupsd.conf tells cupsd to use this tree.
   bindir = pkgs.buildEnv {
     name = "cups-progs";
-    paths = cfg.drivers;
-    pathsToLink = [ "/lib/cups" "/share/cups" "/bin" "/etc/cups" ];
+    paths =
+      [ cups additionalBackends cups_filters pkgs.ghostscript ]
+      ++ optional cfg.gutenprint gutenprint
+      ++ cfg.drivers;
+    pathsToLink = [ "/lib/cups" "/share/cups" "/bin" ];
     postBuild = cfg.bindirCmds;
     ignoreCollisions = true;
   };
 
+  writeConf = name: text: pkgs.writeTextFile {
+    inherit name text;
+    destination = "/etc/cups/${name}";
+  };
+
+  cupsFilesFile = writeConf "cups-files.conf" ''
+    SystemGroup root wheel
+
+    ServerBin ${bindir}/lib/cups
+    DataDir ${bindir}/share/cups
+
+    AccessLog syslog
+    ErrorLog syslog
+    PageLog syslog
+
+    TempDir ${cfg.tempDir}
+
+    # User and group used to run external programs, including
+    # those that actually send the job to the printer.  Note that
+    # Udev sets the group of printer devices to `lp', so we want
+    # these programs to run as `lp' as well.
+    User cups
+    Group lp
+
+    ${cfg.extraFilesConf}
+  '';
+
+  cupsdFile = writeConf "cupsd.conf" ''
+    ${concatMapStrings (addr: ''
+      Listen ${addr}
+    '') cfg.listenAddresses}
+    Listen /var/run/cups/cups.sock
+
+    SetEnv PATH ${bindir}/lib/cups/filter:${bindir}/bin
+
+    DefaultShared ${if cfg.defaultShared then "Yes" else "No"}
+
+    Browsing ${if cfg.browsing then "Yes" else "No"}
+
+    WebInterface ${if cfg.webInterface then "Yes" else "No"}
+
+    ${cfg.extraConf}
+  '';
+
+  browsedFile = writeConf "cups-browsed.conf" cfg.browsedConf;
+
+  rootdir = pkgs.buildEnv {
+    name = "cups-progs";
+    paths = [
+      cupsFilesFile
+      cupsdFile
+      (writeConf "client.conf" cfg.clientConf)
+      (writeConf "snmp.conf" cfg.snmpConf)
+    ] ++ optional avahiEnabled browsedFile
+      ++ optional cfg.gutenprint gutenprint
+      ++ cfg.drivers;
+    pathsToLink = [ "/etc/cups" ];
+    ignoreCollisions = true;
+  };
+
 in
 
 {
@@ -96,25 +162,11 @@ in
         '';
       };
 
-      cupsdConf = mkOption {
-        type = types.lines;
-        default = "";
-        example =
-          ''
-            BrowsePoll cups.example.com
-            LogLevel debug
-          '';
-        description = ''
-          The contents of the configuration file of the CUPS daemon
-          (<filename>cupsd.conf</filename>).
-        '';
-      };
-
-      cupsFilesConf = mkOption {
+      extraFilesConf = mkOption {
         type = types.lines;
         default = "";
         description = ''
-          The contents of the configuration file of the CUPS daemon
+          Extra contents of the configuration file of the CUPS daemon
           (<filename>cups-files.conf</filename>).
         '';
       };
@@ -171,8 +223,18 @@ in
         '';
       };
 
+      gutenprint = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Whether to enable Gutenprint drivers for CUPS. This includes auto-updating
+          Gutenprint PPD files.
+        '';
+      };
+
       drivers = mkOption {
         type = types.listOf types.path;
+        default = [];
         example = literalExample "[ pkgs.splix ]";
         description = ''
           CUPS drivers to use. Drivers provided by CUPS, cups-filters, Ghostscript
@@ -204,15 +266,10 @@ in
         description = "CUPS printing services";
       };
 
-    environment.systemPackages = [ cups ];
+    environment.systemPackages = [ cups ] ++ optional polkitEnabled cups-pk-helper;
+    environment.etc."cups".source = "/var/lib/cups";
 
-    environment.etc."cups/client.conf".text = cfg.clientConf;
-    environment.etc."cups/cups-files.conf".text = cfg.cupsFilesConf;
-    environment.etc."cups/cupsd.conf".text = cfg.cupsdConf;
-    environment.etc."cups/cups-browsed.conf".text = cfg.browsedConf;
-    environment.etc."cups/snmp.conf".text = cfg.snmpConf;
-
-    services.dbus.packages = [ cups ];
+    services.dbus.packages = [ cups ] ++ optional polkitEnabled cups-pk-helper;
 
     # Cups uses libusb to talk to printers, and does not use the
     # linux kernel driver. If the driver is not in a black list, it
@@ -230,19 +287,35 @@ in
 
         preStart =
           ''
-            mkdir -m 0755 -p /etc/cups
             mkdir -m 0700 -p /var/cache/cups
             mkdir -m 0700 -p /var/spool/cups
             mkdir -m 0755 -p ${cfg.tempDir}
-          '';
 
-        restartTriggers =
-          [ config.environment.etc."cups/cups-files.conf".source
-            config.environment.etc."cups/cupsd.conf".source
-          ];
+            mkdir -m 0755 -p /var/lib/cups
+            # Backwards compatibility
+            if [ ! -L /etc/cups ]; then
+              mv /etc/cups/* /var/lib/cups
+              rmdir /etc/cups
+              ln -s /var/lib/cups /etc/cups
+            fi
+            # First, clean existing symlinks
+            if [ -n "$(ls /var/lib/cups)" ]; then
+              for i in /var/lib/cups/*; do
+                [ -L "$i" ] && rm "$i"
+              done
+            fi
+            # Then, populate it with static files
+            cd ${rootdir}/etc/cups
+            for i in *; do
+              [ ! -e "/var/lib/cups/$i" ] && ln -s "${rootdir}/etc/cups/$i" "/var/lib/cups/$i"
+            done
+            ${optionalString cfg.gutenprint ''
+              ${gutenprint}/bin/cups-genppdupdate
+            ''}
+          '';
       };
 
-    systemd.services.cups-browsed = mkIf config.services.avahi.enable
+    systemd.services.cups-browsed = mkIf avahiEnabled
       { description = "CUPS Remote Printer Discovery";
 
         wantedBy = [ "multi-user.target" ];
@@ -255,54 +328,13 @@ in
 
         serviceConfig.ExecStart = "${cups_filters}/bin/cups-browsed";
 
-        restartTriggers =
-          [ config.environment.etc."cups/cups-browsed.conf".source
-          ];
+        restartTriggers = [ browsedFile ];
       };
 
-    services.printing.drivers =
-      [ cups pkgs.ghostscript pkgs.cups_filters additionalBackends
-        pkgs.perl pkgs.coreutils pkgs.gnused pkgs.bc pkgs.gawk pkgs.gnugrep
-      ];
-
-    services.printing.cupsFilesConf =
-      ''
-        SystemGroup root wheel
-
-        ServerBin ${bindir}/lib/cups
-        DataDir ${bindir}/share/cups
-
-        AccessLog syslog
-        ErrorLog syslog
-        PageLog syslog
-
-        TempDir ${cfg.tempDir}
-
-        # User and group used to run external programs, including
-        # those that actually send the job to the printer.  Note that
-        # Udev sets the group of printer devices to `lp', so we want
-        # these programs to run as `lp' as well.
-        User cups
-        Group lp
-      '';
-
-    services.printing.cupsdConf =
+    services.printing.extraConf =
       ''
         LogLevel info
 
-        ${concatMapStrings (addr: ''
-          Listen ${addr}
-        '') cfg.listenAddresses}
-        Listen /var/run/cups/cups.sock
-
-        SetEnv PATH ${bindir}/lib/cups/filter:${bindir}/bin:${bindir}/sbin
-
-        DefaultShared ${if cfg.defaultShared then "Yes" else "No"}
-
-        Browsing ${if cfg.browsing then "Yes" else "No"}
-
-        WebInterface ${if cfg.webInterface then "Yes" else "No"}
-
         DefaultAuthType Basic
 
         <Location />
@@ -343,8 +375,6 @@ in
             Order deny,allow
           </Limit>
         </Policy>
-
-        ${cfg.extraConf}
       '';
 
     security.pam.services.cups = {};
diff --git a/nixos/modules/services/search/elasticsearch.nix b/nixos/modules/services/search/elasticsearch.nix
index e586600cdffd..478ebcfb9664 100644
--- a/nixos/modules/services/search/elasticsearch.nix
+++ b/nixos/modules/services/search/elasticsearch.nix
@@ -128,6 +128,7 @@ in {
       description = "Elasticsearch Daemon";
       wantedBy = [ "multi-user.target" ];
       after = [ "network-interfaces.target" ];
+      path = [ pkgs.inetutils ];
       environment = { ES_HOME = cfg.dataDir; };
       serviceConfig = {
         ExecStart = "${cfg.package}/bin/elasticsearch -Des.path.conf=${configDir} ${toString cfg.extraCmdLineOptions}";
@@ -139,8 +140,7 @@ in {
         if [ "$(id -u)" = 0 ]; then chown -R elasticsearch ${cfg.dataDir}; fi
 
         # Install plugins
-        rm ${cfg.dataDir}/plugins || true
-        ln -s ${esPlugins}/plugins ${cfg.dataDir}/plugins
+        ln -sfT ${esPlugins}/plugins ${cfg.dataDir}/plugins
       '';
       postStart = mkBefore ''
         until ${pkgs.curl.bin}/bin/curl -s -o /dev/null ${cfg.listenAddress}:${toString cfg.port}; do
diff --git a/nixos/modules/services/system/uptimed.nix b/nixos/modules/services/system/uptimed.nix
index 5f8916bbf9a4..b20d60968032 100644
--- a/nixos/modules/services/system/uptimed.nix
+++ b/nixos/modules/services/system/uptimed.nix
@@ -1,66 +1,55 @@
-{pkgs, config, lib, ...}:
+{ config, lib, pkgs, ... }:
 
-let
-
-  inherit (lib) mkOption mkIf singleton;
-
-  inherit (pkgs) uptimed;
+with lib;
 
+let
+  cfg = config.services.uptimed;
   stateDir = "/var/spool/uptimed";
-
-  uptimedUser = "uptimed";
-
 in
-
 {
-
-  ###### interface
-
   options = {
-
     services.uptimed = {
-
       enable = mkOption {
         default = false;
         description = ''
-          Uptimed allows you to track your highest uptimes.
+          Enable <literal>uptimed</literal>, allowing you to track
+          your highest uptimes.
         '';
       };
-
     };
-
   };
 
-
-  ###### implementation
-
-  config = mkIf config.services.uptimed.enable {
-
-    environment.systemPackages = [ uptimed ];
-
-    users.extraUsers = singleton
-      { name = uptimedUser;
-        uid = config.ids.uids.uptimed;
-        description = "Uptimed daemon user";
-        home = stateDir;
-      };
+  config = mkIf cfg.enable {
+    users.extraUsers.uptimed = {
+      description = "Uptimed daemon user";
+      home        = stateDir;
+      createHome  = true;
+      uid         = config.ids.uids.uptimed;
+    };
 
     systemd.services.uptimed = {
-      description = "Uptimed daemon";
-      wantedBy = [ "multi-user.target" ];
+      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 = ''
-        mkdir -m 0755 -p ${stateDir}
-        chown ${uptimedUser} ${stateDir}
-
         if ! test -f ${stateDir}/bootid ; then
-          ${uptimed}/sbin/uptimed -b
+          ${pkgs.uptimed}/sbin/uptimed -b
         fi
       '';
-
-      script = "${uptimed}/sbin/uptimed";
     };
-
   };
-
 }
diff --git a/nixos/modules/services/x11/display-managers/default.nix b/nixos/modules/services/x11/display-managers/default.nix
index 3aa09193a66e..3437d8f38930 100644
--- a/nixos/modules/services/x11/display-managers/default.nix
+++ b/nixos/modules/services/x11/display-managers/default.nix
@@ -16,13 +16,6 @@ let
   cfg = config.services.xserver;
   xorg = pkgs.xorg;
 
-  vaapiDrivers = pkgs.buildEnv {
-    name = "vaapi-drivers";
-    paths = cfg.vaapiDrivers;
-    # We only want /lib/dri, but with a single input path, we need "/" for it to work
-    pathsToLink = [ "/" ];
-  };
-
   fontconfig = config.fonts.fontconfig;
   xresourcesXft = pkgs.writeText "Xresources-Xft" ''
     ${optionalString (fontconfig.dpi != 0) ''Xft.dpi: ${toString fontconfig.dpi}''}
@@ -107,8 +100,6 @@ let
           ${xorg.xrdb}/bin/xrdb -merge ~/.Xdefaults
       fi
 
-      export LIBVA_DRIVERS_PATH=${vaapiDrivers}/lib/dri
-
       # Speed up application start by 50-150ms according to
       # http://kdemonkey.blogspot.nl/2008/04/magic-trick.html
       rm -rf $HOME/.compose-cache
diff --git a/nixos/modules/services/x11/display-managers/sddm.nix b/nixos/modules/services/x11/display-managers/sddm.nix
index 6b344822977f..7a17a222bcab 100644
--- a/nixos/modules/services/x11/display-managers/sddm.nix
+++ b/nixos/modules/services/x11/display-managers/sddm.nix
@@ -31,6 +31,9 @@ let
     [General]
     HaltCommand=${pkgs.systemd}/bin/systemctl poweroff
     RebootCommand=${pkgs.systemd}/bin/systemctl reboot
+    ${optionalString cfg.autoNumlock ''
+    Numlock=on
+    ''}
 
     [Theme]
     Current=${cfg.theme}
@@ -110,6 +113,14 @@ in
         '';
       };
 
+      autoNumlock = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Enable numlock at login.
+        '';
+      };
+
       setupScript = mkOption {
         type = types.str;
         default = "";
diff --git a/nixos/modules/services/x11/window-managers/i3.nix b/nixos/modules/services/x11/window-managers/i3.nix
index 0d5816e363d6..d43dacb1be6b 100644
--- a/nixos/modules/services/x11/window-managers/i3.nix
+++ b/nixos/modules/services/x11/window-managers/i3.nix
@@ -34,6 +34,6 @@ in
         '';
       }];
     };
-    environment.systemPackages = [ pkgs.i3 ];
+    environment.systemPackages = with pkgs; [ i3 i3status dmenu ];
   };
 }
diff --git a/nixos/modules/services/x11/xserver.nix b/nixos/modules/services/x11/xserver.nix
index 86f0641b0e37..069653d1e458 100644
--- a/nixos/modules/services/x11/xserver.nix
+++ b/nixos/modules/services/x11/xserver.nix
@@ -216,15 +216,6 @@ in
         '';
       };
 
-      vaapiDrivers = mkOption {
-        type = types.listOf types.path;
-        default = [ ];
-        example = literalExample "[ pkgs.vaapiIntel pkgs.vaapiVdpau ]";
-        description = ''
-          Packages providing libva acceleration drivers.
-        '';
-      };
-
       startGnuPGAgent = mkOption {
         type = types.bool;
         default = false;