summary refs log tree commit diff
path: root/nixos/modules/services
diff options
context:
space:
mode:
Diffstat (limited to 'nixos/modules/services')
-rw-r--r--nixos/modules/services/continuous-integration/jenkins/default.nix31
-rw-r--r--nixos/modules/services/continuous-integration/jenkins/job-builder.nix155
-rw-r--r--nixos/modules/services/databases/postgresql.nix4
-rw-r--r--nixos/modules/services/hardware/actkbd.nix3
-rw-r--r--nixos/modules/services/hardware/tlp.nix24
-rw-r--r--nixos/modules/services/mail/postfix.nix41
-rw-r--r--nixos/modules/services/misc/autofs.nix45
-rw-r--r--nixos/modules/services/misc/calibre-server.nix63
-rw-r--r--nixos/modules/services/misc/ihaskell.nix6
-rw-r--r--nixos/modules/services/misc/nixos-manual.nix4
-rw-r--r--nixos/modules/services/misc/parsoid.nix2
-rw-r--r--nixos/modules/services/misc/synergy.nix2
-rw-r--r--nixos/modules/services/monitoring/bosun.nix10
-rw-r--r--nixos/modules/services/monitoring/grafana.nix2
-rw-r--r--nixos/modules/services/monitoring/teamviewer.nix1
-rw-r--r--nixos/modules/services/networking/asterisk.nix1
-rw-r--r--nixos/modules/services/networking/autossh.nix114
-rw-r--r--nixos/modules/services/networking/copy-com.nix3
-rw-r--r--nixos/modules/services/networking/networkmanager.nix31
-rw-r--r--nixos/modules/services/networking/quassel.nix13
-rw-r--r--nixos/modules/services/networking/supplicant.nix249
-rw-r--r--nixos/modules/services/networking/tlsdated.nix2
-rw-r--r--nixos/modules/services/networking/wakeonlan.nix2
-rw-r--r--nixos/modules/services/scheduling/cron.nix2
-rw-r--r--nixos/modules/services/web-servers/lighttpd/default.nix1
-rw-r--r--nixos/modules/services/x11/desktop-managers/gnome3.nix1
-rw-r--r--nixos/modules/services/x11/desktop-managers/kde5.nix135
-rw-r--r--nixos/modules/services/x11/display-managers/gdm.nix4
-rw-r--r--nixos/modules/services/x11/display-managers/sddm.nix90
-rw-r--r--nixos/modules/services/x11/redshift.nix12
-rw-r--r--nixos/modules/services/x11/window-managers/clfswm.nix31
-rw-r--r--nixos/modules/services/x11/window-managers/default.nix1
-rw-r--r--nixos/modules/services/x11/window-managers/xmonad.nix6
33 files changed, 940 insertions, 151 deletions
diff --git a/nixos/modules/services/continuous-integration/jenkins/default.nix b/nixos/modules/services/continuous-integration/jenkins/default.nix
index 31e585f211fe..0568b1af7d5c 100644
--- a/nixos/modules/services/continuous-integration/jenkins/default.nix
+++ b/nixos/modules/services/continuous-integration/jenkins/default.nix
@@ -65,11 +65,15 @@ in {
       };
 
       environment = mkOption {
-        default = { NIX_REMOTE = "daemon"; };
+        default = { };
         type = with types; attrsOf str;
         description = ''
           Additional environment variables to be passed to the jenkins process.
-          The environment will always include JENKINS_HOME.
+          As a base environment, jenkins receives NIX_PATH, SSL_CERT_FILE and
+          GIT_SSL_CAINFO from <option>environment.sessionVariables</option>,
+          NIX_REMOTE is set to "daemon" and JENKINS_HOME is set to
+          the value of <option>services.jenkins.home</option>. This option has
+          precedence and can be used to override those mentioned variables.
         '';
       };
 
