summary refs log tree commit diff
path: root/nixos
diff options
context:
space:
mode:
Diffstat (limited to 'nixos')
-rw-r--r--nixos/doc/manual/configuration/adding-custom-packages.xml2
-rw-r--r--nixos/doc/manual/configuration/x-windows.xml1
-rw-r--r--nixos/doc/manual/development/sources.xml4
-rw-r--r--nixos/doc/manual/release-notes/rl-1809.xml29
-rw-r--r--nixos/modules/installer/tools/nixos-generate-config.pl7
-rw-r--r--nixos/modules/misc/ids.nix2
-rw-r--r--nixos/modules/module-list.nix2
-rw-r--r--nixos/modules/rename.nix1
-rw-r--r--nixos/modules/services/audio/mpd.nix4
-rw-r--r--nixos/modules/services/backup/restic.nix1
-rw-r--r--nixos/modules/services/databases/foundationdb.xml52
-rw-r--r--nixos/modules/services/misc/disnix.nix2
-rw-r--r--nixos/modules/services/misc/dysnomia.nix10
-rw-r--r--nixos/modules/services/misc/nix-daemon.nix10
-rw-r--r--nixos/modules/services/monitoring/graphite.nix34
-rw-r--r--nixos/modules/services/monitoring/netdata.nix4
-rw-r--r--nixos/modules/services/monitoring/prometheus/exporters.nix9
-rw-r--r--nixos/modules/services/networking/ocserv.nix99
-rw-r--r--nixos/modules/services/security/cfssl.nix209
-rw-r--r--nixos/modules/services/web-servers/hydron.nix66
-rw-r--r--nixos/modules/services/web-servers/meguca.nix81
-rw-r--r--nixos/modules/services/web-servers/tomcat.nix11
-rw-r--r--nixos/modules/services/x11/desktop-managers/default.nix12
-rw-r--r--nixos/modules/services/x11/desktop-managers/gnome3.nix54
-rw-r--r--nixos/modules/services/x11/display-managers/default.nix89
-rw-r--r--nixos/modules/services/x11/display-managers/gdm.nix4
-rw-r--r--nixos/modules/services/x11/display-managers/lightdm-greeters/gtk.nix2
-rw-r--r--nixos/modules/services/x11/display-managers/lightdm.nix14
-rw-r--r--nixos/modules/services/x11/display-managers/sddm.nix4
-rw-r--r--nixos/modules/services/x11/display-managers/slim.nix4
-rw-r--r--nixos/modules/system/boot/loader/systemd-boot/systemd-boot-builder.py1
-rw-r--r--nixos/modules/system/boot/loader/systemd-boot/systemd-boot.nix34
-rw-r--r--nixos/release.nix1
-rw-r--r--nixos/tests/acme.nix4
-rw-r--r--nixos/tests/cfssl.nix67
-rw-r--r--nixos/tests/containers-imperative.nix5
-rw-r--r--nixos/tests/gnome3.nix1
-rw-r--r--nixos/tests/graphite.nix5
-rw-r--r--nixos/tests/netdata.nix8
39 files changed, 749 insertions, 200 deletions
diff --git a/nixos/doc/manual/configuration/adding-custom-packages.xml b/nixos/doc/manual/configuration/adding-custom-packages.xml
index b59287a622e..028a9427534 100644
--- a/nixos/doc/manual/configuration/adding-custom-packages.xml
+++ b/nixos/doc/manual/configuration/adding-custom-packages.xml
@@ -14,7 +14,7 @@
 xlink:href="http://nixos.org/nixpkgs/manual">Nixpkgs
   manual</link>. In short, you clone Nixpkgs:
 <screen>
-$ git clone git://github.com/NixOS/nixpkgs.git
+$ git clone https://github.com/NixOS/nixpkgs
 $ cd nixpkgs
 </screen>
   Then you write and test the package as described in the Nixpkgs manual.
diff --git a/nixos/doc/manual/configuration/x-windows.xml b/nixos/doc/manual/configuration/x-windows.xml
index 9a0969ad635..948b35209b7 100644
--- a/nixos/doc/manual/configuration/x-windows.xml
+++ b/nixos/doc/manual/configuration/x-windows.xml
@@ -26,6 +26,7 @@
 <xref linkend="opt-services.xserver.desktopManager.plasma5.enable"/> = true;
 <xref linkend="opt-services.xserver.desktopManager.xfce.enable"/> = true;
 <xref linkend="opt-services.xserver.desktopManager.gnome3.enable"/> = true;
+<xref linkend="opt-services.xserver.desktopManager.mate.enable"/> = true;
 <xref linkend="opt-services.xserver.windowManager.xmonad.enable"/> = true;
 <xref linkend="opt-services.xserver.windowManager.twm.enable"/> = true;
 <xref linkend="opt-services.xserver.windowManager.icewm.enable"/> = true;
diff --git a/nixos/doc/manual/development/sources.xml b/nixos/doc/manual/development/sources.xml
index c7b64cb84be..eec9b56b1c0 100644
--- a/nixos/doc/manual/development/sources.xml
+++ b/nixos/doc/manual/development/sources.xml
@@ -11,9 +11,9 @@
   modify NixOS, however, you should check out the latest sources from Git. This
   is as follows:
 <screen>
-$ git clone git://github.com/NixOS/nixpkgs.git
+$ git clone https://github.com/NixOS/nixpkgs
 $ cd nixpkgs
-$ git remote add channels git://github.com/NixOS/nixpkgs-channels.git
+$ git remote add channels https://github.com/NixOS/nixpkgs-channels
 $ git remote update channels
 </screen>
   This will check out the latest Nixpkgs sources to
diff --git a/nixos/doc/manual/release-notes/rl-1809.xml b/nixos/doc/manual/release-notes/rl-1809.xml
index f03b1eab619..5a445e30ec6 100644
--- a/nixos/doc/manual/release-notes/rl-1809.xml
+++ b/nixos/doc/manual/release-notes/rl-1809.xml
@@ -75,12 +75,34 @@ $ nix-instantiate -E '(import &lt;nixpkgsunstable&gt; {}).gitFull'
   <itemizedlist>
    <listitem>
     <para>
+     There is a new <varname>services.foundationdb</varname> module for deploying
+     <link xlink:href="https://www.foundationdb.org">FoundationDB</link> clusters.
+    </para>
+   </listitem>
+   <listitem>
+    <para>
      When enabled the <literal>iproute2</literal> will copy the files expected
      by ip route (e.g., <filename>rt_tables</filename>) in
      <filename>/run/iproute2</filename>. This allows to write aliases for
      routing tables for instance.
     </para>
    </listitem>
+   <listitem>
+    <para>
+      <varname>services.strongswan-swanctl</varname>
+      is a modern replacement for <varname>services.strongswan</varname>.
+      You can use either one of them to setup IPsec VPNs but not both at the same time.
+    </para>
+    <para>
+      <varname>services.strongswan-swanctl</varname> uses the
+      <link xlink:href="https://wiki.strongswan.org/projects/strongswan/wiki/swanctl">swanctl</link>
+      command which uses the modern
+      <link xlink:href="https://github.com/strongswan/strongswan/blob/master/src/libcharon/plugins/vici/README.md">vici</link>
+      <emphasis>Versatile IKE Configuration Interface</emphasis>.
+      The deprecated <literal>ipsec</literal> command used in <varname>services.strongswan</varname> is using the legacy
+      <link xlink:href="https://github.com/strongswan/strongswan/blob/master/README_LEGACY.md">stroke configuration interface</link>.
+    </para>
+   </listitem>
   </itemizedlist>
  </section>
 
@@ -370,7 +392,12 @@ inherit (pkgs.nixos {
       <varname>s6-dns</varname>, <varname>s6-networking</varname>,
       <varname>s6-linux-utils</varname> and <varname>s6-portable-utils</varname> respectively.
     </para>
-   </listitem>
+  </listitem>
+  <listitem>
+    <para>
+      The module option <option>nix.useSandbox</option> is now defaulted to <literal>true</literal>.
+    </para>
+  </listitem>
   </itemizedlist>
  </section>
 </section>
diff --git a/nixos/modules/installer/tools/nixos-generate-config.pl b/nixos/modules/installer/tools/nixos-generate-config.pl
index cbe145d5a33..bb201d97ded 100644
--- a/nixos/modules/installer/tools/nixos-generate-config.pl
+++ b/nixos/modules/installer/tools/nixos-generate-config.pl
@@ -537,6 +537,13 @@ if ($showHardwareConfig) {
   boot.loader.systemd-boot.enable = true;
   boot.loader.efi.canTouchEfiVariables = true;
 EOF
+        } elsif (-e "/boot/extlinux") {
+            $bootLoaderConfig = <<EOF;
+  # Use the extlinux boot loader. (NixOS wants to enable GRUB by default)
+  boot.loader.grub.enable = false;
+  # Enables the generation of /boot/extlinux/extlinux.conf
+  boot.loader.generic-extlinux-compatible.enable = true;
+EOF
         } elsif ($virt ne "systemd-nspawn") {
             $bootLoaderConfig = <<EOF;
   # Use the GRUB 2 boot loader.
diff --git a/nixos/modules/misc/ids.nix b/nixos/modules/misc/ids.nix
index 782f6c8f69d..f73660ed99d 100644
--- a/nixos/modules/misc/ids.nix
+++ b/nixos/modules/misc/ids.nix
@@ -323,6 +323,7 @@
       mapred = 296;
       hadoop = 297;
       hydron = 298;
+      cfssl = 299;
 
       # When adding a uid, make sure it doesn't match an existing gid. And don't use uids above 399!
 
@@ -606,6 +607,7 @@
       mapred = 296;
       hadoop = 297;
       hydron = 298;
+      cfssl = 299;
 
       # When adding a gid, make sure it doesn't match an existing
       # uid. Users and groups with the same name should have equal
diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix
index e5dce84d6ee..5f96336de67 100644
--- a/nixos/modules/module-list.nix
+++ b/nixos/modules/module-list.nix
@@ -543,6 +543,7 @@
   ./services/networking/ntopng.nix
   ./services/networking/ntpd.nix
   ./services/networking/nylon.nix
+  ./services/networking/ocserv.nix
   ./services/networking/oidentd.nix
   ./services/networking/openfire.nix
   ./services/networking/openntpd.nix
@@ -621,6 +622,7 @@
   ./services/search/hound.nix
   ./services/search/kibana.nix
   ./services/search/solr.nix
+  ./services/security/cfssl.nix
   ./services/security/clamav.nix
   ./services/security/fail2ban.nix
   ./services/security/fprintd.nix
diff --git a/nixos/modules/rename.nix b/nixos/modules/rename.nix
index 40f66ccb26b..75f02ea78e6 100644
--- a/nixos/modules/rename.nix
+++ b/nixos/modules/rename.nix
@@ -9,7 +9,6 @@ with lib;
     (mkRenamedOptionModule [ "system" "nixos" "stateVersion" ] [ "system" "stateVersion" ])
     (mkRenamedOptionModule [ "system" "nixos" "defaultChannel" ] [ "system" "defaultChannel" ])
 
-    (mkRenamedOptionModule [ "dysnomia" ] [ "services" "dysnomia" ])
     (mkRenamedOptionModule [ "environment" "x11Packages" ] [ "environment" "systemPackages" ])
     (mkRenamedOptionModule [ "environment" "enableBashCompletion" ] [ "programs" "bash" "enableCompletion" ])
     (mkRenamedOptionModule [ "environment" "nix" ] [ "nix" "package" ])
diff --git a/nixos/modules/services/audio/mpd.nix b/nixos/modules/services/audio/mpd.nix
index 3add6556d0d..5bfe2b6a22a 100644
--- a/nixos/modules/services/audio/mpd.nix
+++ b/nixos/modules/services/audio/mpd.nix
@@ -55,11 +55,11 @@ in {
       };
 
       musicDirectory = mkOption {
-        type = types.path;
+        type = with types; either path (strMatching "(http|https|nfs|smb)://.+");
         default = "${cfg.dataDir}/music";
         defaultText = ''''${dataDir}/music'';
         description = ''
-          The directory where mpd reads music from.
+          The directory or NFS/SMB network share where mpd reads music from.
         '';
       };
 
diff --git a/nixos/modules/services/backup/restic.nix b/nixos/modules/services/backup/restic.nix
index 9b31ff3b582..6ece5a9b5ad 100644
--- a/nixos/modules/services/backup/restic.nix
+++ b/nixos/modules/services/backup/restic.nix
@@ -18,6 +18,7 @@ with lib;
 
         s3CredentialsFile = mkOption {
           type = with types; nullOr str;
+          default = null;
           description = ''
             file containing the AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY
             for an S3-hosted repository, in the format of an EnvironmentFile
diff --git a/nixos/modules/services/databases/foundationdb.xml b/nixos/modules/services/databases/foundationdb.xml
index 51fe9ae3f91..f4090c49276 100644
--- a/nixos/modules/services/databases/foundationdb.xml
+++ b/nixos/modules/services/databases/foundationdb.xml
@@ -12,12 +12,10 @@
 
 <para><emphasis>Maintainer:</emphasis> Austin Seipp</para>
 
-<para><emphasis>Available version(s):</emphasis> 5.1.x</para>
+<para><emphasis>Available version(s):</emphasis> 5.1.x, 5.2.x, 6.0.x</para>
 
-<para>FoundationDB (or "FDB") is a distributed, open source, high performance,
-transactional key-value store. It can store petabytes of data and deliver
-exceptional performance while maintaining consistency and ACID semantics
-(serializable transactions) over a large cluster.</para>
+<para>FoundationDB (or "FDB") is an open source, distributed, transactional
+key-value store.</para>
 
 <section><title>Configuring and basic setup</title>
 
@@ -26,12 +24,12 @@ exceptional performance while maintaining consistency and ACID semantics
 
 <programlisting>
 services.foundationdb.enable = true;
-services.foundationdb.package = pkgs.foundationdb51; # FoundationDB 5.1.x
+services.foundationdb.package = pkgs.foundationdb52; # FoundationDB 5.2.x
 </programlisting>
 </para>
 
 <para>The <option>services.foundationdb.package</option> option is required,
-and must always be specified. Because FoundationDB network protocols and
+and must always be specified. Due to the fact FoundationDB network protocols and
 on-disk storage formats may change between (major) versions, and upgrades must
 be explicitly handled by the user, you must always manually specify this
 yourself so that the NixOS module will use the proper version. Note that minor,
@@ -70,6 +68,40 @@ fdb>
 </programlisting>
 </para>
 
+<para>You can also write programs using the available client libraries.
+For example, the following Python program can be run in order to grab the
+cluster status, as a quick example. (This example uses
+<command>nix-shell</command> shebang support to automatically supply the
+necessary Python modules).
+
+<programlisting>
+a@link> cat fdb-status.py
+#! /usr/bin/env nix-shell
+#! nix-shell -i python -p python pythonPackages.foundationdb52
+
+import fdb
+import json
+
+def main():
+    fdb.api_version(520)
+    db = fdb.open()
+
+    @fdb.transactional
+    def get_status(tr):
+        return str(tr['\xff\xff/status/json'])
+
+    obj = json.loads(get_status(db))
+    print('FoundationDB available: %s' % obj['client']['database_status']['available'])
+
+if __name__ == "__main__":
+    main()
+a@link> chmod +x fdb-status.py
+a@link> ./fdb-status.py
+FoundationDB available: True
+a@link>
+</programlisting>
+</para>
+
 <para>FoundationDB is run under the <command>foundationdb</command> user and
 group by default, but this may be changed in the NixOS configuration. The
 systemd unit <command>foundationdb.service</command> controls the
@@ -295,7 +327,6 @@ only undergone fairly basic testing of all the available functionality.</para>
       individual <command>fdbserver</command> processes. Currently, all server
       processes inherit all the global <command>fdbmonitor</command> settings.
       </para></listitem>
-  <listitem><para>Python bindings are not currently installed.</para></listitem>
   <listitem><para>Ruby bindings are not currently installed.</para></listitem>
   <listitem><para>Go bindings are not currently installed.</para></listitem>
 </itemizedlist>
@@ -306,8 +337,9 @@ only undergone fairly basic testing of all the available functionality.</para>
 
 <para>NixOS's FoundationDB module allows you to configure all of the most
 relevant configuration options for <command>fdbmonitor</command>, matching it
-quite closely. For a complete list of all options, check <command>man
-configuration.nix</command>.</para>
+quite closely. A complete list of options for the FoundationDB module may be
+found <link linkend="opt-services.foundationdb.enable">here</link>. You should
+also read the FoundationDB documentation as well.</para>
 
 </section>
 
diff --git a/nixos/modules/services/misc/disnix.nix b/nixos/modules/services/misc/disnix.nix
index bb3ac1ecf07..c21cb2afc3c 100644
--- a/nixos/modules/services/misc/disnix.nix
+++ b/nixos/modules/services/misc/disnix.nix
@@ -47,7 +47,7 @@ in
   ###### implementation
 
   config = mkIf cfg.enable {
-    services.dysnomia.enable = true;
+    dysnomia.enable = true;
 
     environment.systemPackages = [ pkgs.disnix ] ++ optional cfg.useWebServiceInterface pkgs.DisnixWebService;
 
diff --git a/nixos/modules/services/misc/dysnomia.nix b/nixos/modules/services/misc/dysnomia.nix
index ba74b18b697..61ea822890e 100644
--- a/nixos/modules/services/misc/dysnomia.nix
+++ b/nixos/modules/services/misc/dysnomia.nix
@@ -3,7 +3,7 @@
 with lib;
 
 let
-  cfg = config.services.dysnomia;
+  cfg = config.dysnomia;
 
   printProperties = properties:
     concatMapStrings (propertyName:
@@ -69,7 +69,7 @@ let
 in
 {
   options = {
-    services.dysnomia = {
+    dysnomia = {
 
       enable = mkOption {
         type = types.bool;
@@ -142,7 +142,7 @@ in
 
     environment.systemPackages = [ cfg.package ];
 
-    services.dysnomia.package = pkgs.dysnomia.override (origArgs: {
+    dysnomia.package = pkgs.dysnomia.override (origArgs: {
       enableApacheWebApplication = config.services.httpd.enable;
       enableAxis2WebService = config.services.tomcat.axis2.enable;
       enableEjabberdDump = config.services.ejabberd.enable;
@@ -153,7 +153,7 @@ in
       enableMongoDatabase = config.services.mongodb.enable;
     });
 
-    services.dysnomia.properties = {
+    dysnomia.properties = {
       hostname = config.networking.hostName;
       inherit (config.nixpkgs.localSystem) system;
 
@@ -171,7 +171,7 @@ in
       }}");
     };
 
-    services.dysnomia.containers = lib.recursiveUpdate ({
+    dysnomia.containers = lib.recursiveUpdate ({
       process = {};
       wrapper = {};
     }
diff --git a/nixos/modules/services/misc/nix-daemon.nix b/nixos/modules/services/misc/nix-daemon.nix
index e64df8dc7d2..5ca879bf266 100644
--- a/nixos/modules/services/misc/nix-daemon.nix
+++ b/nixos/modules/services/misc/nix-daemon.nix
@@ -127,16 +127,16 @@ in
 
       useSandbox = mkOption {
         type = types.either types.bool (types.enum ["relaxed"]);
-        default = false;
+        default = true;
         description = "
           If set, Nix will perform builds in a sandboxed environment that it
           will set up automatically for each build. This prevents impurities
           in builds by disallowing access to dependencies outside of the Nix
           store by using network and mount namespaces in a chroot environment.
-          This isn't enabled by default for possible performance impacts due to
-          the initial setup time of a sandbox for each build. It doesn't affect
-          derivation hashes, so changing this option will not trigger a rebuild
-          of packages.
+          This is enabled by default even though it has a possible performance
+          impact due to the initial setup time of a sandbox for each build. It
+          doesn't affect derivation hashes, so changing this option will not
+          trigger a rebuild of packages.
         ";
       };
 
diff --git a/nixos/modules/services/monitoring/graphite.nix b/nixos/modules/services/monitoring/graphite.nix
index 7ad26c137e5..cdc98b407e9 100644
--- a/nixos/modules/services/monitoring/graphite.nix
+++ b/nixos/modules/services/monitoring/graphite.nix
@@ -57,12 +57,6 @@ let
     --nodaemon --syslog --prefix=${name} --pidfile /run/${name}/${name}.pid ${name}
   '';
 
-  mkPidFileDir = name: ''
-    mkdir -p /run/${name}
-    chmod 0700 /run/${name}
-    chown -R graphite:graphite /run/${name}
-  '';
-
   carbonEnv = {
     PYTHONPATH = let
       cenv = pkgs.python.buildEnv.override {
@@ -136,7 +130,7 @@ in {
       finders = mkOption {
         description = "List of finder plugins to load.";
         default = [];
-        example = literalExample "[ pkgs.python27Packages.graphite_influxdb ]";
+        example = literalExample "[ pkgs.python27Packages.influxgraph ]";
         type = types.listOf types.package;
       };
 
@@ -412,18 +406,16 @@ in {
         after = [ "network.target" ];
         environment = carbonEnv;
         serviceConfig = {
+          RuntimeDirectory = name;
           ExecStart = "${pkgs.pythonPackages.twisted}/bin/twistd ${carbonOpts name}";
           User = "graphite";
           Group = "graphite";
           PermissionsStartOnly = true;
           PIDFile="/run/${name}/${name}.pid";
         };
-        preStart = mkPidFileDir name + ''
-
-          mkdir -p ${cfg.dataDir}/whisper
-          chmod 0700 ${cfg.dataDir}/whisper
-          chown graphite:graphite ${cfg.dataDir}
-          chown graphite:graphite ${cfg.dataDir}/whisper
+        preStart = ''
+          install -dm0700 -o graphite -g graphite ${cfg.dataDir}
+          install -dm0700 -o graphite -g graphite ${cfg.dataDir}/whisper
         '';
       };
     })
@@ -436,12 +428,12 @@ in {
         after = [ "network.target" ];
         environment = carbonEnv;
         serviceConfig = {
+          RuntimeDirectory = name;
           ExecStart = "${pkgs.pythonPackages.twisted}/bin/twistd ${carbonOpts name}";
           User = "graphite";
           Group = "graphite";
           PIDFile="/run/${name}/${name}.pid";
         };
-        preStart = mkPidFileDir name;
       };
     })
 
@@ -452,12 +444,12 @@ in {
         after = [ "network.target" ];
         environment = carbonEnv;
         serviceConfig = {
+          RuntimeDirectory = name;
           ExecStart = "${pkgs.pythonPackages.twisted}/bin/twistd ${carbonOpts name}";
           User = "graphite";
           Group = "graphite";
           PIDFile="/run/${name}/${name}.pid";
         };
-        preStart = mkPidFileDir name;
       };
     })
 
@@ -485,7 +477,7 @@ in {
           PYTHONPATH = let
               penv = pkgs.python.buildEnv.override {
                 extraLibs = [
-                  pythonPackages.graphite_web
+                  pythonPackages.graphite-web
                   pythonPackages.pysqlite
                 ];
               };
@@ -524,16 +516,16 @@ in {
           fi
 
           # Only collect static files when graphite_web changes.
-          if ! [ "${dataDir}/current_graphite_web" -ef "${pythonPackages.graphite_web}" ]; then
+          if ! [ "${dataDir}/current_graphite_web" -ef "${pythonPackages.graphite-web}" ]; then
             mkdir -p ${staticDir}
             ${pkgs.pythonPackages.django_1_8}/bin/django-admin.py collectstatic  --noinput --clear
             chown -R graphite:graphite ${staticDir}
-            ln -sfT "${pythonPackages.graphite_web}" "${dataDir}/current_graphite_web"
+            ln -sfT "${pythonPackages.graphite-web}" "${dataDir}/current_graphite_web"
           fi
         '';
       };
 
-      environment.systemPackages = [ pythonPackages.graphite_web ];
+      environment.systemPackages = [ pythonPackages.graphite-web ];
     }))
 
     (mkIf cfg.api.enable {
@@ -607,7 +599,7 @@ in {
           GRAPHITE_URL = cfg.pager.graphiteUrl;
         };
         serviceConfig = {
-          ExecStart = "${pkgs.pythonPackages.graphite_pager}/bin/graphite-pager --config ${pagerConfig}";
+          ExecStart = "${pkgs.pythonPackages.graphitepager}/bin/graphite-pager --config ${pagerConfig}";
           User = "graphite";
           Group = "graphite";
         };
@@ -615,7 +607,7 @@ in {
 
       services.redis.enable = mkDefault true;
 
-      environment.systemPackages = [ pkgs.pythonPackages.graphite_pager ];
+      environment.systemPackages = [ pkgs.pythonPackages.graphitepager ];
     })
 
     (mkIf cfg.beacon.enable {
diff --git a/nixos/modules/services/monitoring/netdata.nix b/nixos/modules/services/monitoring/netdata.nix
index eefddf5a206..edcaa10d969 100644
--- a/nixos/modules/services/monitoring/netdata.nix
+++ b/nixos/modules/services/monitoring/netdata.nix
@@ -14,6 +14,10 @@ let
     global = {
       "plugins directory" = "${wrappedPlugins}/libexec/netdata/plugins.d ${pkgs.netdata}/libexec/netdata/plugins.d";
     };
+    web = {
+      "web files owner" = "root";
+      "web files group" = "root";
+    };
   };
   mkConfig = generators.toINI {} (recursiveUpdate localConfig cfg.config);
   configFile = pkgs.writeText "netdata.conf" (if cfg.configText != null then cfg.configText else mkConfig);
diff --git a/nixos/modules/services/monitoring/prometheus/exporters.nix b/nixos/modules/services/monitoring/prometheus/exporters.nix
index 9c58a15bcd7..1d5f400250f 100644
--- a/nixos/modules/services/monitoring/prometheus/exporters.nix
+++ b/nixos/modules/services/monitoring/prometheus/exporters.nix
@@ -73,7 +73,7 @@ let
       description = ''
         Specify a filter for iptables to use when
         <option>services.prometheus.exporters.${name}.openFirewall</option>
-        is true. It is used as `ip46tables -I INPUT <option>firewallFilter</option> -j ACCEPT`.
+        is true. It is used as `ip46tables -I nixos-fw <option>firewallFilter</option> -j nixos-fw-accept`.
       '';
     };
     user = mkOption {
@@ -116,9 +116,10 @@ let
 
   mkExporterConf = { name, conf, serviceOpts }:
     mkIf conf.enable {
-      networking.firewall.extraCommands = mkIf conf.openFirewall ''
-        ip46tables -I INPUT ${conf.firewallFilter} -j ACCEPT
-      '';
+      networking.firewall.extraCommands = mkIf conf.openFirewall (concatStrings [
+        "ip46tables -I nixos-fw ${conf.firewallFilter} "
+        "-m comment --comment ${name}-exporter -j nixos-fw-accept"
+      ]);
       systemd.services."prometheus-${name}-exporter" = mkMerge ([{
         wantedBy = [ "multi-user.target" ];
         after = [ "network.target" ];
diff --git a/nixos/modules/services/networking/ocserv.nix b/nixos/modules/services/networking/ocserv.nix
new file mode 100644
index 00000000000..61473a9fabf
--- /dev/null
+++ b/nixos/modules/services/networking/ocserv.nix
@@ -0,0 +1,99 @@
+{ config, pkgs, lib, ... }:
+
+with lib;
+
+let
+
+  cfg = config.services.ocserv;
+
+in
+
+{
+  options.services.ocserv = {
+    enable = mkEnableOption "ocserv";
+
+    config = mkOption {
+      type = types.lines;
+
+      description = ''
+        Configuration content to start an OCServ server.
+
+        For a full configuration reference,please refer to the online documentation
+        (https://ocserv.gitlab.io/www/manual.html), the openconnect
+        recipes (https://github.com/openconnect/recipes) or `man ocserv`.
+      '';
+
+      example = ''
+        # configuration examples from $out/doc without explanatory comments.
+        # for a full reference please look at the installed man pages.
+        auth = "plain[passwd=./sample.passwd]"
+        tcp-port = 443
+        udp-port = 443
+        run-as-user = nobody
+        run-as-group = nogroup
+        socket-file = /var/run/ocserv-socket
+        server-cert = certs/server-cert.pem
+        server-key = certs/server-key.pem
+        keepalive = 32400
+        dpd = 90
+        mobile-dpd = 1800
+        switch-to-tcp-timeout = 25
+        try-mtu-discovery = false
+        cert-user-oid = 0.9.2342.19200300.100.1.1
+        tls-priorities = "NORMAL:%SERVER_PRECEDENCE:%COMPAT:-VERS-SSL3.0"
+        auth-timeout = 240
+        min-reauth-time = 300
+        max-ban-score = 80
+        ban-reset-time = 1200
+        cookie-timeout = 300
+        deny-roaming = false
+        rekey-time = 172800
+        rekey-method = ssl
+        use-occtl = true
+        pid-file = /var/run/ocserv.pid
+        device = vpns
+        predictable-ips = true
+        default-domain = example.com
+        ipv4-network = 192.168.1.0
+        ipv4-netmask = 255.255.255.0
+        dns = 192.168.1.2
+        ping-leases = false
+        route = 10.10.10.0/255.255.255.0
+        route = 192.168.0.0/255.255.0.0
+        no-route = 192.168.5.0/255.255.255.0
+        cisco-client-compat = true
+        dtls-legacy = true
+
+        [vhost:www.example.com]
+        auth = "certificate"
+        ca-cert = certs/ca.pem
+        server-cert = certs/server-cert-secp521r1.pem
+        server-key = cersts/certs/server-key-secp521r1.pem
+        ipv4-network = 192.168.2.0
+        ipv4-netmask = 255.255.255.0
+        cert-user-oid = 0.9.2342.19200300.100.1.1
+      '';
+    };
+  };
+
+  config = mkIf cfg.enable {
+    environment.systemPackages = [ pkgs.ocserv ];
+    environment.etc."ocserv/ocserv.conf".text = cfg.config;
+
+    security.pam.services.ocserv = {};
+
+    systemd.services.ocserv = {
+      description = "OpenConnect SSL VPN server";
+      documentation = [ "man:ocserv(8)" ];
+      after = [ "dbus.service" "network-online.target" ];
+      wantedBy = [ "multi-user.target" ];
+
+      serviceConfig = {
+        PrivateTmp = true;
+        PIDFile = "/var/run/ocserv.pid";
+        ExecStart = "${pkgs.ocserv}/bin/ocserv --foreground --pid-file /var/run/ocesrv.pid --config /etc/ocserv/ocserv.conf";
+        ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
+      };
+    };
+  };
+}
diff --git a/nixos/modules/services/security/cfssl.nix b/nixos/modules/services/security/cfssl.nix
new file mode 100644
index 00000000000..1eb2f65ba60
--- /dev/null
+++ b/nixos/modules/services/security/cfssl.nix
@@ -0,0 +1,209 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.services.cfssl;
+in {
+  options.services.cfssl = {
+    enable = mkEnableOption "the CFSSL CA api-server";
+
+    dataDir = mkOption {
+      default = "/var/lib/cfssl";
+      type = types.path;
+      description = "Cfssl work directory.";
+    };
+
+    address = mkOption {
+      default = "127.0.0.1";
+      type = types.str;
+      description = "Address to bind.";
+    };
+
+    port = mkOption {
+      default = 8888;
+      type = types.ints.u16;
+      description = "Port to bind.";
+    };
+
+    ca = mkOption {
+      defaultText = "\${cfg.dataDir}/ca.pem";
+      type = types.str;
+      description = "CA used to sign the new certificate -- accepts '[file:]fname' or 'env:varname'.";
+    };
+
+    caKey = mkOption {
+      defaultText = "file:\${cfg.dataDir}/ca-key.pem";
+      type = types.str;
+      description = "CA private key -- accepts '[file:]fname' or 'env:varname'.";
+    };
+
+    caBundle = mkOption {
+      default = null;
+      type = types.nullOr types.path;
+      description = "Path to root certificate store.";
+    };
+
+    intBundle = mkOption {
+      default = null;
+      type = types.nullOr types.path;
+      description = "Path to intermediate certificate store.";
+    };
+
+    intDir = mkOption {
+      default = null;
+      type = types.nullOr types.path;
+      description = "Intermediates directory.";
+    };
+
+    metadata = mkOption {
+      default = null;
+      type = types.nullOr types.path;
+      description = ''
+        Metadata file for root certificate presence.
+        The content of the file is a json dictionary (k,v): each key k is
+        a SHA-1 digest of a root certificate while value v is a list of key
+        store filenames.
+      '';
+    };
+
+    remote = mkOption {
+      default = null;
+      type = types.nullOr types.str;
+      description = "Remote CFSSL server.";
+    };
+
+    configFile = mkOption {
+      default = null;
+      type = types.nullOr types.str;
+      description = "Path to configuration file. Do not put this in nix-store as it might contain secrets.";
+    };
+
+    responder = mkOption {
+      default = null;
+      type = types.nullOr types.path;
+      description = "Certificate for OCSP responder.";
+    };
+
+    responderKey = mkOption {
+      default = null;
+      type = types.nullOr types.str;
+      description = "Private key for OCSP responder certificate. Do not put this in nix-store.";
+    };
+
+    tlsKey = mkOption {
+      default = null;
+      type = types.nullOr types.str;
+      description = "Other endpoint's CA private key. Do not put this in nix-store.";
+    };
+
+    tlsCert = mkOption {
+      default = null;
+      type = types.nullOr types.path;
+      description = "Other endpoint's CA to set up TLS protocol.";
+    };
+
+    mutualTlsCa = mkOption {
+      default = null;
+      type = types.nullOr types.path;
+      description = "Mutual TLS - require clients be signed by this CA.";
+    };
+
+    mutualTlsCn = mkOption {
+      default = null;
+      type = types.nullOr types.str;
+      description = "Mutual TLS - regex for whitelist of allowed client CNs.";
+    };
+
+    tlsRemoteCa = mkOption {
+      default = null;
+      type = types.nullOr types.path;
+      description = "CAs to trust for remote TLS requests.";
+    };
+
+    mutualTlsClientCert = mkOption {
+      default = null;
+      type = types.nullOr types.path;
+      description = "Mutual TLS - client certificate to call remote instance requiring client certs.";
+    };
+
+    mutualTlsClientKey = mkOption {
+      default = null;
+      type = types.nullOr types.path;
+      description = "Mutual TLS - client key to call remote instance requiring client certs. Do not put this in nix-store.";
+    };
+
+    dbConfig = mkOption {
+      default = null;
+      type = types.nullOr types.path;
+      description = "Certificate db configuration file. Path must be writeable.";
+    };
+
+    logLevel = mkOption {
+      default = 1;
+      type = types.enum [ 0 1 2 3 4 5 ];
+      description = "Log level (0 = DEBUG, 5 = FATAL).";
+    };
+  };
+
+  config = {
+    users.extraGroups.cfssl = {
+      gid = config.ids.gids.cfssl;
+    };
+
+    users.extraUsers.cfssl = {
+      description = "cfssl user";
+      createHome = true;
+      home = cfg.dataDir;
+      group = "cfssl";
+      uid = config.ids.uids.cfssl;
+    };
+
+    systemd.services.cfssl = mkIf cfg.enable {
+      description = "CFSSL CA API server";
+      wantedBy = [ "multi-user.target" ];
+      after = [ "network.target" ];
+
+      serviceConfig = {
+        WorkingDirectory = cfg.dataDir;
+        StateDirectory = cfg.dataDir;
+        StateDirectoryMode = 700;
+        Restart = "always";
+        User = "cfssl";
+
+        ExecStart = with cfg; let
+          opt = n: v: optionalString (v != null) ''-${n}="${v}"'';
+        in
+          lib.concatStringsSep " \\\n" [
+            "${pkgs.cfssl}/bin/cfssl serve"
+            (opt "address" address)
+            (opt "port" (toString port))
+            (opt "ca" ca)
+            (opt "ca-key" caKey)
+            (opt "ca-bundle" caBundle)
+            (opt "int-bundle" intBundle)
+            (opt "int-dir" intDir)
+            (opt "metadata" metadata)
+            (opt "remote" remote)
+            (opt "config" configFile)
+            (opt "responder" responder)
+            (opt "responder-key" responderKey)
+            (opt "tls-key" tlsKey)
+            (opt "tls-cert" tlsCert)
+            (opt "mutual-tls-ca" mutualTlsCa)
+            (opt "mutual-tls-cn" mutualTlsCn)
+            (opt "mutual-tls-client-key" mutualTlsClientKey)
+            (opt "mutual-tls-client-cert" mutualTlsClientCert)
+            (opt "tls-remote-ca" tlsRemoteCa)
+            (opt "db-config" dbConfig)
+            (opt "loglevel" (toString logLevel))
+          ];
+      };
+    };
+
+    services.cfssl = {
+      ca = mkDefault "${cfg.dataDir}/ca.pem";
+      caKey = mkDefault "${cfg.dataDir}/ca-key.pem";
+    };
+  };
+}
diff --git a/nixos/modules/services/web-servers/hydron.nix b/nixos/modules/services/web-servers/hydron.nix
index 49a18f5e7b2..c49efaede16 100644
--- a/nixos/modules/services/web-servers/hydron.nix
+++ b/nixos/modules/services/web-servers/hydron.nix
@@ -1,6 +1,8 @@
 { config, lib, pkgs, ... }:
 
-let cfg = config.services.hydron;
+let
+  cfg = config.services.hydron;
+  postgres = config.services.postgresql;
 in with lib; {
   options.services.hydron = {
     enable = mkEnableOption "hydron";
@@ -25,6 +27,38 @@ in with lib; {
       '';
     };
 
+    password = mkOption {
+      type = types.str;
+      default = "hydron";
+      example = "dumbpass";
+      description = "Password for the hydron database.";
+    };
+
+    passwordFile = mkOption {
+      type = types.path;
+      default = "/run/keys/hydron-password-file";
+      example = "/home/okina/hydron/keys/pass";
+      description = "Password file for the hydron database.";
+    };
+
+    postgresArgs = mkOption {
+      type = types.str;
+      description = "Postgresql connection arguments.";
+      example = ''
+        {
+          "driver": "postgres",
+          "connection": "user=hydron password=dumbpass dbname=hydron sslmode=disable"
+        }
+      '';
+    };
+
+    postgresArgsFile = mkOption {
+      type = types.path;
+      default = "/run/keys/hydron-postgres-args";
+      example = "/home/okina/hydron/keys/postgres";
+      description = "Postgresql connection arguments file.";
+    };
+
     listenAddress = mkOption {
       type = types.nullOr types.str;
       default = null;
@@ -47,16 +81,36 @@ in with lib; {
   };
 
   config = mkIf cfg.enable {
+    security.sudo.enable = cfg.enable;
+    services.postgresql.enable = cfg.enable;
+    services.hydron.passwordFile = mkDefault (pkgs.writeText "hydron-password-file" cfg.password);
+    services.hydron.postgresArgsFile = mkDefault (pkgs.writeText "hydron-postgres-args" cfg.postgresArgs);
+    services.hydron.postgresArgs = mkDefault ''
+      {
+        "driver": "postgres",
+        "connection": "user=hydron password=${cfg.password} dbname=hydron sslmode=disable"
+      }
+    '';
+
     systemd.services.hydron = {
       description = "hydron";
-      after = [ "network.target" ];
+      after = [ "network.target" "postgresql.service" ];
       wantedBy = [ "multi-user.target" ];
 
       preStart = ''
-        # Ensure folder exists and permissions are correct
-        mkdir -p ${escapeShellArg cfg.dataDir}/images
+        # Ensure folder exists or create it and permissions are correct
+        mkdir -p ${escapeShellArg cfg.dataDir}/{.hydron,images}
+        ln -sf ${escapeShellArg cfg.postgresArgsFile} ${escapeShellArg cfg.dataDir}/.hydron/db_conf.json
         chmod 750 ${escapeShellArg cfg.dataDir}
         chown -R hydron:hydron ${escapeShellArg cfg.dataDir}
+
+        # Ensure the database is correct or create it
+        ${pkgs.sudo}/bin/sudo -u ${postgres.superUser} ${postgres.package}/bin/createuser \
+          -SDR hydron || true
+        ${pkgs.sudo}/bin/sudo -u ${postgres.superUser} ${postgres.package}/bin/createdb \
+          -T template0 -E UTF8 -O hydron hydron || true
+        ${pkgs.sudo}/bin/sudo -u hydron ${postgres.package}/bin/psql \
+          -c "ALTER ROLE hydron WITH PASSWORD '$(cat ${escapeShellArg cfg.passwordFile})';" || true
       '';
 
       serviceConfig = {
@@ -101,5 +155,9 @@ in with lib; {
     };
   };
 
+  imports = [
+    (mkRenamedOptionModule [ "services" "hydron" "baseDir" ] [ "services" "hydron" "dataDir" ])
+  ];
+
   meta.maintainers = with maintainers; [ chiiruno ];
 }
diff --git a/nixos/modules/services/web-servers/meguca.nix b/nixos/modules/services/web-servers/meguca.nix
index ed7325ff079..11aebcb91d8 100644
--- a/nixos/modules/services/web-servers/meguca.nix
+++ b/nixos/modules/services/web-servers/meguca.nix
@@ -1,65 +1,71 @@
 { config, lib, pkgs, ... }:
 
-with lib;
 let
   cfg = config.services.meguca;
   postgres = config.services.postgresql;
-in
-{
+in with lib; {
   options.services.meguca = {
     enable = mkEnableOption "meguca";
 
-    baseDir = mkOption {
+    dataDir = mkOption {
       type = types.path;
-      default = "/run/meguca";
+      default = "/var/lib/meguca";
+      example = "/home/okina/meguca";
       description = "Location where meguca stores it's database and links.";
     };
 
     password = mkOption {
       type = types.str;
       default = "meguca";
+      example = "dumbpass";
       description = "Password for the meguca database.";
     };
 
     passwordFile = mkOption {
       type = types.path;
       default = "/run/keys/meguca-password-file";
+      example = "/home/okina/meguca/keys/pass";
       description = "Password file for the meguca database.";
     };
 
     reverseProxy = mkOption {
       type = types.nullOr types.str;
       default = null;
+      example = "192.168.1.5";
       description = "Reverse proxy IP.";
     };
 
     sslCertificate = mkOption {
       type = types.nullOr types.str;
       default = null;
+      example = "/home/okina/meguca/ssl.cert";
       description = "Path to the SSL certificate.";
     };
 
     listenAddress = mkOption {
       type = types.nullOr types.str;
       default = null;
+      example = "127.0.0.1:8000";
       description = "Listen on a specific IP address and port.";
     };
 
     cacheSize = mkOption {
       type = types.nullOr types.int;
       default = null;
+      example = 256;
       description = "Cache size in MB.";
     };
 
     postgresArgs = mkOption {
       type = types.str;
-      default = "user=meguca password=" + cfg.password + " dbname=meguca sslmode=disable";
+      example = "user=meguca password=dumbpass dbname=meguca sslmode=disable";
       description = "Postgresql connection arguments.";
     };
 
     postgresArgsFile = mkOption {
       type = types.path;
       default = "/run/keys/meguca-postgres-args";
+      example = "/home/okina/meguca/keys/postgres";
       description = "Postgresql connection arguments file.";
     };
 
@@ -83,18 +89,11 @@ in
   };
 
   config = mkIf cfg.enable {
-    security.sudo.enable = cfg.enable == true;
-    services.postgresql.enable = cfg.enable == true;
-
-    services.meguca.passwordFile = mkDefault (toString (pkgs.writeTextFile {
-      name = "meguca-password-file";
-      text = cfg.password;
-    }));
-
-    services.meguca.postgresArgsFile = mkDefault (toString (pkgs.writeTextFile {
-      name = "meguca-postgres-args";
-      text = cfg.postgresArgs;
-    }));
+    security.sudo.enable = cfg.enable;
+    services.postgresql.enable = cfg.enable;
+    services.meguca.passwordFile = mkDefault (pkgs.writeText "meguca-password-file" cfg.password);
+    services.meguca.postgresArgsFile = mkDefault (pkgs.writeText "meguca-postgres-args" cfg.postgresArgs);
+    services.meguca.postgresArgs = mkDefault "user=meguca password=${cfg.password} dbname=meguca sslmode=disable";
 
     systemd.services.meguca = {
       description = "meguca";
@@ -102,10 +101,11 @@ in
       wantedBy = [ "multi-user.target" ];
 
       preStart = ''
-        # Ensure folder exists and links are correct or create them
-        mkdir -p ${cfg.baseDir}
-        chmod 750 ${cfg.baseDir}
-        ln -sf ${pkgs.meguca}/share/meguca/www ${cfg.baseDir}
+        # Ensure folder exists or create it and links and permissions are correct
+        mkdir -p ${escapeShellArg cfg.dataDir}
+        ln -sf ${pkgs.meguca}/share/meguca/www ${escapeShellArg cfg.dataDir}
+        chmod 750 ${escapeShellArg cfg.dataDir}
+        chown -R meguca:meguca ${escapeShellArg cfg.dataDir}
 
         # Ensure the database is correct or create it
         ${pkgs.sudo}/bin/sudo -u ${postgres.superUser} ${postgres.package}/bin/createuser \
@@ -113,47 +113,46 @@ in
         ${pkgs.sudo}/bin/sudo -u ${postgres.superUser} ${postgres.package}/bin/createdb \
           -T template0 -E UTF8 -O meguca meguca || true
         ${pkgs.sudo}/bin/sudo -u meguca ${postgres.package}/bin/psql \
-          -c "ALTER ROLE meguca WITH PASSWORD '$(cat ${cfg.passwordFile})';" || true
+          -c "ALTER ROLE meguca WITH PASSWORD '$(cat ${escapeShellArg cfg.passwordFile})';" || true
       '';
 
     script = ''
-      cd ${cfg.baseDir}
-
-      ${pkgs.meguca}/bin/meguca -d "$(cat ${cfg.postgresArgsFile})"\
-        ${optionalString (cfg.reverseProxy != null) " -R ${cfg.reverseProxy}"}\
-        ${optionalString (cfg.sslCertificate != null) " -S ${cfg.sslCertificate}"}\
-        ${optionalString (cfg.listenAddress != null) " -a ${cfg.listenAddress}"}\
-        ${optionalString (cfg.cacheSize != null) " -c ${toString cfg.cacheSize}"}\
-        ${optionalString (cfg.compressTraffic) " -g"}\
-        ${optionalString (cfg.assumeReverseProxy) " -r"}\
-        ${optionalString (cfg.httpsOnly) " -s"} start
-    '';
+      cd ${escapeShellArg cfg.dataDir}
+
+      ${pkgs.meguca}/bin/meguca -d "$(cat ${escapeShellArg cfg.postgresArgsFile})"''
+      + optionalString (cfg.reverseProxy != null) " -R ${cfg.reverseProxy}"
+      + optionalString (cfg.sslCertificate != null) " -S ${cfg.sslCertificate}"
+      + optionalString (cfg.listenAddress != null) " -a ${cfg.listenAddress}"
+      + optionalString (cfg.cacheSize != null) " -c ${toString cfg.cacheSize}"
+      + optionalString (cfg.compressTraffic) " -g"
+      + optionalString (cfg.assumeReverseProxy) " -r"
+      + optionalString (cfg.httpsOnly) " -s" + " start";
 
       serviceConfig = {
         PermissionsStartOnly = true;
         Type = "forking";
         User = "meguca";
         Group = "meguca";
-        RuntimeDirectory = "meguca";
         ExecStop = "${pkgs.meguca}/bin/meguca stop";
       };
     };
 
     users = {
+      groups.meguca.gid = config.ids.gids.meguca;
+
       users.meguca = {
         description = "meguca server service user";
-        home = cfg.baseDir;
+        home = cfg.dataDir;
         createHome = true;
         group = "meguca";
         uid = config.ids.uids.meguca;
       };
-
-      groups.meguca = {
-        gid = config.ids.gids.meguca;
-        members = [ "meguca" ];
-      };
     };
   };
 
+  imports = [
+    (mkRenamedOptionModule [ "services" "meguca" "baseDir" ] [ "services" "meguca" "dataDir" ])
+  ];
+
   meta.maintainers = with maintainers; [ chiiruno ];
 }
diff --git a/nixos/modules/services/web-servers/tomcat.nix b/nixos/modules/services/web-servers/tomcat.nix
index d8ccb7ca65d..d92ba72a833 100644
--- a/nixos/modules/services/web-servers/tomcat.nix
+++ b/nixos/modules/services/web-servers/tomcat.nix
@@ -108,7 +108,7 @@ in
       };
 
       webapps = mkOption {
-        type = types.listOf types.package;
+        type = types.listOf types.path;
         default = [ tomcat.webapps ];
         defaultText = "[ pkgs.tomcat85.webapps ]";
         description = "List containing WAR files or directories with WAR files which are web applications to be deployed on Tomcat";
@@ -118,8 +118,15 @@ in
         type = types.listOf (types.submodule {
           options = {
             name = mkOption {
-              type = types.listOf types.str;
+              type = types.str;
               description = "name of the virtualhost";
+            };
+            webapps = mkOption {
+              type = types.listOf types.path;
+              description = ''
+                List containing web application WAR files and/or directories containing
+                web applications and configuration files for the virtual host.
+              '';
               default = [];
             };
           };
diff --git a/nixos/modules/services/x11/desktop-managers/default.nix b/nixos/modules/services/x11/desktop-managers/default.nix
index f435e85f6b8..cce35aa28ba 100644
--- a/nixos/modules/services/x11/desktop-managers/default.nix
+++ b/nixos/modules/services/x11/desktop-managers/default.nix
@@ -96,13 +96,13 @@ in
           else if any (w: w.name == defaultDM) cfg.session.list then
             defaultDM
           else
-            throw ''
-              Default desktop manager (${defaultDM}) not found.
-              Probably you want to change
-                services.xserver.desktopManager.default = "${defaultDM}";
-              to one of
+            builtins.trace ''
+              Default desktop manager (${defaultDM}) not found at evaluation time.
+              These are the known valid session names:
                 ${concatMapStringsSep "\n  " (w: "services.xserver.desktopManager.default = \"${w.name}\";") cfg.session.list}
-            '';
+              It's also possible the default can be found in one of these packages:
+                ${concatMapStringsSep "\n  " (p: p.name) config.services.xserver.displayManager.extraSessionFilePackages}
+            '' defaultDM;
       };
 
     };
diff --git a/nixos/modules/services/x11/desktop-managers/gnome3.nix b/nixos/modules/services/x11/desktop-managers/gnome3.nix
index 9fb8f44b242..ee9b11928ae 100644
--- a/nixos/modules/services/x11/desktop-managers/gnome3.nix
+++ b/nixos/modules/services/x11/desktop-managers/gnome3.nix
@@ -57,8 +57,12 @@ in {
       sessionPath = mkOption {
         default = [];
         example = literalExample "[ pkgs.gnome3.gpaste ]";
-        description = "Additional list of packages to be added to the session search path.
-                       Useful for gnome shell extensions or gsettings-conditionated autostart.";
+        description = ''
+          Additional list of packages to be added to the session search path.
+          Useful for GNOME Shell extensions or GSettings-conditional autostart.
+
+          Note that this should be a last resort; patching the package is preferred (see GPaste).
+        '';
         apply = list: list ++ [ pkgs.gnome3.gnome-shell pkgs.gnome3.gnome-shell-extensions ];
       };
 
@@ -126,18 +130,10 @@ in {
 
     fonts.fonts = [ pkgs.dejavu_fonts pkgs.cantarell-fonts ];
 
-    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}
-
-          # find theme engines
-          export GTK_PATH=${config.system.path}/lib/gtk-3.0:${config.system.path}/lib/gtk-2.0
-
-          export XDG_MENU_PREFIX=gnome-
+    services.xserver.displayManager.extraSessionFilePackages = [ pkgs.gnome3.gnome-session ];
 
+    services.xserver.displayManager.sessionCommands = ''
+      if test "$XDG_CURRENT_DESKTOP" = "GNOME"; then
           ${concatMapStrings (p: ''
             if [ -d "${p}/share/gsettings-schemas/${p.name}" ]; then
               export XDG_DATA_DIRS=$XDG_DATA_DIRS''${XDG_DATA_DIRS:+:}${p}/share/gsettings-schemas/${p.name}
@@ -148,34 +144,28 @@ in {
               export LD_LIBRARY_PATH=$LD_LIBRARY_PATH''${LD_LIBRARY_PATH:+:}${p}/lib
             fi
           '') cfg.sessionPath}
+      fi
+    '';
 
-          # Override default mimeapps
-          export XDG_DATA_DIRS=$XDG_DATA_DIRS''${XDG_DATA_DIRS:+:}${mimeAppsList}/share
-
-          # Override gsettings-desktop-schema
-          export NIX_GSETTINGS_OVERRIDES_DIR=${nixos-gsettings-desktop-schemas}/share/gsettings-schemas/nixos-gsettings-overrides/glib-2.0/schemas
-
-          # Let nautilus find extensions
-          export NAUTILUS_EXTENSION_DIR=${config.system.path}/lib/nautilus/extensions-3.0/
-
-          # Find the mouse
-          export XCURSOR_PATH=~/.icons:${config.system.path}/share/icons
+    environment.variables.GNOME_SESSION_DEBUG = optionalString cfg.debug "1";
 
-          # Update user dirs as described in http://freedesktop.org/wiki/Software/xdg-user-dirs/
-          ${pkgs.xdg-user-dirs}/bin/xdg-user-dirs-update
+    # Override default mimeapps
+    environment.variables.XDG_DATA_DIRS = [ "${mimeAppsList}/share" ];
 
-          ${pkgs.gnome3.gnome-session}/bin/gnome-session ${optionalString cfg.debug "--debug"} &
-          waitPID=$!
-        '';
-      };
+    # Override GSettings schemas
+    environment.variables.NIX_GSETTINGS_OVERRIDES_DIR = "${nixos-gsettings-desktop-schemas}/share/gsettings-schemas/nixos-gsettings-overrides/glib-2.0/schemas";
 
-    services.xserver.updateDbusEnvironment = true;
+    # Let nautilus find extensions
+    # TODO: Create nautilus-with-extensions package
+    environment.variables.NAUTILUS_EXTENSION_DIR = "${config.system.path}/lib/nautilus/extensions-3.0";
 
     environment.variables.GIO_EXTRA_MODULES = [ "${lib.getLib pkgs.gnome3.dconf}/lib/gio/modules"
                                                 "${pkgs.gnome3.glib-networking.out}/lib/gio/modules"
                                                 "${pkgs.gnome3.gvfs}/lib/gio/modules" ];
     environment.systemPackages = pkgs.gnome3.corePackages ++ cfg.sessionPath
-      ++ (removePackagesByName pkgs.gnome3.optionalPackages config.environment.gnome3.excludePackages);
+      ++ (removePackagesByName pkgs.gnome3.optionalPackages config.environment.gnome3.excludePackages) ++ [
+      pkgs.xdg-user-dirs # Update user dirs as described in http://freedesktop.org/wiki/Software/xdg-user-dirs/
+    ];
 
     # Use the correct gnome3 packageSet
     networking.networkmanager.basePackages =
diff --git a/nixos/modules/services/x11/display-managers/default.nix b/nixos/modules/services/x11/display-managers/default.nix
index 43ed21c95fe..78095e7ce0b 100644
--- a/nixos/modules/services/x11/display-managers/default.nix
+++ b/nixos/modules/services/x11/display-managers/default.nix
@@ -27,55 +27,26 @@ let
     Xft.hintstyle: hintslight
   '';
 
-  # file provided by services.xserver.displayManager.session.script
-  xsession = wm: dm: pkgs.writeScript "xsession"
+  # file provided by services.xserver.displayManager.session.wrapper
+  xsessionWrapper = pkgs.writeScript "xsession-wrapper"
     ''
       #! ${pkgs.bash}/bin/bash
 
-      # Expected parameters:
-      #   $1 = <desktop-manager>+<window-manager>
-
-      # Actual parameters (FIXME):
-      # SDDM is calling this script like the following:
-      #   $1 = /nix/store/xxx-xsession (= $0)
-      #   $2 = <desktop-manager>+<window-manager>
-      # SLiM is using the following parameter:
-      #   $1 = /nix/store/xxx-xsession <desktop-manager>+<window-manager>
-      # LightDM keeps the double quotes:
-      #   $1 = /nix/store/xxx-xsession "<desktop-manager>+<window-manager>"
-      # The fake/auto display manager doesn't use any parameters and GDM is
-      # broken.
-      # If you want to "debug" this script don't print the parameters to stdout
-      # or stderr because this script will be executed multiple times and the
-      # output won't be visible in the log when the script is executed for the
-      # first time (e.g. append them to a file instead)!
-
-      # All of the above cases are handled by the following hack (FIXME).
-      # Since this line is *very important* for *all display managers* it is
-      # very important to test changes to the following line with all display
-      # managers:
-      if [ "''${1:0:1}" = "/" ]; then eval exec "$1" "$2" ; fi
-
-      # Now it should be safe to assume that the script was called with the
-      # expected parameters.
+      # Shared environment setup for graphical sessions.
 
       . /etc/profile
       cd "$HOME"
 
-      # The first argument of this script is the session type.
-      sessionType="$1"
-      if [ "$sessionType" = default ]; then sessionType=""; fi
-
       ${optionalString cfg.startDbusSession ''
         if test -z "$DBUS_SESSION_BUS_ADDRESS"; then
-          exec ${pkgs.dbus.dbus-launch} --exit-with-session "$0" "$sessionType"
+          exec ${pkgs.dbus.dbus-launch} --exit-with-session "$0" "$@"
         fi
       ''}
 
       ${optionalString cfg.displayManager.job.logToJournal ''
         if [ -z "$_DID_SYSTEMD_CAT" ]; then
           export _DID_SYSTEMD_CAT=1
-          exec ${config.systemd.package}/bin/systemd-cat -t xsession "$0" "$sessionType"
+          exec ${config.systemd.package}/bin/systemd-cat -t xsession "$0" "$@"
         fi
       ''}
 
@@ -90,7 +61,9 @@ let
         }
 
         # Publish access credentials in the root window.
-        ${config.hardware.pulseaudio.package.out}/bin/pactl load-module module-x11-publish "display=$DISPLAY"
+        if ${config.hardware.pulseaudio.package.out}/bin/pulseaudio --dump-modules | grep module-x11-publish &> /dev/null; then
+          ${config.hardware.pulseaudio.package.out}/bin/pactl load-module module-x11-publish "display=$DISPLAY"
+        fi
       ''}
 
       # Tell systemd about our $DISPLAY and $XAUTHORITY.
@@ -101,6 +74,7 @@ let
       ${config.systemd.package}/bin/systemctl --user import-environment DISPLAY XAUTHORITY DBUS_SESSION_BUS_ADDRESS
 
       # Load X defaults.
+      # FIXME: Check XDG_SESSION_TYPE against x11
       ${xorg.xrdb}/bin/xrdb -merge ${xresourcesXft}
       if test -e ~/.Xresources; then
           ${xorg.xrdb}/bin/xrdb -merge ~/.Xresources
@@ -132,11 +106,32 @@ let
       # Allow the user to setup a custom session type.
       if test -x ~/.xsession; then
           exec ~/.xsession
+      fi
+
+      if test "$1"; then
+          # Run the supplied session command. Remove any double quotes with eval.
+          eval exec "$@"
       else
-          if test "$sessionType" = "custom"; then
-              sessionType="" # fall-thru if there is no ~/.xsession
-          fi
+          # Fall back to the default window/desktopManager
+          exec ${cfg.displayManager.session.script}
       fi
+    '';
+
+  # file provided by services.xserver.displayManager.session.script
+  xsession = wm: dm: pkgs.writeScript "xsession"
+    ''
+      #! ${pkgs.bash}/bin/bash
+
+      # Legacy session script used to construct .desktop files from
+      # `services.xserver.displayManager.session` entries. Called from
+      # `sessionWrapper`.
+
+      # Expected parameters:
+      #   $1 = <desktop-manager>+<window-manager>
+
+      # The first argument of this script is the session type.
+      sessionType="$1"
+      if [ "$sessionType" = default ]; then sessionType=""; fi
 
       # The session type is "<desktop-manager>+<window-manager>", so
       # extract those (see:
@@ -186,19 +181,22 @@ let
       allowSubstitutes = false;
     }
     ''
-      mkdir -p "$out"
+      mkdir -p "$out/share/xsessions"
       ${concatMapStrings (n: ''
-        cat - > "$out/${n}.desktop" << EODESKTOP
+        cat - > "$out/share/xsessions/${n}.desktop" << EODESKTOP
         [Desktop Entry]
         Version=1.0
         Type=XSession
         TryExec=${cfg.displayManager.session.script}
         Exec=${cfg.displayManager.session.script} "${n}"
-        X-GDM-BypassXsession=true
         Name=${n}
         Comment=
         EODESKTOP
       '') names}
+
+      ${concatMapStrings (pkg: ''
+        ${xorg.lndir}/bin/lndir ${pkg}/share/xsessions $out/share/xsessions
+      '') cfg.displayManager.extraSessionFilePackages}
     '';
 
 in
@@ -245,6 +243,14 @@ in
         '';
       };
 
+      extraSessionFilePackages = mkOption {
+        type = types.listOf types.package;
+        default = [];
+        description = ''
+          A list of packages containing xsession files to be passed to the display manager.
+        '';
+      };
+
       session = mkOption {
         default = [];
         example = literalExample
@@ -280,6 +286,7 @@ in
               (filter (w: d.name != "none" || w.name != "none") wm));
           desktops = mkDesktops names;
           script = xsession wm dm;
+          wrapper = xsessionWrapper;
         };
       };
 
diff --git a/nixos/modules/services/x11/display-managers/gdm.nix b/nixos/modules/services/x11/display-managers/gdm.nix
index 8b08c01ea0d..78dc39f7f62 100644
--- a/nixos/modules/services/x11/display-managers/gdm.nix
+++ b/nixos/modules/services/x11/display-managers/gdm.nix
@@ -109,7 +109,7 @@ in
         environment = {
           GDM_X_SERVER_EXTRA_ARGS = toString
             (filter (arg: arg != "-terminate") cfg.xserverArgs);
-          GDM_SESSIONS_DIR = "${cfg.session.desktops}";
+          GDM_SESSIONS_DIR = "${cfg.session.desktops}/share/xsessions";
           # Find the mouse
           XCURSOR_PATH = "~/.icons:${pkgs.gnome3.adwaita-icon-theme}/share/icons";
         };
@@ -173,6 +173,8 @@ in
       ${optionalString cfg.gdm.debug "Enable=true"}
     '';
 
+    environment.etc."gdm/Xsession".source = config.services.xserver.displayManager.session.wrapper;
+
     # GDM LFS PAM modules, adapted somehow to NixOS
     security.pam.services = {
       gdm-launch-environment.text = ''
diff --git a/nixos/modules/services/x11/display-managers/lightdm-greeters/gtk.nix b/nixos/modules/services/x11/display-managers/lightdm-greeters/gtk.nix
index cfa38f175dd..013956c0546 100644
--- a/nixos/modules/services/x11/display-managers/lightdm-greeters/gtk.nix
+++ b/nixos/modules/services/x11/display-managers/lightdm-greeters/gtk.nix
@@ -23,7 +23,7 @@ let
       makeWrapper ${pkgs.lightdm_gtk_greeter}/sbin/lightdm-gtk-greeter \
         $out/greeter \
         --prefix PATH : "${pkgs.glibc.bin}/bin" \
-        --set GDK_PIXBUF_MODULE_FILE "${pkgs.gdk_pixbuf.out}/lib/gdk-pixbuf-2.0/2.10.0/loaders.cache" \
+        --set GDK_PIXBUF_MODULE_FILE "${pkgs.librsvg.out}/lib/gdk-pixbuf-2.0/2.10.0/loaders.cache" \
         --set GTK_PATH "${theme}:${pkgs.gtk3.out}" \
         --set GTK_EXE_PREFIX "${theme}" \
         --set GTK_DATA_PREFIX "${theme}" \
diff --git a/nixos/modules/services/x11/display-managers/lightdm.nix b/nixos/modules/services/x11/display-managers/lightdm.nix
index 54d4520a0c8..6be15d8cdf4 100644
--- a/nixos/modules/services/x11/display-managers/lightdm.nix
+++ b/nixos/modules/services/x11/display-managers/lightdm.nix
@@ -45,11 +45,11 @@ let
         greeter-user = ${config.users.users.lightdm.name}
         greeters-directory = ${cfg.greeter.package}
       ''}
-      sessions-directory = ${dmcfg.session.desktops}
+      sessions-directory = ${dmcfg.session.desktops}/share/xsessions
 
       [Seat:*]
       xserver-command = ${xserverWrapper}
-      session-wrapper = ${dmcfg.session.script}
+      session-wrapper = ${dmcfg.session.wrapper}
       ${optionalString cfg.greeter.enable ''
         greeter-session = ${cfg.greeter.name}
       ''}
@@ -176,21 +176,13 @@ in
           LightDM auto-login requires services.xserver.displayManager.lightdm.autoLogin.user to be set
         '';
       }
-      { assertion = cfg.autoLogin.enable -> elem defaultSessionName dmcfg.session.names;
+      { assertion = cfg.autoLogin.enable -> dmDefault != "none" || wmDefault != "none";
         message = ''
           LightDM 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.
         '';
       }
-      { assertion = hasDefaultUserSession -> elem defaultSessionName dmcfg.session.names;
-        message = ''
-          services.xserver.desktopManager.default and
-          services.xserver.windowMananger.default are not set to valid
-          values. The current default session: ${defaultSessionName}
-          is not valid.
-        '';
-      }
       { assertion = !cfg.greeter.enable -> (cfg.autoLogin.enable && cfg.autoLogin.timeout == 0);
         message = ''
           LightDM can only run without greeter if automatic login is enabled and the timeout for it
diff --git a/nixos/modules/services/x11/display-managers/sddm.nix b/nixos/modules/services/x11/display-managers/sddm.nix
index 426b899586f..1b347803932 100644
--- a/nixos/modules/services/x11/display-managers/sddm.nix
+++ b/nixos/modules/services/x11/display-managers/sddm.nix
@@ -49,8 +49,8 @@ let
     MinimumVT=${toString (if xcfg.tty != null then xcfg.tty else 7)}
     ServerPath=${xserverWrapper}
     XephyrPath=${pkgs.xorg.xorgserver.out}/bin/Xephyr
-    SessionCommand=${dmcfg.session.script}
-    SessionDir=${dmcfg.session.desktops}
+    SessionCommand=${dmcfg.session.wrapper}
+    SessionDir=${dmcfg.session.desktops}/share/xsessions
     XauthPath=${pkgs.xorg.xauth}/bin/xauth
     DisplayCommand=${Xsetup}
     DisplayStopCommand=${Xstop}
diff --git a/nixos/modules/services/x11/display-managers/slim.nix b/nixos/modules/services/x11/display-managers/slim.nix
index f645a5c2f07..51ce5f4e243 100644
--- a/nixos/modules/services/x11/display-managers/slim.nix
+++ b/nixos/modules/services/x11/display-managers/slim.nix
@@ -13,8 +13,8 @@ let
       xauth_path ${dmcfg.xauthBin}
       default_xserver ${dmcfg.xserverBin}
       xserver_arguments ${toString dmcfg.xserverArgs}
-      sessiondir ${dmcfg.session.desktops}
-      login_cmd exec ${pkgs.runtimeShell} ${dmcfg.session.script} "%session"
+      sessiondir ${dmcfg.session.desktops}/share/xsessions
+      login_cmd exec ${pkgs.runtimeShell} ${dmcfg.session.wrapper} "%session"
       halt_cmd ${config.systemd.package}/sbin/shutdown -h now
       reboot_cmd ${config.systemd.package}/sbin/shutdown -r now
       logfile /dev/stderr
diff --git a/nixos/modules/system/boot/loader/systemd-boot/systemd-boot-builder.py b/nixos/modules/system/boot/loader/systemd-boot/systemd-boot-builder.py
index 3333569c36b..1dc888c5822 100644
--- a/nixos/modules/system/boot/loader/systemd-boot/systemd-boot-builder.py
+++ b/nixos/modules/system/boot/loader/systemd-boot/systemd-boot-builder.py
@@ -43,6 +43,7 @@ def write_loader_conf(profile, generation):
             f.write("default nixos-generation-%d\n" % (generation))
         if not @editor@:
             f.write("editor 0");
+        f.write("console-mode @consoleMode@\n");
     os.rename("@efiSysMountPoint@/loader/loader.conf.tmp", "@efiSysMountPoint@/loader/loader.conf")
 
 def profile_path(profile, generation, name):
diff --git a/nixos/modules/system/boot/loader/systemd-boot/systemd-boot.nix b/nixos/modules/system/boot/loader/systemd-boot/systemd-boot.nix
index a5a88a99be8..feed863efd6 100644
--- a/nixos/modules/system/boot/loader/systemd-boot/systemd-boot.nix
+++ b/nixos/modules/system/boot/loader/systemd-boot/systemd-boot.nix
@@ -22,6 +22,8 @@ let
 
     editor = if cfg.editor then "True" else "False";
 
+    inherit (cfg) consoleMode;
+
     inherit (efi) efiSysMountPoint canTouchEfiVariables;
   };
 in {
@@ -52,6 +54,38 @@ in {
         compatibility.
       '';
     };
+
+    consoleMode = mkOption {
+      default = "keep";
+
+      type = types.enum [ "0" "1" "2" "auto" "max" "keep" ];
+
+      description = ''
+        The resolution of the console. The following values are valid:
+        </para>
+        <para>
+        <itemizedlist>
+          <listitem><para>
+            <literal>"0"</literal>: Standard UEFI 80x25 mode
+          </para></listitem>
+          <listitem><para>
+            <literal>"1"</literal>: 80x50 mode, not supported by all devices
+          </para></listitem>
+          <listitem><para>
+            <literal>"2"</literal>: The first non-standard mode provided by the device firmware, if any
+          </para></listitem>
+          <listitem><para>
+            <literal>"auto"</literal>: Pick a suitable mode automatically using heuristics
+          </para></listitem>
+          <listitem><para>
+            <literal>"max"</literal>: Pick the highest-numbered available mode
+          </para></listitem>
+          <listitem><para>
+            <literal>"keep"</literal>: Keep the mode selected by firmware (the default)
+          </para></listitem>
+        </itemizedlist>
+      '';
+    };
   };
 
   config = mkIf cfg.enable {
diff --git a/nixos/release.nix b/nixos/release.nix
index 413f2bec54c..007859259b1 100644
--- a/nixos/release.nix
+++ b/nixos/release.nix
@@ -256,6 +256,7 @@ in rec {
   tests.buildbot = callTest tests/buildbot.nix {};
   tests.cadvisor = callTestOnMatchingSystems ["x86_64-linux"] tests/cadvisor.nix {};
   tests.ceph = callTestOnMatchingSystems ["x86_64-linux"] tests/ceph.nix {};
+  tests.cfssl = callTestOnMatchingSystems ["x86_64-linux"] tests/cfssl.nix {};
   tests.chromium = (callSubTestsOnMatchingSystems ["x86_64-linux"] tests/chromium.nix {}).stable or {};
   tests.cjdns = callTest tests/cjdns.nix {};
   tests.cloud-init = callTest tests/cloud-init.nix {};
diff --git a/nixos/tests/acme.nix b/nixos/tests/acme.nix
index 6d728b387e1..c7fd4910e07 100644
--- a/nixos/tests/acme.nix
+++ b/nixos/tests/acme.nix
@@ -12,7 +12,9 @@ let
         '';
       });
 
-      pythonPackages = (super.python.override {
+      # Override certifi so that it accepts fake certificate for Let's Encrypt
+      # Need to override the attribute used by simp_le, which is python3Packages
+      python3Packages = (super.python3.override {
         packageOverrides = lib.const (pysuper: {
           certifi = pysuper.certifi.overridePythonAttrs (attrs: {
             postPatch = (attrs.postPatch or "") + ''
diff --git a/nixos/tests/cfssl.nix b/nixos/tests/cfssl.nix
new file mode 100644
index 00000000000..513ed8c4574
--- /dev/null
+++ b/nixos/tests/cfssl.nix
@@ -0,0 +1,67 @@
+import ./make-test.nix ({ pkgs, ...} : {
+  name = "cfssl";
+
+  machine = { config, lib, pkgs, ... }:
+  {
+    networking.firewall.allowedTCPPorts = [ config.services.cfssl.port ];
+
+    services.cfssl.enable = true;
+    systemd.services.cfssl.after = [ "cfssl-init.service" ];
+
+    systemd.services.cfssl-init = {
+      description = "Initialize the cfssl CA";
+      wantedBy    = [ "multi-user.target" ];
+      serviceConfig = {
+        User             = "cfssl";
+        Type             = "oneshot";
+        WorkingDirectory = config.services.cfssl.dataDir;
+      };
+      script = with pkgs; ''
+        ${cfssl}/bin/cfssl genkey -initca ${pkgs.writeText "ca.json" (builtins.toJSON {
+          hosts = [ "ca.example.com" ];
+          key = {
+            algo = "rsa"; size = 4096; };
+            names = [
+              {
+                C = "US";
+                L = "San Francisco";
+                O = "Internet Widgets, LLC";
+                OU = "Certificate Authority";
+                ST = "California";
+              }
+            ];
+        })} | ${cfssl}/bin/cfssljson -bare ca
+      '';
+    };
+  };
+
+  testScript =
+  let
+    cfsslrequest = with pkgs; writeScript "cfsslrequest" ''
+      curl -X POST -H "Content-Type: application/json" -d @${csr} \
+        http://localhost:8888/api/v1/cfssl/newkey | ${cfssl}/bin/cfssljson /tmp/certificate
+    '';
+    csr = pkgs.writeText "csr.json" (builtins.toJSON {
+      CN = "www.example.com";
+      hosts = [ "example.com" "www.example.com" ];
+      key = {
+        algo = "rsa";
+        size = 2048;
+      };
+      names = [
+        {
+          C = "US";
+          L = "San Francisco";
+          O = "Example Company, LLC";
+          OU = "Operations";
+          ST = "California";
+        }
+      ];
+    });
+  in
+    ''
+      $machine->waitForUnit('cfssl.service');
+      $machine->waitUntilSucceeds('${cfsslrequest}');
+      $machine->succeed('ls /tmp/certificate-key.pem');
+    '';
+})
diff --git a/nixos/tests/containers-imperative.nix b/nixos/tests/containers-imperative.nix
index 93b00b5b977..913d8bed19d 100644
--- a/nixos/tests/containers-imperative.nix
+++ b/nixos/tests/containers-imperative.nix
@@ -9,6 +9,11 @@ import ./make-test.nix ({ pkgs, ...} : {
   machine =
     { config, pkgs, lib, ... }:
     { imports = [ ../modules/installer/cd-dvd/channel.nix ];
+
+      # XXX: Sandbox setup fails while trying to hardlink files from the host's
+      #      store file system into the prepared chroot directory.
+      nix.useSandbox = false;
+
       virtualisation.writableStore = true;
       virtualisation.memorySize = 1024;
       # Make sure we always have all the required dependencies for creating a
diff --git a/nixos/tests/gnome3.nix b/nixos/tests/gnome3.nix
index 3f51d04163a..af2404bf530 100644
--- a/nixos/tests/gnome3.nix
+++ b/nixos/tests/gnome3.nix
@@ -15,6 +15,7 @@ import ./make-test.nix ({ pkgs, ...} : {
       services.xserver.displayManager.lightdm.autoLogin.enable = true;
       services.xserver.displayManager.lightdm.autoLogin.user = "alice";
       services.xserver.desktopManager.gnome3.enable = true;
+      services.xserver.desktopManager.default = "gnome";
 
       virtualisation.memorySize = 1024;
     };
diff --git a/nixos/tests/graphite.nix b/nixos/tests/graphite.nix
index 1fe4357191e..27a87bdbb9f 100644
--- a/nixos/tests/graphite.nix
+++ b/nixos/tests/graphite.nix
@@ -1,4 +1,4 @@
-import ./make-test.nix ({ ... } :
+import ./make-test.nix ({ pkgs, ... } :
 {
   name = "graphite";
   nodes = {
@@ -11,10 +11,12 @@ import ./make-test.nix ({ ... } :
           api = {
             enable = true;
             port = 8082;
+            finders = [ pkgs.python27Packages.influxgraph ];
           };
           carbon.enableCache = true;
           seyren.enable = true;
           pager.enable = true;
+          beacon.enable = true;
         };
       };
   };
@@ -25,6 +27,7 @@ import ./make-test.nix ({ ... } :
     $one->waitForUnit("graphiteWeb.service");
     $one->waitForUnit("graphiteApi.service");
     $one->waitForUnit("graphitePager.service");
+    $one->waitForUnit("graphite-beacon.service");
     $one->waitForUnit("carbonCache.service");
     $one->waitForUnit("seyren.service");
     # The services above are of type "simple". systemd considers them active immediately
diff --git a/nixos/tests/netdata.nix b/nixos/tests/netdata.nix
index c56506ba287..eb45db6f04c 100644
--- a/nixos/tests/netdata.nix
+++ b/nixos/tests/netdata.nix
@@ -19,8 +19,12 @@ import ./make-test.nix ({ pkgs, ...} : {
     startAll;
 
     $netdata->waitForUnit("netdata.service");
-    # check if netdata can read disk ops for root owned processes. 
-    # if > 0, successful. verifies both netdata working and 
+
+    # check if the netdata main page loads.
+    $netdata->succeed("curl --fail http://localhost:19999/");
+
+    # check if netdata can read disk ops for root owned processes.
+    # if > 0, successful. verifies both netdata working and
     # apps.plugin has elevated capabilities.
     my $cmd = <<'CMD';
     curl -s http://localhost:19999/api/v1/data\?chart=users.pwrites | \