@@ -106,12 +110,29 @@ in {
       after = [ "network.target" ];
       wantedBy = [ "multi-user.target" ];
 
-      environment = {
-        JENKINS_HOME = cfg.home;
-      } // cfg.environment;
+      environment =
+        let
+          selectedSessionVars =
+            lib.filterAttrs (n: v: builtins.elem n
+                [ "NIX_PATH"
+                  "SSL_CERT_FILE"
+                  "GIT_SSL_CAINFO"
+                ])
+              config.environment.sessionVariables;
+        in
+          selectedSessionVars //
+          { JENKINS_HOME = cfg.home;
+            NIX_REMOTE = "daemon";
+          } //
+          cfg.environment;
 
       path = cfg.packages;
 
+      # Force .war (re)extraction, or else we might run stale Jenkins.
+      preStart = ''
+        rm -rf ${cfg.home}/war
+      '';
+
       script = ''
         ${pkgs.jdk}/bin/java -jar ${pkgs.jenkins} --httpPort=${toString cfg.port} ${concatStringsSep " " cfg.extraOptions}
       '';
diff --git a/nixos/modules/services/continuous-integration/jenkins/job-builder.nix b/nixos/modules/services/continuous-integration/jenkins/job-builder.nix
new file mode 100644
index 000000000000..ec15a6a3d706
--- /dev/null
+++ b/nixos/modules/services/continuous-integration/jenkins/job-builder.nix
@@ -0,0 +1,155 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  jenkinsCfg = config.services.jenkins;
+  cfg = config.services.jenkins.jobBuilder;
+
+in {
+  options = {
+    services.jenkins.jobBuilder = {
+      enable = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Whether or not to enable the Jenkins Job Builder (JJB) service. It
+          allows defining jobs for Jenkins in a declarative manner.
+
+          Jobs managed through the Jenkins WebUI (or by other means) are left
+          unchanged.
+
+          Note that it really is declarative configuration; if you remove a
+          previously defined job, the corresponding job directory will be
+          deleted.
+
+          Please see the Jenkins Job Builder documentation for more info:
+          <link xlink:href="http://docs.openstack.org/infra/jenkins-job-builder/">
+          http://docs.openstack.org/infra/jenkins-job-builder/</link>
+        '';
+      };
+
+      yamlJobs = mkOption {
+        default = "";
+        type = types.lines;
+        example = ''
+          - job:
+              name: jenkins-job-test-1
+              builders:
+                - shell: echo 'Hello world!'
+        '';
+        description = ''
+          Job descriptions for Jenkins Job Builder in YAML format.
+        '';
+      };
+
+      jsonJobs = mkOption {
+        default = [ ];
+        type = types.listOf types.str;
+        example = literalExample ''
+          [
+            '''
+              [ { "job":
+                  { "name": "jenkins-job-test-2",
+                    "builders": [ "shell": "echo 'Hello world!'" ]
+                  }
+                }
+              ]
+            '''
+          ]
+        '';
+        description = ''
+          Job descriptions for Jenkins Job Builder in JSON format.
+        '';
+      };
+
+      nixJobs = mkOption {
+        default = [ ];
+        type = types.listOf types.attrs;
+        example = literalExample ''
+          [ { job =
+              { name = "jenkins-job-test-3";
+                builders = [
+                  { shell = "echo 'Hello world!'"; }
+                ];
+              };
+            }
+          ];
+        '';
+        description = ''
+          Job descriptions for Jenkins Job Builder in Nix format.
+
+          This is a trivial wrapper around jsonJobs, using builtins.toJSON
+          behind the scene.
+        '';
+      };
+    };
+  };
+
+  config = mkIf (jenkinsCfg.enable && cfg.enable) {
+    systemd.services.jenkins-job-builder = {
+      description = "Jenkins Job Builder Service";
+      # JJB can run either before or after jenkins. We chose after, so we can
+      # always use curl to notify (running) jenkins to reload its config.
+      after = [ "jenkins.service" ];
+      wantedBy = [ "multi-user.target" ];
+
+      path = with pkgs; [ jenkins-job-builder curl ];
+
+      # Q: Why manipulate files directly instead of using "jenkins-jobs upload [...]"?
+      # A: Because this module is for administering a local jenkins install,
+      #    and using local file copy allows us to not worry about
+      #    authentication.
+      script =
+        let
+          yamlJobsFile = builtins.toFile "jobs.yaml" cfg.yamlJobs;
+          jsonJobsFiles =
+            map (x: (builtins.toFile "jobs.json" x))
+              (cfg.jsonJobs ++ [(builtins.toJSON cfg.nixJobs)]);
+          jobBuilderOutputDir = "/run/jenkins-job-builder/output";
+          # Stamp file is placed in $JENKINS_HOME/jobs/$JOB_NAME/ to indicate
+          # ownership. Enables tracking and removal of stale jobs.
+          ownerStamp = ".config-xml-managed-by-nixos-jenkins-job-builder";
+        in
+          ''
+            rm -rf ${jobBuilderOutputDir}
+            cur_decl_jobs=/run/jenkins-job-builder/declarative-jobs
+            rm -f "$cur_decl_jobs"
+
+            # Create / update jobs
+            mkdir -p ${jobBuilderOutputDir}
+            for inputFile in ${yamlJobsFile} ${concatStringsSep " " jsonJobsFiles}; do
+                HOME="${jenkinsCfg.home}" "${pkgs.jenkins-job-builder}/bin/jenkins-jobs" --ignore-cache test -o "${jobBuilderOutputDir}" "$inputFile"
+            done
+
+            for file in "${jobBuilderOutputDir}/"*; do
+                test -f "$file" || continue
+                jobname="$(basename $file)"
+                jobdir="${jenkinsCfg.home}/jobs/$jobname"
+                echo "Creating / updating job \"$jobname\""
+                mkdir -p "$jobdir"
+                touch "$jobdir/${ownerStamp}"
+                cp "$file" "$jobdir/config.xml"
+                echo "$jobname" >> "$cur_decl_jobs"
+            done
+
+            # Remove stale jobs
+            for file in "${jenkinsCfg.home}"/jobs/*/${ownerStamp}; do
+                test -f "$file" || continue
+                jobdir="$(dirname $file)"
+                jobname="$(basename "$jobdir")"
+                grep --quiet --line-regexp "$jobname" "$cur_decl_jobs" 2>/dev/null && continue
+                echo "Deleting stale job \"$jobname\""
+                rm -rf "$jobdir"
+            done
+
+            echo "Asking Jenkins to reload config"
+            curl --silent -X POST http://localhost:${toString jenkinsCfg.port}/reload
+          '';
+      serviceConfig = {
+        User = jenkinsCfg.user;
+        RuntimeDirectory = "jenkins-job-builder";
+      };
+    };
+  };
+}
diff --git a/nixos/modules/services/databases/postgresql.nix b/nixos/modules/services/databases/postgresql.nix
index bae088c6610e..16e3235eb2c8 100644
--- a/nixos/modules/services/databases/postgresql.nix
+++ b/nixos/modules/services/databases/postgresql.nix
@@ -119,7 +119,7 @@ in
       extraPlugins = mkOption {
         type = types.listOf types.path;
         default = [];
-        example = literalExample "pkgs.postgis";
+        example = literalExample "[ (pkgs.postgis.override { postgresql = pkgs.postgresql94; }).v_2_1_4 ]";
         description = ''
           When this list contains elements a new store path is created.
           PostgreSQL and the elments are symlinked into it. Then pg_config,
@@ -202,6 +202,8 @@ in
                   # For non-root operation.
                   initdb
                 fi
+                # See postStart!
+                touch "${cfg.dataDir}/.first_startup"
             fi
 
             ln -sfn "${configFile}" "${cfg.dataDir}/postgresql.conf"
diff --git a/nixos/modules/services/hardware/actkbd.nix b/nixos/modules/services/hardware/actkbd.nix
index 82de362c371b..b16a8f50a3d8 100644
--- a/nixos/modules/services/hardware/actkbd.nix
+++ b/nixos/modules/services/hardware/actkbd.nix
@@ -125,6 +125,9 @@ in
       };
     };
 
+    # For testing
+    environment.systemPackages = [ pkgs.actkbd ];
+
   };
 
 }
diff --git a/nixos/modules/services/hardware/tlp.nix b/nixos/modules/services/hardware/tlp.nix
index f221c82e2eda..23b6edcefd1a 100644
--- a/nixos/modules/services/hardware/tlp.nix
+++ b/nixos/modules/services/hardware/tlp.nix
@@ -6,9 +6,23 @@ let
 
 cfg = config.services.tlp;
 
-tlp = pkgs.tlp.override { kmod = config.system.sbin.modprobe; };
-
-confFile = pkgs.writeText "tlp" (builtins.readFile "${tlp}/etc/default/tlp" + cfg.extraConfig);
+enableRDW = config.networking.networkmanager.enable;
+
+tlp = pkgs.tlp.override {
+  inherit enableRDW;
+  kmod = config.system.sbin.modprobe;
+};
+
+# XXX: We can't use writeTextFile + readFile here because it triggers
+# TLP build to get the .drv (even on --dry-run).
+confFile = pkgs.runCommand "tlp"
+  { config = cfg.extraConfig;
+    passAsFile = [ "config" ];
+  }
+  ''
+    cat ${tlp}/etc/default/tlp > $out
+    cat $configPath >> $out
+  '';
 
 in
 
@@ -81,13 +95,15 @@ in
     environment.etc = [{ source = confFile;
                          target = "default/tlp";
                        }
-                      ] ++ optional tlp.enableRDW {
+                      ] ++ optional enableRDW {
                         source = "${tlp}/etc/NetworkManager/dispatcher.d/99tlp-rdw-nm";
                         target = "NetworkManager/dispatcher.d/99tlp-rdw-nm";
                       };
 
     environment.systemPackages = [ tlp ];
 
+    boot.kernelModules = [ "msr" ];
+
   };
 
 }
diff --git a/nixos/modules/services/mail/postfix.nix b/nixos/modules/services/mail/postfix.nix
index e8beba4b3586..3a9e62a02052 100644
--- a/nixos/modules/services/mail/postfix.nix
+++ b/nixos/modules/services/mail/postfix.nix
@@ -11,6 +11,8 @@ let
 
   mainCf =
     ''
+      compatibility_level = 2
+
       queue_directory = /var/postfix/queue
       command_directory = ${pkgs.postfix}/sbin
       daemon_directory = ${pkgs.postfix}/libexec/postfix
@@ -31,10 +33,7 @@ let
           mynetworks_style = ${cfg.networksStyle}
         ''
       else
-        # Postfix default is subnet, but let's play safe
-        ''
-          mynetworks_style = host
-        '')
+        "")
     + optionalString (cfg.hostname != "") ''
       myhostname = ${cfg.hostname}
     ''
@@ -89,7 +88,7 @@ let
   masterCf = ''
     # ==========================================================================
     # service type  private unpriv  chroot  wakeup  maxproc command + args
-    #               (yes)   (yes)   (yes)   (never) (100)
+    #               (yes)   (yes)   (no)    (never) (100)
     # ==========================================================================
     smtp      inet  n       -       n       -       -       smtpd
     #submission inet n       -       n       -       -       smtpd
@@ -232,8 +231,7 @@ in
         default = null;
         example = ["localdomain"];
         description = "
-          List of domains we agree to relay to. Default is the same as
-          destination.
+          List of domains we agree to relay to. Default is empty.
         ";
       };
 
@@ -357,32 +355,29 @@ in
         }
       ];
 
-    jobs.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.
+    systemd.services.postfix =
       { description = "Postfix mail server";
 
         wantedBy = [ "multi-user.target" ];
         after = [ "network.target" ];
 
-        daemonType = "fork";
+        serviceConfig = {
+          Type = "forking";
+          Restart = "always";
+          PIDFile = "/var/postfix/queue/pid/master.pid";
+        };
 
         preStart = ''
-          if ! [ -d /var/spool/postfix ]; then
-            ${pkgs.coreutils}/bin/mkdir -p /var/spool/mail /var/postfix/conf /var/postfix/queue
-          fi
+          ${pkgs.coreutils}/bin/mkdir -p /var/spool/mail /var/postfix/conf /var/postfix/queue
 
           ${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
-          ${pkgs.coreutils}/bin/ln -sf /var/spool/mail /var/mail
+          ${pkgs.coreutils}/bin/ln -sf /var/spool/mail /var/
 
-          ln -sf "${pkgs.postfix}/etc/postfix/"* /var/postfix/conf
+          ln -sf ${pkgs.postfix}/etc/postfix/postfix-files /var/postfix/conf
 
           ln -sf ${aliasesFile} /var/postfix/conf/aliases
           ln -sf ${virtualFile} /var/postfix/conf/virtual
@@ -391,12 +386,18 @@ in
 
           ${pkgs.postfix}/sbin/postalias -c /var/postfix/conf /var/postfix/conf/aliases
           ${pkgs.postfix}/sbin/postmap -c /var/postfix/conf /var/postfix/conf/virtual
+        '';
 
+        script = ''
           ${pkgs.postfix}/sbin/postfix -c /var/postfix/conf start
         '';
 
+        reload = ''
+          ${pkgs.postfix}/sbin/postfix -c /var/postfix/conf reload
+        '';
+
         preStop = ''
-            ${pkgs.postfix}/sbin/postfix -c /var/postfix/conf stop
+          ${pkgs.postfix}/sbin/postfix -c /var/postfix/conf stop
         '';
 
       };
diff --git a/nixos/modules/services/misc/autofs.nix b/nixos/modules/services/misc/autofs.nix
index f4a1059d09f0..b4dae79cf8a9 100644
--- a/nixos/modules/services/misc/autofs.nix
+++ b/nixos/modules/services/misc/autofs.nix
@@ -71,48 +71,17 @@ in
 
   config = mkIf cfg.enable {
 
-    environment.etc = singleton
-      { target = "auto.master";
-        source = pkgs.writeText "auto.master" cfg.autoMaster;
-      };
-
     boot.kernelModules = [ "autofs4" ];
 
-    jobs.autofs =
+    systemd.services.autofs =
       { description = "Filesystem automounter";
+        wantedBy = [ "multi-user.target" ];
+        after = [ "network.target" ];
 
-        startOn = "started network-interfaces";
-        stopOn = "stopping network-interfaces";
-
-        path = [ pkgs.nfs-utils pkgs.sshfsFuse ];
-
-        preStop =
-          ''
-            set -e; while :; do pkill -TERM automount; sleep 1; done
-          '';
-
-        # automount doesn't clean up when receiving SIGKILL.
-        # umount -l should unmount the directories recursively when they are no longer used
-        # It does, but traces are left in /etc/mtab. So unmount recursively..
-        postStop =
-          ''
-          PATH=${pkgs.gnused}/bin:${pkgs.coreutils}/bin
-          exec &> /tmp/logss
-          # double quote for sed:
-          escapeSpaces(){ sed 's/ /\\\\040/g'; }
-          unescapeSpaces(){ sed 's/\\040/ /g'; }
-          sed -n 's@^\s*\(\([^\\ ]\|\\ \)*\)\s.*@\1@p' ${autoMaster} | sed 's/[\\]//' | while read mountPoint; do
-            sed -n "s@[^ ]\+\s\+\($(echo "$mountPoint"| escapeSpaces)[^ ]*\).*@\1@p" /proc/mounts | sort -r | unescapeSpaces| while read smountP; do
-              ${pkgs.utillinux}/bin/umount -l "$smountP" || true
-            done
-          done
-          '';
-
-        script =
-          ''
-            ${if cfg.debug then "exec &> /var/log/autofs" else ""}
-            exec ${pkgs.autofs5}/sbin/automount ${if cfg.debug then "-d" else ""} -f -t ${builtins.toString cfg.timeout} "${autoMaster}" ${if cfg.debug then "-l7" else ""}
-          '';
+        serviceConfig = {
+          ExecStart = "${pkgs.autofs5}/sbin/automount ${if cfg.debug then "-d" else ""} -f -t ${builtins.toString cfg.timeout} ${autoMaster} ${if cfg.debug then "-l7" else ""}";
+          ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
+        };
       };
 
   };
diff --git a/nixos/modules/services/misc/calibre-server.nix b/nixos/modules/services/misc/calibre-server.nix
new file mode 100644
index 000000000000..a920aa22ccdf
--- /dev/null
+++ b/nixos/modules/services/misc/calibre-server.nix
@@ -0,0 +1,63 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+  cfg = config.services.calibre-server;
+
+in
+
+{
+
+  ###### interface
+
+  options = {
+
+    services.calibre-server = {
+
+      enable = mkEnableOption "calibre-server";
+
+      libraryDir = mkOption {
+        description = ''
+          The directory where the Calibre library to serve is.
+          '';
+          type = types.path;
+      };
+
+    };
+
+  };
+
+
+  ###### implementation
+
+  config = mkIf cfg.enable {
+
+    systemd.services.calibre-server =
+      {
+        description = "Calibre Server";
+        after = [ "network.target" ];
+        wantedBy = [ "multi-user.target" ];
+        serviceConfig = {
+          User = "calibre-server";
+          Restart = "always";
+          ExecStart = "${pkgs.calibre}/bin/calibre-server --with-library=${cfg.libraryDir}";
+        };
+
+      };
+
+    environment.systemPackages = [ pkgs.calibre ];
+
+    users.extraUsers.calibre-server = {
+        uid = config.ids.uids.calibre-server;
+        group = "calibre-server";
+      };
+
+    users.extraGroups.calibre-server = {
+        gid = config.ids.gids.calibre-server;
+      };
+
+  };
+
+}
diff --git a/nixos/modules/services/misc/ihaskell.nix b/nixos/modules/services/misc/ihaskell.nix
index 7f7f981de498..13c41466eab2 100644
--- a/nixos/modules/services/misc/ihaskell.nix
+++ b/nixos/modules/services/misc/ihaskell.nix
@@ -22,9 +22,9 @@ in
       };
 
       haskellPackages = mkOption {
-        default = pkgs.haskellngPackages;
-        defaultText = "pkgs.haskellngPackages";
-        example = literalExample "pkgs.haskell-ng.packages.ghc784";
+        default = pkgs.haskellPackages;
+        defaultText = "pkgs.haskellPackages";
+        example = literalExample "pkgs.haskell.packages.ghc784";
         description = ''
           haskellPackages used to build IHaskell and other packages.
           This can be used to change the GHC version used to build
diff --git a/nixos/modules/services/misc/nixos-manual.nix b/nixos/modules/services/misc/nixos-manual.nix
index c10d8197686f..7534eb0ae6a3 100644
--- a/nixos/modules/services/misc/nixos-manual.nix
+++ b/nixos/modules/services/misc/nixos-manual.nix
@@ -92,7 +92,9 @@ in
 
     system.build.manual = manual;
 
-    environment.systemPackages = [ manual.manpages manual.manual help ];
+    environment.systemPackages =
+      [ manual.manual help ]
+      ++ optional config.programs.man.enable manual.manpages;
 
     boot.extraTTYs = mkIf cfg.showManual ["tty${cfg.ttyNumber}"];
 
diff --git a/nixos/modules/services/misc/parsoid.nix b/nixos/modules/services/misc/parsoid.nix
index 0844190a5490..ea97d6e30e83 100644
--- a/nixos/modules/services/misc/parsoid.nix
+++ b/nixos/modules/services/misc/parsoid.nix
@@ -91,7 +91,7 @@ in
       wantedBy = [ "multi-user.target" ];
       after = [ "network.target" ];
       serviceConfig = {
-        ExecStart = "${pkgs.nodePackages.parsoid}/lib/node_modules/parsoid/api/server.js -c ${confFile} -n ${toString cfg.workers}";
+        ExecStart = "${pkgs.nodePackages_0_10.parsoid}/lib/node_modules/parsoid/api/server.js -c ${confFile} -n ${toString cfg.workers}";
       };
     };
 
diff --git a/nixos/modules/services/misc/synergy.nix b/nixos/modules/services/misc/synergy.nix
index 054df965347d..7e8eadbe5f37 100644
--- a/nixos/modules/services/misc/synergy.nix
+++ b/nixos/modules/services/misc/synergy.nix
@@ -89,6 +89,7 @@ in
         wantedBy = optional cfgC.autoStart "multi-user.target";
         path = [ pkgs.synergy ];
         serviceConfig.ExecStart = ''${pkgs.synergy}/bin/synergyc -f ${optionalString (cfgC.screenName != "") "-n ${cfgC.screenName}"} ${cfgC.serverAddress}'';
+        serviceConfig.Restart = "on-failure";
       };
     })
     (mkIf cfgS.enable {
@@ -98,6 +99,7 @@ in
         wantedBy = optional cfgS.autoStart "multi-user.target";
         path = [ pkgs.synergy ];
         serviceConfig.ExecStart = ''${pkgs.synergy}/bin/synergys -c ${cfgS.configFile} -f ${optionalString (cfgS.address != "") "-a ${cfgS.address}"} ${optionalString (cfgS.screenName != "") "-n ${cfgS.screenName}" }'';
+        serviceConfig.Restart = "on-failure";
       };
     })
   ];
diff --git a/nixos/modules/services/monitoring/bosun.nix b/nixos/modules/services/monitoring/bosun.nix
index 7e8dea4ec024..ebe4741f01bd 100644
--- a/nixos/modules/services/monitoring/bosun.nix
+++ b/nixos/modules/services/monitoring/bosun.nix
@@ -9,7 +9,7 @@ let
     tsdbHost = ${cfg.opentsdbHost}
     httpListen = ${cfg.listenAddress}
     stateFile = ${cfg.stateFile}
-    checkFrequency = 5m
+    checkFrequency = ${cfg.checkFrequency}
 
     ${cfg.extraConfig}
   '';
@@ -77,6 +77,14 @@ in {
         '';
       };
 
+      checkFrequency = mkOption {
+        type = types.str;
+        default = "5m";
+        description = ''
+          Bosun's check frequency
+        '';
+      };
+
       extraConfig = mkOption {
         type = types.string;
         default = "";
diff --git a/nixos/modules/services/monitoring/grafana.nix b/nixos/modules/services/monitoring/grafana.nix
index fa653565a67f..5302728eae91 100644
--- a/nixos/modules/services/monitoring/grafana.nix
+++ b/nixos/modules/services/monitoring/grafana.nix
@@ -318,7 +318,7 @@ in {
       wantedBy = ["multi-user.target"];
       after = ["networking.target"];
       serviceConfig = {
-        ExecStart = "${cfg.package-backend}/bin/grafana --config ${cfgFile} web";
+        ExecStart = "${cfg.package}/bin/grafana --config ${cfgFile} web";
         WorkingDirectory = cfg.dataDir;
         User = "grafana";
       };
diff --git a/nixos/modules/services/monitoring/teamviewer.nix b/nixos/modules/services/monitoring/teamviewer.nix
index beba5dcd1b06..533f1ea6644b 100644
--- a/nixos/modules/services/monitoring/teamviewer.nix
+++ b/nixos/modules/services/monitoring/teamviewer.nix
@@ -29,6 +29,7 @@ in
 
       wantedBy = [ "graphical.target" ];
       after = [ "NetworkManager-wait-online.service" "network.target" ];
+      preStart = "mkdir -pv /var/tmp/teamviewer10/{logs,config}";
 
       serviceConfig = {
         Type = "forking";
diff --git a/nixos/modules/services/networking/asterisk.nix b/nixos/modules/services/networking/asterisk.nix
index b079cb227303..13617a1b6c58 100644
--- a/nixos/modules/services/networking/asterisk.nix
+++ b/nixos/modules/services/networking/asterisk.nix
@@ -201,6 +201,7 @@ in
         for d in '${varlibdir}' '${spooldir}' '${logdir}'; do
           # TODO: Make exceptions for /var directories that likely should be updated
           if [ ! -e "$d" ]; then
+            mkdir -p "$d"
             cp --recursive ${pkgs.asterisk}/"$d" "$d"
             chown --recursive ${asteriskUser} "$d"
             find "$d" -type d | xargs chmod 0755
diff --git a/nixos/modules/services/networking/autossh.nix b/nixos/modules/services/networking/autossh.nix
new file mode 100644
index 000000000000..9ea17469870d
--- /dev/null
+++ b/nixos/modules/services/networking/autossh.nix
@@ -0,0 +1,114 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+  cfg = config.services.autossh;
+
+in
+
+{
+
+  ###### interface
+
+  options = {
+
+    services.autossh = {
+
+      sessions = mkOption {
+        type = types.listOf (types.submodule {
+          options = {
+            name = mkOption {
+              type = types.string;
+              example = "socks-peer";
+              description = "Name of the local AutoSSH session";
+            };
+            user = mkOption {
+              type = types.string;
+              example = "bill";
+              description = "Name of the user the AutoSSH session should run as";
+            };
+            monitoringPort = mkOption {
+              type = types.int;
+              default = 0;
+              example = 20000;
+              description = ''
+                Port to be used by AutoSSH for peer monitoring. Note, that
+                AutoSSH also uses mport+1. Value of 0 disables the keep-alive
+                style monitoring
+              '';
+            };
+            extraArguments = mkOption {
+              type = types.string;
+              example = "-N -D4343 bill@socks.example.net";
+              description = ''
+                Arguments to be passed to AutoSSH and retransmitted to SSH
+                process. Some meaningful options include -N (don't run remote
+                command), -D (open SOCKS proxy on local port), -R (forward
+                remote port), -L (forward local port), -v (Enable debug). Check
+                ssh manual for the complete list.
+              '';
+            };
+          };
+        });
+
+        default = [];
+        description = ''
+          List of AutoSSH sessions to start as systemd services. Each service is
+          named 'autossh-{session.name}'.
+        '';
+
+        example = [
+          {
+            name="socks-peer";
+            user="bill";
+            monitoringPort = 20000;
+            extraArguments="-N -D4343 billremote@socks.host.net";
+          }
+        ];
+
+      };
+    };
+
+  };
+
+  ###### implementation
+
+  config = mkIf (cfg.sessions != []) {
+
+    systemd.services =
+
+      lib.fold ( s : acc : acc //
+        {
+          "autossh-${s.name}" =
+            let
+              mport = if s ? monitoringPort then s.monitoringPort else 0;
+            in
+            {
+              description = "AutoSSH session (" + s.name + ")";
+
+              after = [ "network.target" ];
+              wantedBy = [ "multi-user.target" ];
+
+              # To be able to start the service with no network connection
+              environment.AUTOSSH_GATETIME="0";
+
+              # How often AutoSSH checks the network, in seconds
+              environment.AUTOSSH_POLL="30";
+
+              serviceConfig = {
+                  User = "${s.user}";
+                  PermissionsStartOnly = true;
+                  # AutoSSH may exit with 0 code if the SSH session was
+                  # gracefully terminated by either local or remote side.
+                  Restart = "on-success";
+                  ExecStart = "${pkgs.autossh}/bin/autossh -M ${toString mport} ${s.extraArguments}";
+              };
+            };
+        }) {} cfg.sessions;
+
+    environment.systemPackages = [ pkgs.autossh ];
+
+  };
+}
diff --git a/nixos/modules/services/networking/copy-com.nix b/nixos/modules/services/networking/copy-com.nix
index 69a41ab97963..ee0d043d471b 100644
--- a/nixos/modules/services/networking/copy-com.nix
+++ b/nixos/modules/services/networking/copy-com.nix
@@ -39,7 +39,8 @@ in
 
     systemd.services."copy-com-${cfg.user}" = {
       description = "Copy.com client";
-      after = [ "network.target" "local-fs.target" ];
+      wants = [ "network-online.target" ];
+      after = [ "network-online.target" "local-fs.target" ];
       wantedBy = [ "multi-user.target" ];
       serviceConfig = {
         ExecStart = "${pkgs.copy-com}/bin/CopyConsole ${if cfg.debug then "-consoleOutput -debugToConsole=dirwatch,path-watch,csm_path,csm -debug -console" else ""}";
diff --git a/nixos/modules/services/networking/networkmanager.nix b/nixos/modules/services/networking/networkmanager.nix
index 8370eca21e52..7df194fa419b 100644
--- a/nixos/modules/services/networking/networkmanager.nix
+++ b/nixos/modules/services/networking/networkmanager.nix
@@ -6,16 +6,18 @@ with lib;
 let
   cfg = config.networking.networkmanager;
 
-  stateDirs = "/var/lib/NetworkManager /var/lib/dhclient";
+  # /var/lib/misc is for dnsmasq.leases.
+  stateDirs = "/var/lib/NetworkManager /var/lib/dhclient /var/lib/misc";
 
   configFile = writeText "NetworkManager.conf" ''
     [main]
     plugins=keyfile
 
     [keyfile]
-    ${optionalString (config.networking.hostName != "") ''
-      hostname=${config.networking.hostName}
-    ''}
+    ${optionalString (config.networking.hostName != "")
+      ''hostname=${config.networking.hostName}''}
+    ${optionalString (cfg.unmanaged != [])
+      ''unmanaged-devices=${lib.concatStringsSep ";" cfg.unmanaged}''}
 
     [logging]
     level=WARN
@@ -40,7 +42,6 @@ let
     polkit.addRule(function(action, subject) {
       if (
         subject.isInGroup("networkmanager")
-        && subject.active
         && (action.id.indexOf("org.freedesktop.NetworkManager.") == 0
             || action.id.indexOf("org.freedesktop.ModemManager")  == 0
         ))
@@ -97,6 +98,16 @@ in {
         '';
       };
 
+      unmanaged = mkOption {
+        type = types.listOf types.string;
+        default = [];
+        description = ''
+          List of interfaces that will not be managed by NetworkManager.
+          Interface name can be specified here, but if you need more fidelity
+          see "Device List Format" in NetworkManager.conf man page.
+        '';
+      };
+
       # Ugly hack for using the correct gnome3 packageSet
       basePackages = mkOption {
         type = types.attrsOf types.path;
@@ -206,10 +217,16 @@ in {
 
     environment.systemPackages = cfg.packages;
 
-    users.extraGroups = singleton {
+    users.extraGroups = [{
       name = "networkmanager";
       gid = config.ids.gids.networkmanager;
-    };
+    }
+    {
+      name = "nm-openvpn";
+    }];
+    users.extraUsers = [{
+      name = "nm-openvpn";
+    }];
 
     systemd.packages = cfg.packages;
 
diff --git a/nixos/modules/services/networking/quassel.nix b/nixos/modules/services/networking/quassel.nix
index 005eb7bd7614..52c7ac8e6893 100644
--- a/nixos/modules/services/networking/quassel.nix
+++ b/nixos/modules/services/networking/quassel.nix
@@ -23,11 +23,11 @@ in
         '';
       };
 
-      interface = mkOption {
-        default = "127.0.0.1";
+      interfaces = mkOption {
+        default = [ "127.0.0.1" ];
         description = ''
-          The interface the Quassel daemon 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
+          The interfaces the Quassel daemon 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.
         '';
       };
@@ -78,7 +78,8 @@ in
       { description = "Quassel IRC client daemon";
 
         wantedBy = [ "multi-user.target" ];
-        after = [ "network.target" ];
+        after = [ "network.target" ] ++ optional config.services.postgresql.enable "postgresql.service"
+                                     ++ optional config.services.mysql.enable "mysql.service";
 
         preStart = ''
           mkdir -p ${cfg.dataDir}
@@ -87,7 +88,7 @@ in
 
         serviceConfig =
         {
-          ExecStart = "${quassel}/bin/quasselcore --listen=${cfg.interface} --port=${toString cfg.portNumber} --configdir=${cfg.dataDir}";
+          ExecStart = "${quassel}/bin/quasselcore --listen=${concatStringsSep '','' cfg.interfaces} --port=${toString cfg.portNumber} --configdir=${cfg.dataDir}";
           User = user;
           PermissionsStartOnly = true;
         };
diff --git a/nixos/modules/services/networking/supplicant.nix b/nixos/modules/services/networking/supplicant.nix
new file mode 100644
index 000000000000..502a0468787f
--- /dev/null
+++ b/nixos/modules/services/networking/supplicant.nix
@@ -0,0 +1,249 @@
+{ config, lib, utils, pkgs, ... }:
+
+with lib;
+
+let
+
+  cfg = config.networking.supplicant;
+
+  # We must escape interfaces due to the systemd interpretation
+  subsystemDevice = interface:
+    "sys-subsystem-net-devices-${utils.escapeSystemdPath interface}.device";
+
+  serviceName = iface: "supplicant-${if (iface=="WLAN") then "wlan@" else (
+                                     if (iface=="LAN") then "lan@" else (
+                                     if (iface=="DBUS") then "dbus"
+                                     else (replaceChars [" "] ["-"] iface)))}";
+
+  # TODO: Use proper privilege separation for wpa_supplicant
+  supplicantService = iface: suppl:
+    let
+      deps = (if (iface=="WLAN"||iface=="LAN") then ["sys-subsystem-net-devices-%i.device"] else (
+             if (iface=="DBUS") then ["dbus.service"]
+             else (map subsystemDevice (splitString " " iface))))
+             ++ optional (suppl.bridge!="") (subsystemDevice suppl.bridge);
+
+      ifaceArg = concatStringsSep " -N " (map (i: "-i${i}") (splitString " " iface));
+      driverArg = optionalString (suppl.driver != null) "-D${suppl.driver}";
+      bridgeArg = optionalString (suppl.bridge!="") "-b${suppl.bridge}";
+      confFileArg = optionalString (suppl.configFile.path!=null) "-c${suppl.configFile.path}";
+      extraConfFile = pkgs.writeText "supplicant-extra-conf-${replaceChars [" "] ["-"] iface}" ''
+        ${optionalString suppl.userControlled.enable "ctrl_interface=DIR=${suppl.userControlled.socketDir} GROUP=${suppl.userControlled.group}"}
+        ${optionalString suppl.configFile.writable "update_config=1"}
+        ${suppl.extraConf}
+      '';
+    in
+      { description = "Supplicant ${iface}${optionalString (iface=="WLAN"||iface=="LAN") " %I"}";
+        wantedBy = [ "network.target" ];
+        bindsTo = deps;
+        after = deps;
+        before = [ "network.target" ];
+        # Receive restart event after resume
+        partOf = [ "post-resume.target" ];
+
+        path = [ pkgs.coreutils ];
+
+        preStart = ''
+          ${optionalString (suppl.configFile.path!=null) ''
+            touch -a ${suppl.configFile.path}
+            chmod 600 ${suppl.configFile.path}
+          ''}
+          ${optionalString suppl.userControlled.enable ''
+            if ! test -e ${suppl.userControlled.socketDir}; then
+                mkdir -m 0770 -p ${suppl.userControlled.socketDir}
+                chgrp ${suppl.userControlled.group} ${suppl.userControlled.socketDir}
+            fi
+
+            if test "$(stat --printf '%G' ${suppl.userControlled.socketDir})" != "${suppl.userControlled.group}"; then
+                echo "ERROR: bad ownership on ${suppl.userControlled.socketDir}" >&2
+                exit 1
+            fi
+          ''}
+        '';
+
+        serviceConfig.ExecStart = "${pkgs.wpa_supplicant}/bin/wpa_supplicant -s ${driverArg} ${confFileArg} -I${extraConfFile} ${bridgeArg} ${suppl.extraCmdArgs} ${if (iface=="WLAN"||iface=="LAN") then "-i%I" else (if (iface=="DBUS") then "-u" else ifaceArg)}";
+
+      };
+
+
+in
+
+{
+
+  ###### interface
+
+  options = {
+
+    networking.supplicant = mkOption {
+      type = types.attrsOf types.optionSet;
+
+      default = { };
+
+      example = {
+        "wlan0 wlan1" = {
+          configFile = "/etc/wpa_supplicant";
+          userControlled.group = "network";
+          extraConf = ''
+            ap_scan=1
+            p2p_disabled=1
+          '';
+          extraCmdArgs = "-u -W";
+          bridge = "br0";
+        };
+      };
+
+      description = ''
+        Interfaces for which to start <command>wpa_supplicant</command>.
+        The supplicant is used to scan for and associate with wireless networks,
+        or to authenticate with 802.1x capable network switches.
+
+        The value of this option is an attribute set. Each attribute configures a
+        <command>wpa_supplicant</command> service, where the attribute name specifies
+        the name of the interface that <command>wpa_supplicant</command> operates on.
+        The attribute name can be a space separated list of interfaces.
+        The attribute names <literal>WLAN</literal>, <literal>LAN</literal> and <literal>DBUS</literal>
+        have a special meaning. <literal>WLAN</literal> and <literal>LAN</literal> are
+        configurations for universal <command>wpa_supplicant</command> service that is
+        started for each WLAN interface or for each LAN interface, respectively.
+        <literal>DBUS</literal> defines a device-unrelated <command>wpa_supplicant</command>
+        service that can be accessed through <literal>D-Bus</literal>.
+      '';
+
+      options = {
+
+        configFile = {
+
+          path = mkOption {
+            type = types.path;
+            example = "/etc/wpa_supplicant.conf";
+            description = ''
+              External <literal>wpa_supplicant.conf</literal> configuration file.
+              The configuration options defined declaratively within <literal>networking.supplicant</literal> have
+              precedence over options defined in <literal>configFile</literal>.
+            '';
+          };
+
+          writable = mkOption {
+            type = types.bool;
+            default = false;
+            description = ''
+              Whether the configuration file at <literal>configFile.path</literal> should be written to by
+              <literal>wpa_supplicant</literal>.
+            '';
+          };
+
+        };
+
+        extraConf = mkOption {
+          type = types.lines;
+          default = "";
+          example = ''
+            ap_scan=1
+            device_name=My-NixOS-Device
+            device_type=1-0050F204-1
+            driver_param=use_p2p_group_interface=1
+            disable_scan_offload=1
+            p2p_listen_reg_class=81
+            p2p_listen_channel=1
+            p2p_oper_reg_class=81
+            p2p_oper_channel=1
+            manufacturer=NixOS
+            model_name=NixOS_Unstable
+            model_number=2015
+          '';
+          description = ''
+            Configuration options for <literal>wpa_supplicant.conf</literal>.
+            Options defined here have precedence over options in <literal>configFile</literal>.
+            NOTE: Do not write sensitive data into <literal>extraConf</literal> as it will
+            be world-readable in the <literal>nix-store</literal>. For sensitive information
+            use the <literal>configFile</literal> instead.
+          '';
+        };
+
+        extraCmdArgs = mkOption {
+          type = types.str;
+          default = "";
+          example = "-e/var/run/wpa_supplicant/entropy.bin";
+          description =
+            "Command line arguments to add when executing <literal>wpa_supplicant</literal>.";
+        };
+
+        driver = mkOption {
+          type = types.nullOr types.str;
+          default = "nl80211,wext";
+          description = "Force a specific wpa_supplicant driver.";
+        };
+
+        bridge = mkOption {
+          type = types.str;
+          default = "";
+          description = "Name of the bridge interface that wpa_supplicant should listen at.";
+        };
+
+        userControlled = {
+
+          enable = mkOption {
+            type = types.bool;
+            default = false;
+            description = ''
+              Allow normal users to control wpa_supplicant through wpa_gui or wpa_cli.
+              This is useful for laptop users that switch networks a lot and don't want
+              to depend on a large package such as NetworkManager just to pick nearby
+              access points.
+            '';
+          };
+
+          socketDir = mkOption {
+            type = types.str;
+            default = "/var/run/wpa_supplicant";
+            description = "Directory of sockets for controlling wpa_supplicant.";
+          };
+
+          group = mkOption {
+            type = types.str;
+            default = "wheel";
+            example = "network";
+            description = "Members of this group can control wpa_supplicant.";
+          };
+
+        };
+
+      };
+
+    };
+
+  };
+
+
+  ###### implementation
+
+  config = mkIf (cfg != {}) {
+
+    environment.systemPackages =  [ pkgs.wpa_supplicant ];
+
+    services.dbus.packages = [ pkgs.wpa_supplicant ];
+
+    systemd.services = mapAttrs' (n: v: nameValuePair (serviceName n) (supplicantService n v)) cfg;
+
+    services.udev.packages = [
+      (pkgs.writeTextFile {
+        name = "99-zzz-60-supplicant.rules";
+        destination = "/etc/udev/rules.d/99-zzz-60-supplicant.rules";
+        text = ''
+          ${flip (concatMapStringsSep "\n") (filter (n: n!="WLAN" && n!="LAN" && n!="DBUS") (attrNames cfg)) (iface:
+            flip (concatMapStringsSep "\n") (splitString " " iface) (i: ''
+              ACTION=="add", SUBSYSTEM=="net", ENV{INTERFACE}=="${i}", TAG+="systemd", ENV{SYSTEMD_WANTS}+="supplicant-${replaceChars [" "] ["-"] iface}.service", TAG+="SUPPLICANT_ASSIGNED"''))}
+
+          ${optionalString (hasAttr "WLAN" cfg) ''
+            ACTION=="add", SUBSYSTEM=="net", ENV{DEVTYPE}=="wlan", TAG!="SUPPLICANT_ASSIGNED", TAG+="systemd", PROGRAM="${pkgs.systemd}/bin/systemd-escape -p %E{INTERFACE}", ENV{SYSTEMD_WANTS}+="supplicant-wlan@$result.service"
+          ''}
+          ${optionalString (hasAttr "LAN" cfg) ''
+            ACTION=="add", SUBSYSTEM=="net", ENV{DEVTYPE}=="lan", TAG!="SUPPLICANT_ASSIGNED", TAG+="systemd", PROGRAM="${pkgs.systemd}/bin/systemd-escape -p %E{INTERFACE}", ENV{SYSTEMD_WANTS}+="supplicant-lan@$result.service"
+          ''}
+        '';
+      })];
+
+  };
+
+}
+
diff --git a/nixos/modules/services/networking/tlsdated.nix b/nixos/modules/services/networking/tlsdated.nix
index f2d0c9f35c9c..ff7d0178a81a 100644
--- a/nixos/modules/services/networking/tlsdated.nix
+++ b/nixos/modules/services/networking/tlsdated.nix
@@ -63,7 +63,7 @@ in
         });
         default = [
           {
-            host = "www.ptb.de";
+            host = "encrypted.google.com";
             port = 443;
             proxy = null;
           }
diff --git a/nixos/modules/services/networking/wakeonlan.nix b/nixos/modules/services/networking/wakeonlan.nix
index 11bb7e925255..ebfba263cd8f 100644
--- a/nixos/modules/services/networking/wakeonlan.nix
+++ b/nixos/modules/services/networking/wakeonlan.nix
@@ -40,7 +40,7 @@ in
       ];
       description = ''
         Interfaces where to enable Wake-On-LAN, and how. Two methods available:
-        "magickey" and "password". The password has the shape of six bytes
+        "magicpacket" and "password". The password has the shape of six bytes
         in hexadecimal separated by a colon each. For more information,
         check the ethtool manual.
       '';
diff --git a/nixos/modules/services/scheduling/cron.nix b/nixos/modules/services/scheduling/cron.nix
index 02d80a77da50..1b5e83173e8f 100644
--- a/nixos/modules/services/scheduling/cron.nix
+++ b/nixos/modules/services/scheduling/cron.nix
@@ -100,7 +100,7 @@ in
       environment.systemPackages = [ cronNixosPkg ];
 
       environment.etc.crontab =
-        { source = pkgs.runCommand "crontabs" { inherit allFiles; }
+        { source = pkgs.runCommand "crontabs" { inherit allFiles; preferLocalBuild = true; }
             ''
               touch $out
               for i in $allFiles; do
diff --git a/nixos/modules/services/web-servers/lighttpd/default.nix b/nixos/modules/services/web-servers/lighttpd/default.nix
index 2c662c0aead9..171503db4eec 100644
--- a/nixos/modules/services/web-servers/lighttpd/default.nix
+++ b/nixos/modules/services/web-servers/lighttpd/default.nix
@@ -44,7 +44,6 @@ let
     "mod_flv_streaming"
     "mod_magnet"
     "mod_mysql_vhost"
-    "mod_rewrite"
     "mod_scgi"
     "mod_setenv"
     "mod_trigger_b4_dl"
diff --git a/nixos/modules/services/x11/desktop-managers/gnome3.nix b/nixos/modules/services/x11/desktop-managers/gnome3.nix
index 0fc255c4d64c..e32d6669b046 100644
--- a/nixos/modules/services/x11/desktop-managers/gnome3.nix
+++ b/nixos/modules/services/x11/desktop-managers/gnome3.nix
@@ -104,6 +104,7 @@ in {
 
     services.xserver.desktopManager.session = singleton
       { name = "gnome3";
+        bgSupport = true;
         start = ''
           # Set GTK_DATA_PREFIX so that GTK+ can find the themes
           export GTK_DATA_PREFIX=${config.system.path}
diff --git a/nixos/modules/services/x11/desktop-managers/kde5.nix b/nixos/modules/services/x11/desktop-managers/kde5.nix
index 5061d59b7c7f..6fdd5b4fa36d 100644
--- a/nixos/modules/services/x11/desktop-managers/kde5.nix
+++ b/nixos/modules/services/x11/desktop-managers/kde5.nix
@@ -8,38 +8,9 @@ let
   cfg = xcfg.desktopManager.kde5;
   xorg = pkgs.xorg;
 
-  phononBackends = {
-    gstreamer = [
-      pkgs.phonon_backend_gstreamer
-      pkgs.gst_all.gstreamer
-      pkgs.gst_all.gstPluginsBase
-      pkgs.gst_all.gstPluginsGood
-      pkgs.gst_all.gstPluginsUgly
-      pkgs.gst_all.gstPluginsBad
-      pkgs.gst_all.gstFfmpeg # for mp3 playback
-      pkgs.phonon_qt5_backend_gstreamer
-      pkgs.gst_all_1.gstreamer
-      pkgs.gst_all_1.gst-plugins-base
-      pkgs.gst_all_1.gst-plugins-good
-      pkgs.gst_all_1.gst-plugins-ugly
-      pkgs.gst_all_1.gst-plugins-bad
-      pkgs.gst_all_1.gst-libav # for mp3 playback
-    ];
-
-    vlc = [
-      pkgs.phonon_qt5_backend_vlc
-      pkgs.phonon_backend_vlc
-    ];
-  };
-
-  phononBackendPackages = flip concatMap cfg.phononBackends
-    (name: attrByPath [name] (throw "unknown phonon backend `${name}'") phononBackends);
-
   kf5 = pkgs.kf5_stable;
-
-  plasma5 = pkgs.plasma5_stable.override { inherit kf5; };
-
-  kdeApps = pkgs.kdeApps_stable.override { inherit kf5; };
+  plasma5 = pkgs.plasma5_stable;
+  kdeApps = pkgs.kdeApps_stable;
 
 in
 
@@ -53,14 +24,24 @@ in
         description = "Enable the Plasma 5 (KDE 5) desktop environment.";
       };
 
-      phononBackends = mkOption {
-        type = types.listOf types.str;
-        default = ["gstreamer"];
-        example = ["gstreamer" "vlc"];
-        description = ''
-          Phonon backends to use in KDE. Only the VLC and GStreamer backends are
-          available. The GStreamer backend is preferred by upstream.
-        '';
+      phonon = {
+
+        gstreamer = {
+          enable = mkOption {
+            type = types.bool;
+            default = true;
+            description = "Enable the GStreamer Phonon backend (recommended).";
+          };
+        };
+
+        vlc = {
+          enable = mkOption {
+            type = types.bool;
+            default = false;
+            description = "Enable the VLC Phonon backend.";
+          };
+        };
+
       };
 
     };
@@ -88,23 +69,77 @@ in
     };
 
     environment.systemPackages =
-      filter isDerivation (builtins.attrValues plasma5)
-      ++ filter isDerivation (builtins.attrValues kf5)
-      ++ [
+      [
         pkgs.qt4 # qtconfig is the only way to set Qt 4 theme
 
-        kdeApps.kde-baseapps
-        kdeApps.kde-base-artwork
-        kdeApps.kmix
+        kf5.frameworkintegration
+        kf5.kinit
+
+        plasma5.breeze
+        plasma5.kde-cli-tools
+        plasma5.kdeplasma-addons
+        plasma5.kgamma5
+        plasma5.khelpcenter
+        plasma5.khotkeys
+        plasma5.kinfocenter
+        plasma5.kmenuedit
+        plasma5.kscreen
+        plasma5.ksysguard
+        plasma5.kwayland
+        plasma5.kwin
+        plasma5.kwrited
+        plasma5.milou
+        plasma5.oxygen
+        plasma5.polkit-kde-agent
+        plasma5.systemsettings
+
+        plasma5.plasma-desktop
+        plasma5.plasma-workspace
+        plasma5.plasma-workspace-wallpapers
+
+        kdeApps.ark
+        kdeApps.dolphin
+        kdeApps.dolphin-plugins
+        kdeApps.ffmpegthumbs
+        kdeApps.gwenview
+        kdeApps.kate
+        kdeApps.kdegraphics-thumbnailers
         kdeApps.konsole
-        kdeApps.oxygen-icons
-
-        kdeApps.kde-runtime
+        kdeApps.okular
+        kdeApps.print-manager
 
+        kdeApps.oxygen-icons
         pkgs.hicolor_icon_theme
 
+        plasma5.kde-gtk-config
         pkgs.orion # GTK theme, nearly identical to Breeze
-      ] ++ phononBackendPackages;
+      ]
+      ++ lib.optional config.hardware.bluetooth.enable plasma5.bluedevil
+      ++ lib.optional config.networking.networkmanager.enable plasma5.plasma-nm
+      ++ lib.optional config.hardware.pulseaudio.enable plasma5.plasma-pa
+      ++ lib.optional config.powerManagement.enable plasma5.powerdevil
+      ++ lib.optionals cfg.phonon.gstreamer.enable
+        [
+          pkgs.phonon_backend_gstreamer
+          pkgs.gst_all.gstreamer
+          pkgs.gst_all.gstPluginsBase
+          pkgs.gst_all.gstPluginsGood
+          pkgs.gst_all.gstPluginsUgly
+          pkgs.gst_all.gstPluginsBad
+          pkgs.gst_all.gstFfmpeg # for mp3 playback
+          pkgs.phonon_qt5_backend_gstreamer
+          pkgs.gst_all_1.gstreamer
+          pkgs.gst_all_1.gst-plugins-base
+          pkgs.gst_all_1.gst-plugins-good
+          pkgs.gst_all_1.gst-plugins-ugly
+          pkgs.gst_all_1.gst-plugins-bad
+          pkgs.gst_all_1.gst-libav # for mp3 playback
+        ]
+      ++ lib.optionals cfg.phonon.vlc.enable
+        [
+          pkgs.phonon_qt5_backend_vlc
+          pkgs.phonon_backend_vlc
+        ];
 
     environment.pathsToLink = [ "/share" ];
 
@@ -114,7 +149,7 @@ in
     };
 
     environment.profileRelativeEnvVars =
-      mkIf (lib.elem "gstreamer" cfg.phononBackends)
+      mkIf cfg.phonon.gstreamer.enable
       {
         GST_PLUGIN_SYSTEM_PATH = [ "/lib/gstreamer-0.10" ];
         GST_PLUGIN_SYSTEM_PATH_1_0 = [ "/lib/gstreamer-1.0" ];
diff --git a/nixos/modules/services/x11/display-managers/gdm.nix b/nixos/modules/services/x11/display-managers/gdm.nix
index c9a563768323..58eb6f050131 100644
--- a/nixos/modules/services/x11/display-managers/gdm.nix
+++ b/nixos/modules/services/x11/display-managers/gdm.nix
@@ -20,7 +20,9 @@ in
 
       enable = mkEnableOption ''
         GDM as the display manager.
-        <emphasis>GDM is very experimental and may render system unusable.</emphasis>
+        <emphasis>GDM in NixOS is not well-tested with desktops other
+        than GNOME, so use with caution, as it could render the
+        system unusable.</emphasis>
       '';
 
       debug = mkEnableOption ''
diff --git a/nixos/modules/services/x11/display-managers/sddm.nix b/nixos/modules/services/x11/display-managers/sddm.nix
index 3f1d190ae66b..16a0d1b6d963 100644
--- a/nixos/modules/services/x11/display-managers/sddm.nix
+++ b/nixos/modules/services/x11/display-managers/sddm.nix
@@ -35,8 +35,23 @@ let
     SessionCommand=${dmcfg.session.script}
     SessionDir=${dmcfg.session.desktops}
     XauthPath=${pkgs.xorg.xauth}/bin/xauth
+
+    ${optionalString cfg.autoLogin.enable ''
+    [Autologin]
+    User=${cfg.autoLogin.user}
+    Session=${defaultSessionName}.desktop
+    Relogin=${if cfg.autoLogin.relogin then "true" else "false"}
+    ''}
+
+    ${cfg.extraConfig}
   '';
 
+  defaultSessionName =
+    let
+      dm = xcfg.desktopManager.default;
+      wm = xcfg.windowManager.default;
+    in dm + optionalString (wm != "none") (" + " + wm);
+
 in
 {
   options = {
@@ -50,6 +65,19 @@ in
         '';
       };
 
+      extraConfig = mkOption {
+        type = types.str;
+        default = "";
+        example = ''
+          [Autologin]
+          User=john
+          Session=plasma.desktop
+        '';
+        description = ''
+          Extra lines appended to the configuration of SDDM.
+        '';
+      };
+
       theme = mkOption {
         type = types.str;
         default = "maui";
@@ -57,12 +85,62 @@ in
           Greeter theme to use.
         '';
       };
+
+      autoLogin = mkOption {
+        default = {};
+        description = ''
+          Configuration for automatic login.
+        '';
+
+        type = types.submodule {
+	  options = {
+            enable = mkOption {
+              type = types.bool;
+              default = false;
+              description = ''
+                Automatically log in as the sepecified <option>autoLogin.user</option>.
+              '';
+            };
+
+            user = mkOption {
+              type = types.nullOr types.str;
+              default = null;
+              description = ''
+                User to be used for the autologin.
+              '';
+            };
+
+            relogin = mkOption {
+              type = types.bool;
+              default = false;
+              description = ''
+                If true automatic login will kick in again on session exit, otherwise it
+                will work only the first time.
+              '';
+            };
+	  };
+        };
+      };
+
     };
 
   };
 
   config = mkIf cfg.enable {
 
+    assertions = [
+      { assertion = cfg.autoLogin.enable -> cfg.autoLogin.user != null;
+        message = "SDDM auto-login requires services.xserver.displayManager.sddm.autoLogin.user to be set";
+      }
+      { assertion = cfg.autoLogin.enable -> elem defaultSessionName dmcfg.session.names;
+        message = ''
+          SDDM auto-login requires that services.xserver.desktopManager.default and
+	  services.xserver.windowMananger.default are set to valid values. The current
+	  default session: ${defaultSessionName} is not valid.
+	'';
+      }
+    ];
+
     services.xserver.displayManager.slim.enable = false;
 
     services.xserver.displayManager.job = {
@@ -93,6 +171,18 @@ in
         session  optional       pam_keyinit.so force revoke
         session  optional       pam_permit.so
       '';
+
+      sddm-autologin.text = ''
+        auth     requisite pam_nologin.so
+        auth     required  pam_succeed_if.so uid >= 1000 quiet
+        auth     required  pam_permit.so
+
+        account  include   sddm
+
+        password include   sddm
+
+        session  include   sddm
+      '';
     };
 
     users.extraUsers.sddm = {
diff --git a/nixos/modules/services/x11/redshift.nix b/nixos/modules/services/x11/redshift.nix
index ffae22d2d670..d40373ec2e55 100644
--- a/nixos/modules/services/x11/redshift.nix
+++ b/nixos/modules/services/x11/redshift.nix
@@ -22,14 +22,16 @@ in {
     latitude = mkOption {
       type = types.str;
       description = ''
-        Your current latitude.
+        Your current latitude, between
+        <literal>-90.0</literal> and <literal>90.0</literal>.
       '';
     };
 
     longitude = mkOption {
       type = types.str;
       description = ''
-        Your current longitude.
+        Your current longitude, between
+        between <literal>-180.0</literal> and <literal>180.0</literal>.
       '';
     };
 
@@ -38,14 +40,16 @@ in {
         type = types.int;
         default = 5500;
         description = ''
-          Colour temperature to use during the day.
+          Colour temperature to use during the day, between
+          <literal>1000</literal> and <literal>25000</literal> K.
         '';
       };
       night = mkOption {
         type = types.int;
         default = 3700;
         description = ''
-          Colour temperature to use at night.
+          Colour temperature to use at night, between
+          <literal>1000</literal> and <literal>25000</literal> K.
         '';
       };
     };
diff --git a/nixos/modules/services/x11/window-managers/clfswm.nix b/nixos/modules/services/x11/window-managers/clfswm.nix
new file mode 100644
index 000000000000..9d8eecb56c77
--- /dev/null
+++ b/nixos/modules/services/x11/window-managers/clfswm.nix
@@ -0,0 +1,31 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.services.xserver.windowManager.clfswm;
+in
+
+{
+  options = {
+    services.xserver.windowManager.clfswm = {
+      enable = mkOption {
+        type = types.bool;
+        default = false;
+        example = true;
+        description = "Enable the clfswm tiling window manager.";
+      };
+    };
+  };
+
+  config = mkIf cfg.enable {
+    services.xserver.windowManager.session = singleton {
+      name = "clfswm";
+      start = ''
+        ${pkgs.clfswm}/bin/clfswm &
+        waitPID=$!
+      '';
+    };
+    environment.systemPackages = [ pkgs.clfswm ];
+  };
+}
diff --git a/nixos/modules/services/x11/window-managers/default.nix b/nixos/modules/services/x11/window-managers/default.nix
index 4751de07a15d..31f42f5ffb9f 100644
--- a/nixos/modules/services/x11/window-managers/default.nix
+++ b/nixos/modules/services/x11/window-managers/default.nix
@@ -10,6 +10,7 @@ in
   imports = [
     ./afterstep.nix
     ./bspwm.nix
+    ./clfswm.nix
     ./compiz.nix
     ./fluxbox.nix
     ./herbstluftwm.nix
diff --git a/nixos/modules/services/x11/window-managers/xmonad.nix b/nixos/modules/services/x11/window-managers/xmonad.nix
index c922ca7848d1..288800d514d3 100644
--- a/nixos/modules/services/x11/window-managers/xmonad.nix
+++ b/nixos/modules/services/x11/window-managers/xmonad.nix
@@ -20,9 +20,9 @@ in
       };
 
       haskellPackages = mkOption {
-        default = pkgs.haskellngPackages;
-        defaultText = "pkgs.haskellngPackages";
-        example = literalExample "pkgs.haskell-ng.packages.ghc784";
+        default = pkgs.haskellPackages;
+        defaultText = "pkgs.haskellPackages";
+        example = literalExample "pkgs.haskell.packages.ghc784";
         description = ''
           haskellPackages used to build Xmonad and other packages.
           This can be used to change the GHC version used to build