about summary refs log tree commit diff
path: root/nixos
diff options
context:
space:
mode:
Diffstat (limited to 'nixos')
-rw-r--r--nixos/doc/manual/default.nix106
-rw-r--r--nixos/lib/make-options-doc/default.nix125
-rw-r--r--nixos/lib/make-options-doc/options-to-docbook.xsl (renamed from nixos/doc/manual/options-to-docbook.xsl)0
-rw-r--r--nixos/lib/make-options-doc/postprocess-option-descriptions.xsl (renamed from nixos/doc/manual/postprocess-option-descriptions.xsl)0
-rw-r--r--nixos/modules/misc/nixpkgs.nix2
-rw-r--r--nixos/modules/module-list.nix11
-rw-r--r--nixos/modules/programs/evince.nix (renamed from nixos/modules/services/desktops/gnome3/evince.nix)13
-rw-r--r--nixos/modules/programs/file-roller.nix (renamed from nixos/modules/services/desktops/gnome3/file-roller.nix)11
-rw-r--r--nixos/modules/programs/gnome-disks.nix (renamed from nixos/modules/services/desktops/gnome3/gnome-disks.nix)15
-rw-r--r--nixos/modules/programs/gnome-documents.nix (renamed from nixos/modules/services/desktops/gnome3/gnome-documents.nix)15
-rw-r--r--nixos/modules/programs/gpaste.nix (renamed from nixos/modules/services/desktops/gnome3/gpaste.nix)15
-rw-r--r--nixos/modules/programs/nylas-mail.nix36
-rw-r--r--nixos/modules/services/backup/postgresql-wal-receiver.nix203
-rw-r--r--nixos/modules/services/databases/couchdb.nix8
-rw-r--r--nixos/modules/services/databases/postgresql.nix4
-rw-r--r--nixos/modules/services/monitoring/grafana.nix4
-rw-r--r--nixos/modules/services/x11/desktop-managers/gnome3.nix10
-rw-r--r--nixos/release-combined.nix7
-rw-r--r--nixos/tests/all-tests.nix9
-rw-r--r--nixos/tests/gnome3-gdm.nix63
-rw-r--r--nixos/tests/gnome3-xorg.nix41
-rw-r--r--nixos/tests/gnome3.nix51
-rw-r--r--nixos/tests/lightdm.nix2
-rw-r--r--nixos/tests/postgresql-wal-receiver.nix86
-rw-r--r--nixos/tests/syncthing-init.nix8
25 files changed, 589 insertions, 256 deletions
diff --git a/nixos/doc/manual/default.nix b/nixos/doc/manual/default.nix
index 7fc0ad702f84..f9de2db1a084 100644
--- a/nixos/doc/manual/default.nix
+++ b/nixos/doc/manual/default.nix
@@ -5,55 +5,6 @@ with pkgs;
 let
   lib = pkgs.lib;
 
-  # Remove invisible and internal options.
-  optionsListVisible = lib.filter (opt: opt.visible && !opt.internal) (lib.optionAttrSetToDocList options);
-
-  # Replace functions by the string <function>
-  substFunction = x:
-    if builtins.isAttrs x then lib.mapAttrs (name: substFunction) x
-    else if builtins.isList x then map substFunction x
-    else if lib.isFunction x then "<function>"
-    else x;
-
-  # Generate DocBook documentation for a list of packages. This is
-  # what `relatedPackages` option of `mkOption` from
-  # ../../../lib/options.nix influences.
-  #
-  # Each element of `relatedPackages` can be either
-  # - a string:  that will be interpreted as an attribute name from `pkgs`,
-  # - a list:    that will be interpreted as an attribute path from `pkgs`,
-  # - an attrset: that can specify `name`, `path`, `package`, `comment`
-  #   (either of `name`, `path` is required, the rest are optional).
-  genRelatedPackages = packages:
-    let
-      unpack = p: if lib.isString p then { name = p; }
-                  else if lib.isList p then { path = p; }
-                  else p;
-      describe = args:
-        let
-          title = args.title or null;
-          name = args.name or (lib.concatStringsSep "." args.path);
-          path = args.path or [ args.name ];
-          package = args.package or (lib.attrByPath path (throw "Invalid package attribute path `${toString path}'") pkgs);
-        in "<listitem>"
-        + "<para><literal>${lib.optionalString (title != null) "${title} aka "}pkgs.${name} (${package.meta.name})</literal>"
-        + lib.optionalString (!package.meta.available) " <emphasis>[UNAVAILABLE]</emphasis>"
-        + ": ${package.meta.description or "???"}.</para>"
-        + lib.optionalString (args ? comment) "\n<para>${args.comment}</para>"
-        # Lots of `longDescription's break DocBook, so we just wrap them into <programlisting>
-        + lib.optionalString (package.meta ? longDescription) "\n<programlisting>${package.meta.longDescription}</programlisting>"
-        + "</listitem>";
-    in "<itemizedlist>${lib.concatStringsSep "\n" (map (p: describe (unpack p)) packages)}</itemizedlist>";
-
-  optionsListDesc = lib.flip map optionsListVisible (opt: opt // {
-    # Clean up declaration sites to not refer to the NixOS source tree.
-    declarations = map stripAnyPrefixes opt.declarations;
-  }
-  // lib.optionalAttrs (opt ? example) { example = substFunction opt.example; }
-  // lib.optionalAttrs (opt ? default) { default = substFunction opt.default; }
-  // lib.optionalAttrs (opt ? type) { type = substFunction opt.type; }
-  // lib.optionalAttrs (opt ? relatedPackages && opt.relatedPackages != []) { relatedPackages = genRelatedPackages opt.relatedPackages; });
-
   # We need to strip references to /nix/store/* from options,
   # including any `extraSources` if some modules came from elsewhere,
   # or else the build will fail.
@@ -63,37 +14,13 @@ let
   prefixesToStrip = map (p: "${toString p}/") ([ ../../.. ] ++ extraSources);
   stripAnyPrefixes = lib.flip (lib.fold lib.removePrefix) prefixesToStrip;
 
-  # Custom "less" that pushes up all the things ending in ".enable*"
-  # and ".package*"
-  optionLess = a: b:
-    let
-      ise = lib.hasPrefix "enable";
-      isp = lib.hasPrefix "package";
-      cmp = lib.splitByAndCompare ise lib.compare
-                                 (lib.splitByAndCompare isp lib.compare lib.compare);
-    in lib.compareLists cmp a.loc b.loc < 0;
-
-  # Customly sort option list for the man page.
-  optionsList = lib.sort optionLess optionsListDesc;
-
-  # Convert the list of options into an XML file.
-  optionsXML = builtins.toFile "options.xml" (builtins.toXML optionsList);
-
-  optionsDocBook = runCommand "options-db.xml" {} ''
-    optionsXML=${optionsXML}
-    if grep /nixpkgs/nixos/modules $optionsXML; then
-      echo "The manual appears to depend on the location of Nixpkgs, which is bad"
-      echo "since this prevents sharing via the NixOS channel.  This is typically"
-      echo "caused by an option default that refers to a relative path (see above"
-      echo "for hints about the offending path)."
-      exit 1
-    fi
-    ${buildPackages.libxslt.bin}/bin/xsltproc \
-      --stringparam revision '${revision}' \
-      -o intermediate.xml ${./options-to-docbook.xsl} $optionsXML
-    ${buildPackages.libxslt.bin}/bin/xsltproc \
-      -o "$out" ${./postprocess-option-descriptions.xsl} intermediate.xml
-  '';
+  optionsDoc = buildPackages.nixosOptionsDoc {
+    inherit options revision;
+    transformOptions = opt: opt // {
+      # Clean up declaration sites to not refer to the NixOS source tree.
+      declarations = map stripAnyPrefixes opt.declarations;
+    };
+  };
 
   sources = lib.sourceFilesBySuffices ./. [".xml"];
 
@@ -108,7 +35,7 @@ let
   generatedSources = runCommand "generated-docbook" {} ''
     mkdir $out
     ln -s ${modulesDoc} $out/modules.xml
-    ln -s ${optionsDocBook} $out/options-db.xml
+    ln -s ${optionsDoc.optionsDocBook} $out/options-db.xml
     printf "%s" "${version}" > $out/version
   '';
 
@@ -234,22 +161,7 @@ let
 in rec {
   inherit generatedSources;
 
-  # The NixOS options in JSON format.
-  optionsJSON = runCommand "options-json"
-    { meta.description = "List of NixOS options in JSON format";
-    }
-    ''
-      # Export list of options in different format.
-      dst=$out/share/doc/nixos
-      mkdir -p $dst
-
-      cp ${builtins.toFile "options.json" (builtins.unsafeDiscardStringContext (builtins.toJSON
-        (builtins.listToAttrs (map (o: { name = o.name; value = removeAttrs o ["name" "visible" "internal"]; }) optionsList))))
-      } $dst/options.json
-
-      mkdir -p $out/nix-support
-      echo "file json $dst/options.json" >> $out/nix-support/hydra-build-products
-    ''; # */
+  inherit (optionsDoc) optionsJSON optionsXML optionsDocBook;
 
   # Generate the NixOS manual.
   manualHTML = runCommand "nixos-manual-html"
diff --git a/nixos/lib/make-options-doc/default.nix b/nixos/lib/make-options-doc/default.nix
new file mode 100644
index 000000000000..c22c7500335d
--- /dev/null
+++ b/nixos/lib/make-options-doc/default.nix
@@ -0,0 +1,125 @@
+/* Generate JSON, XML and DocBook documentation for given NixOS options.
+
+   Minimal example:
+
+    { pkgs,  }:
+
+    let
+      eval = import (pkgs.path + "/nixos/lib/eval-config.nix") {
+        baseModules = [
+          ../module.nix
+        ];
+        modules = [];
+      };
+    in pkgs.nixosOptionsDoc {
+      options = eval.options;
+    }
+
+*/
+{ pkgs
+, lib
+, options
+, transformOptions ? lib.id  # function for additional tranformations of the options
+, revision ? "" # Specify revision for the options
+}:
+
+let
+  # Replace functions by the string <function>
+  substFunction = x:
+    if builtins.isAttrs x then lib.mapAttrs (name: substFunction) x
+    else if builtins.isList x then map substFunction x
+    else if lib.isFunction x then "<function>"
+    else x;
+
+  optionsListDesc = lib.flip map optionsListVisible
+   (opt: transformOptions opt
+    // lib.optionalAttrs (opt ? example) { example = substFunction opt.example; }
+    // lib.optionalAttrs (opt ? default) { default = substFunction opt.default; }
+    // lib.optionalAttrs (opt ? type) { type = substFunction opt.type; }
+    // lib.optionalAttrs (opt ? relatedPackages && opt.relatedPackages != []) { relatedPackages = genRelatedPackages opt.relatedPackages; }
+   );
+
+  # Generate DocBook documentation for a list of packages. This is
+  # what `relatedPackages` option of `mkOption` from
+  # ../../../lib/options.nix influences.
+  #
+  # Each element of `relatedPackages` can be either
+  # - a string:  that will be interpreted as an attribute name from `pkgs`,
+  # - a list:    that will be interpreted as an attribute path from `pkgs`,
+  # - an attrset: that can specify `name`, `path`, `package`, `comment`
+  #   (either of `name`, `path` is required, the rest are optional).
+  genRelatedPackages = packages:
+    let
+      unpack = p: if lib.isString p then { name = p; }
+                  else if lib.isList p then { path = p; }
+                  else p;
+      describe = args:
+        let
+          title = args.title or null;
+          name = args.name or (lib.concatStringsSep "." args.path);
+          path = args.path or [ args.name ];
+          package = args.package or (lib.attrByPath path (throw "Invalid package attribute path `${toString path}'") pkgs);
+        in "<listitem>"
+        + "<para><literal>${lib.optionalString (title != null) "${title} aka "}pkgs.${name} (${package.meta.name})</literal>"
+        + lib.optionalString (!package.meta.available) " <emphasis>[UNAVAILABLE]</emphasis>"
+        + ": ${package.meta.description or "???"}.</para>"
+        + lib.optionalString (args ? comment) "\n<para>${args.comment}</para>"
+        # Lots of `longDescription's break DocBook, so we just wrap them into <programlisting>
+        + lib.optionalString (package.meta ? longDescription) "\n<programlisting>${package.meta.longDescription}</programlisting>"
+        + "</listitem>";
+    in "<itemizedlist>${lib.concatStringsSep "\n" (map (p: describe (unpack p)) packages)}</itemizedlist>";
+
+  # Custom "less" that pushes up all the things ending in ".enable*"
+  # and ".package*"
+  optionLess = a: b:
+    let
+      ise = lib.hasPrefix "enable";
+      isp = lib.hasPrefix "package";
+      cmp = lib.splitByAndCompare ise lib.compare
+                                 (lib.splitByAndCompare isp lib.compare lib.compare);
+    in lib.compareLists cmp a.loc b.loc < 0;
+
+  # Remove invisible and internal options.
+  optionsListVisible = lib.filter (opt: opt.visible && !opt.internal) (lib.optionAttrSetToDocList options);
+
+  # Customly sort option list for the man page.
+  optionsList = lib.sort optionLess optionsListDesc;
+
+  # Convert the list of options into an XML file.
+  optionsXML = builtins.toFile "options.xml" (builtins.toXML optionsList);
+
+in rec {
+  # The NixOS options in JSON format.
+  optionsJSON = pkgs.runCommand "options.json"
+    { meta.description = "List of NixOS options in JSON format";
+    }
+    ''
+      # Export list of options in different format.
+      dst=$out/share/doc/nixos
+      mkdir -p $dst
+
+      cp ${builtins.toFile "options.json" (builtins.unsafeDiscardStringContext (builtins.toJSON
+        (builtins.listToAttrs (map (o: { name = o.name; value = removeAttrs o ["name" "visible" "internal"]; }) optionsList))))
+      } $dst/options.json
+
+      mkdir -p $out/nix-support
+      echo "file json $dst/options.json" >> $out/nix-support/hydra-build-products
+    ''; # */
+
+  optionsDocBook = pkgs.runCommand "options-docbook.xml" {} ''
+    optionsXML=${optionsXML}
+    if grep /nixpkgs/nixos/modules $optionsXML; then
+      echo "The manual appears to depend on the location of Nixpkgs, which is bad"
+      echo "since this prevents sharing via the NixOS channel.  This is typically"
+      echo "caused by an option default that refers to a relative path (see above"
+      echo "for hints about the offending path)."
+      exit 1
+    fi
+
+    ${pkgs.libxslt.bin}/bin/xsltproc \
+      --stringparam revision '${revision}' \
+      -o intermediate.xml ${./options-to-docbook.xsl} $optionsXML
+    ${pkgs.libxslt.bin}/bin/xsltproc \
+      -o "$out" ${./postprocess-option-descriptions.xsl} intermediate.xml
+  '';
+}
diff --git a/nixos/doc/manual/options-to-docbook.xsl b/nixos/lib/make-options-doc/options-to-docbook.xsl
index 72ac89d4ff62..72ac89d4ff62 100644
--- a/nixos/doc/manual/options-to-docbook.xsl
+++ b/nixos/lib/make-options-doc/options-to-docbook.xsl
diff --git a/nixos/doc/manual/postprocess-option-descriptions.xsl b/nixos/lib/make-options-doc/postprocess-option-descriptions.xsl
index 1201c7612c2e..1201c7612c2e 100644
--- a/nixos/doc/manual/postprocess-option-descriptions.xsl
+++ b/nixos/lib/make-options-doc/postprocess-option-descriptions.xsl
diff --git a/nixos/modules/misc/nixpkgs.nix b/nixos/modules/misc/nixpkgs.nix
index e0c192246c0c..afb74581e239 100644
--- a/nixos/modules/misc/nixpkgs.nix
+++ b/nixos/modules/misc/nixpkgs.nix
@@ -19,7 +19,7 @@ let
       lhs = optCall lhs_ { inherit pkgs; };
       rhs = optCall rhs_ { inherit pkgs; };
     in
-    lhs // rhs //
+    recursiveUpdate lhs rhs //
     optionalAttrs (lhs ? packageOverrides) {
       packageOverrides = pkgs:
         optCall lhs.packageOverrides pkgs //
diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix
index df453aac9fef..c775345ba4c0 100644
--- a/nixos/modules/module-list.nix
+++ b/nixos/modules/module-list.nix
@@ -106,9 +106,14 @@
   ./programs/digitalbitbox/default.nix
   ./programs/dmrconfig.nix
   ./programs/environment.nix
+  ./programs/evince.nix
+  ./programs/file-roller.nix
   ./programs/firejail.nix
   ./programs/fish.nix
   ./programs/freetds.nix
+  ./programs/gnome-disks.nix
+  ./programs/gnome-documents.nix
+  ./programs/gpaste.nix
   ./programs/gnupg.nix
   ./programs/gphoto2.nix
   ./programs/iftop.nix
@@ -209,6 +214,7 @@
   ./services/backup/duplicity.nix
   ./services/backup/mysql-backup.nix
   ./services/backup/postgresql-backup.nix
+  ./services/backup/postgresql-wal-receiver.nix
   ./services/backup/restic.nix
   ./services/backup/restic-rest-server.nix
   ./services/backup/rsnapshot.nix
@@ -280,12 +286,8 @@
   ./services/desktops/pipewire.nix
   ./services/desktops/gnome3/at-spi2-core.nix
   ./services/desktops/gnome3/chrome-gnome-shell.nix
-  ./services/desktops/gnome3/evince.nix
   ./services/desktops/gnome3/evolution-data-server.nix
-  ./services/desktops/gnome3/file-roller.nix
   ./services/desktops/gnome3/glib-networking.nix
-  ./services/desktops/gnome3/gnome-disks.nix
-  ./services/desktops/gnome3/gnome-documents.nix
   ./services/desktops/gnome3/gnome-keyring.nix
   ./services/desktops/gnome3/gnome-online-accounts.nix
   ./services/desktops/gnome3/gnome-remote-desktop.nix
@@ -293,7 +295,6 @@
   ./services/desktops/gnome3/gnome-settings-daemon.nix
   ./services/desktops/gnome3/gnome-terminal-server.nix
   ./services/desktops/gnome3/gnome-user-share.nix
-  ./services/desktops/gnome3/gpaste.nix
   ./services/desktops/gnome3/gvfs.nix
   ./services/desktops/gnome3/rygel.nix
   ./services/desktops/gnome3/seahorse.nix
diff --git a/nixos/modules/services/desktops/gnome3/evince.nix b/nixos/modules/programs/evince.nix
index 5f040a16f067..473fddb09d02 100644
--- a/nixos/modules/services/desktops/gnome3/evince.nix
+++ b/nixos/modules/programs/evince.nix
@@ -6,14 +6,21 @@ with lib;
 
 {
 
+  # Added 2019-08-09
+  imports = [
+    (mkRenamedOptionModule
+      [ "services" "gnome3" "evince" "enable" ]
+      [ "programs" "evince" "enable" ])
+  ];
+
   ###### interface
 
   options = {
 
-    services.gnome3.evince = {
+    programs.evince = {
 
       enable = mkEnableOption
-        "systemd and dbus services for Evince, the GNOME document viewer";
+        "Evince, the GNOME document viewer";
 
     };
 
@@ -22,7 +29,7 @@ with lib;
 
   ###### implementation
 
-  config = mkIf config.services.gnome3.evince.enable {
+  config = mkIf config.programs.evince.enable {
 
     environment.systemPackages = [ pkgs.evince ];
 
diff --git a/nixos/modules/services/desktops/gnome3/file-roller.nix b/nixos/modules/programs/file-roller.nix
index 7fb558a98953..64f6a94e7641 100644
--- a/nixos/modules/services/desktops/gnome3/file-roller.nix
+++ b/nixos/modules/programs/file-roller.nix
@@ -6,11 +6,18 @@ with lib;
 
 {
 
+  # Added 2019-08-09
+  imports = [
+    (mkRenamedOptionModule
+      [ "services" "gnome3" "file-roller" "enable" ]
+      [ "programs" "file-roller" "enable" ])
+  ];
+
   ###### interface
 
   options = {
 
-    services.gnome3.file-roller = {
+    programs.file-roller = {
 
       enable = mkEnableOption "File Roller, an archive manager for GNOME";
 
@@ -21,7 +28,7 @@ with lib;
 
   ###### implementation
 
-  config = mkIf config.services.gnome3.file-roller.enable {
+  config = mkIf config.programs.file-roller.enable {
 
     environment.systemPackages = [ pkgs.gnome3.file-roller ];
 
diff --git a/nixos/modules/services/desktops/gnome3/gnome-disks.nix b/nixos/modules/programs/gnome-disks.nix
index 139534cdb892..1cf839a6ddb0 100644
--- a/nixos/modules/services/desktops/gnome3/gnome-disks.nix
+++ b/nixos/modules/programs/gnome-disks.nix
@@ -1,4 +1,4 @@
-# GNOME Disks daemon.
+# GNOME Disks.
 
 { config, pkgs, lib, ... }:
 
@@ -6,17 +6,24 @@ with lib;
 
 {
 
+  # Added 2019-08-09
+  imports = [
+    (mkRenamedOptionModule
+      [ "services" "gnome3" "gnome-disks" "enable" ]
+      [ "programs" "gnome-disks" "enable" ])
+  ];
+
   ###### interface
 
   options = {
 
-    services.gnome3.gnome-disks = {
+    programs.gnome-disks = {
 
       enable = mkOption {
         type = types.bool;
         default = false;
         description = ''
-          Whether to enable GNOME Disks daemon, a service designed to
+          Whether to enable GNOME Disks daemon, a program designed to
           be a UDisks2 graphical front-end.
         '';
       };
@@ -28,7 +35,7 @@ with lib;
 
   ###### implementation
 
-  config = mkIf config.services.gnome3.gnome-disks.enable {
+  config = mkIf config.programs.gnome-disks.enable {
 
     environment.systemPackages = [ pkgs.gnome3.gnome-disk-utility ];
 
diff --git a/nixos/modules/services/desktops/gnome3/gnome-documents.nix b/nixos/modules/programs/gnome-documents.nix
index f6efb6684240..bfa3d409ee30 100644
--- a/nixos/modules/services/desktops/gnome3/gnome-documents.nix
+++ b/nixos/modules/programs/gnome-documents.nix
@@ -1,4 +1,4 @@
-# GNOME Documents daemon.
+# GNOME Documents.
 
 { config, pkgs, lib, ... }:
 
@@ -6,17 +6,24 @@ with lib;
 
 {
 
+  # Added 2019-08-09
+  imports = [
+    (mkRenamedOptionModule
+      [ "services" "gnome3" "gnome-documents" "enable" ]
+      [ "programs" "gnome-documents" "enable" ])
+  ];
+
   ###### interface
 
   options = {
 
-    services.gnome3.gnome-documents = {
+    programs.gnome-documents = {
 
       enable = mkOption {
         type = types.bool;
         default = false;
         description = ''
-          Whether to enable GNOME Documents services, a document
+          Whether to enable GNOME Documents, a document
           manager application for GNOME.
         '';
       };
@@ -28,7 +35,7 @@ with lib;
 
   ###### implementation
 
-  config = mkIf config.services.gnome3.gnome-documents.enable {
+  config = mkIf config.programs.gnome-documents.enable {
 
     environment.systemPackages = [ pkgs.gnome3.gnome-documents ];
 
diff --git a/nixos/modules/services/desktops/gnome3/gpaste.nix b/nixos/modules/programs/gpaste.nix
index 5a8258775e0a..4f6deb77e5eb 100644
--- a/nixos/modules/services/desktops/gnome3/gpaste.nix
+++ b/nixos/modules/programs/gpaste.nix
@@ -1,12 +1,20 @@
-# GPaste daemon.
+# GPaste.
 { config, lib, pkgs, ... }:
 
 with lib;
 
 {
+
+  # Added 2019-08-09
+  imports = [
+    (mkRenamedOptionModule
+      [ "services" "gnome3" "gpaste" "enable" ]
+      [ "programs" "gpaste" "enable" ])
+  ];
+
   ###### interface
   options = {
-    services.gnome3.gpaste = {
+     programs.gpaste = {
       enable = mkOption {
         type = types.bool;
         default = false;
@@ -18,10 +26,9 @@ with lib;
   };
 
   ###### implementation
-  config = mkIf config.services.gnome3.gpaste.enable {
+  config = mkIf config.programs.gpaste.enable {
     environment.systemPackages = [ pkgs.gnome3.gpaste ];
     services.dbus.packages = [ pkgs.gnome3.gpaste ];
-    services.xserver.desktopManager.gnome3.sessionPath = [ pkgs.gnome3.gpaste ];
     systemd.packages = [ pkgs.gnome3.gpaste ];
   };
 }
diff --git a/nixos/modules/programs/nylas-mail.nix b/nixos/modules/programs/nylas-mail.nix
deleted file mode 100644
index 08a6cd0a6049..000000000000
--- a/nixos/modules/programs/nylas-mail.nix
+++ /dev/null
@@ -1,36 +0,0 @@
-{ config, lib, pkgs, ... }:
-
-with lib;
-
-let
-  cfg = config.services.nylas-mail;
-in {
-  ###### interface
-  options = {
-    services.nylas-mail = {
-
-      enable = mkEnableOption ''
-        nylas-mail - Open-source mail client built on the modern web with Electron, React, and Flux
-      '';
-
-      gnome3-keyring = mkOption {
-        type = types.bool;
-        default = true;
-        description = "Enable gnome3 keyring for nylas-mail.";
-      };
-    };
-  };
-
-
-  ###### implementation
-
-  config = mkIf cfg.enable {
-
-    environment.systemPackages = [ pkgs.nylas-mail-bin ];
-
-    services.gnome3.gnome-keyring = mkIf cfg.gnome3-keyring {
-      enable = true;
-    };
-
-  };
-}
diff --git a/nixos/modules/services/backup/postgresql-wal-receiver.nix b/nixos/modules/services/backup/postgresql-wal-receiver.nix
new file mode 100644
index 000000000000..d9a37037992e
--- /dev/null
+++ b/nixos/modules/services/backup/postgresql-wal-receiver.nix
@@ -0,0 +1,203 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  receiverSubmodule = {
+    options = {
+      postgresqlPackage = mkOption {
+        type = types.package;
+        example = literalExample "pkgs.postgresql_11";
+        description = ''
+          PostgreSQL package to use.
+        '';
+      };
+
+      directory = mkOption {
+        type = types.path;
+        example = literalExample "/mnt/pg_wal/main/";
+        description = ''
+          Directory to write the output to.
+        '';
+      };
+
+      statusInterval = mkOption {
+        type = types.int;
+        default = 10;
+        description = ''
+          Specifies the number of seconds between status packets sent back to the server.
+          This allows for easier monitoring of the progress from server.
+          A value of zero disables the periodic status updates completely,
+          although an update will still be sent when requested by the server, to avoid timeout disconnect.
+        '';
+      };
+
+      slot = mkOption {
+        type = types.str;
+        default = "";
+        example = "some_slot_name";
+        description = ''
+          Require <command>pg_receivewal</command> to use an existing replication slot (see
+          <link xlink:href="https://www.postgresql.org/docs/current/warm-standby.html#STREAMING-REPLICATION-SLOTS">Section 26.2.6 of the PostgreSQL manual</link>).
+          When this option is used, <command>pg_receivewal</command> will report a flush position to the server,
+          indicating when each segment has been synchronized to disk so that the server can remove that segment if it is not otherwise needed.
+
+          When the replication client of <command>pg_receivewal</command> is configured on the server as a synchronous standby,
+          then using a replication slot will report the flush position to the server, but only when a WAL file is closed.
+          Therefore, that configuration will cause transactions on the primary to wait for a long time and effectively not work satisfactorily.
+          The option <option>synchronous</option> must be specified in addition to make this work correctly.
+        '';
+      };
+
+      synchronous = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Flush the WAL data to disk immediately after it has been received.
+          Also send a status packet back to the server immediately after flushing, regardless of <option>statusInterval</option>.
+
+          This option should be specified if the replication client of <command>pg_receivewal</command> is configured on the server as a synchronous standby,
+          to ensure that timely feedback is sent to the server.
+        '';
+      };
+
+      compress = mkOption {
+        type = types.ints.between 0 9;
+        default = 0;
+        description = ''
+          Enables gzip compression of write-ahead logs, and specifies the compression level
+          (<literal>0</literal> through <literal>9</literal>, <literal>0</literal> being no compression and <literal>9</literal> being best compression).
+          The suffix <literal>.gz</literal> will automatically be added to all filenames.
+
+          This option requires PostgreSQL >= 10.
+        '';
+      };
+
+      connection = mkOption {
+        type = types.str;
+        example = "postgresql://user@somehost";
+        description = ''
+          Specifies parameters used to connect to the server, as a connection string.
+          See <link xlink:href="https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING">Section 34.1.1 of the PostgreSQL manual</link> for more information.
+
+          Because <command>pg_receivewal</command> doesn't connect to any particular database in the cluster,
+          database name in the connection string will be ignored.
+        '';
+      };
+
+      extraArgs = mkOption {
+        type = with types; listOf str;
+        default = [ ];
+        example = literalExample ''
+          [
+            "--no-sync"
+          ]
+        '';
+        description = ''
+          A list of extra arguments to pass to the <command>pg_receivewal</command> command.
+        '';
+      };
+
+      environment = mkOption {
+        type = with types; attrsOf str;
+        default = { };
+        example = literalExample ''
+          {
+            PGPASSFILE = "/private/passfile";
+            PGSSLMODE = "require";
+          }
+        '';
+        description = ''
+          Environment variables passed to the service.
+          Usable parameters are listed in <link xlink:href="https://www.postgresql.org/docs/current/libpq-envars.html">Section 34.14 of the PostgreSQL manual</link>.
+        '';
+      };
+    };
+  };
+
+in {
+  options = {
+    services.postgresqlWalReceiver = {
+      receivers = mkOption {
+        type = with types; attrsOf (submodule receiverSubmodule);
+        default = { };
+        example = literalExample ''
+          {
+            main = {
+              postgresqlPackage = pkgs.postgresql_11;
+              directory = /mnt/pg_wal/main/;
+              slot = "main_wal_receiver";
+              connection = "postgresql://user@somehost";
+            };
+          }
+        '';
+        description = ''
+          PostgreSQL WAL receivers.
+          Stream write-ahead logs from a PostgreSQL server using <command>pg_receivewal</command> (formerly <command>pg_receivexlog</command>).
+          See <link xlink:href="https://www.postgresql.org/docs/current/app-pgreceivewal.html">the man page</link> for more information.
+        '';
+      };
+    };
+  };
+
+  config = let
+    receivers = config.services.postgresqlWalReceiver.receivers;
+  in mkIf (receivers != { }) {
+    users = {
+      users.postgres = {
+        uid = config.ids.uids.postgres;
+        group = "postgres";
+        description = "PostgreSQL server user";
+      };
+
+      groups.postgres = {
+        gid = config.ids.gids.postgres;
+      };
+    };
+
+    assertions = concatLists (attrsets.mapAttrsToList (name: config: [
+      {
+        assertion = config.compress > 0 -> versionAtLeast config.postgresqlPackage.version "10";
+        message = "Invalid configuration for WAL receiver \"${name}\": compress requires PostgreSQL version >= 10.";
+      }
+    ]) receivers);
+
+    systemd.tmpfiles.rules = mapAttrsToList (name: config: ''
+      d ${escapeShellArg config.directory} 0750 postgres postgres - -
+    '') receivers;
+
+    systemd.services = with attrsets; mapAttrs' (name: config: nameValuePair "postgresql-wal-receiver-${name}" {
+      description = "PostgreSQL WAL receiver (${name})";
+      wantedBy = [ "multi-user.target" ];
+
+      serviceConfig = {
+        User = "postgres";
+        Group = "postgres";
+        KillSignal = "SIGINT";
+        Restart = "always";
+        RestartSec = 30;
+      };
+
+      inherit (config) environment;
+
+      script = let
+        receiverCommand = postgresqlPackage:
+         if (versionAtLeast postgresqlPackage.version "10")
+           then "${postgresqlPackage}/bin/pg_receivewal"
+           else "${postgresqlPackage}/bin/pg_receivexlog";
+      in ''
+        ${receiverCommand config.postgresqlPackage} \
+          --no-password \
+          --directory=${escapeShellArg config.directory} \
+          --status-interval=${toString config.statusInterval} \
+          --dbname=${escapeShellArg config.connection} \
+          ${optionalString (config.compress > 0) "--compress=${toString config.compress}"} \
+          ${optionalString (config.slot != "") "--slot=${escapeShellArg config.slot}"} \
+          ${optionalString config.synchronous "--synchronous"} \
+          ${concatStringsSep " " config.extraArgs}
+      '';
+    }) receivers;
+  };
+
+  meta.maintainers = with maintainers; [ pacien ];
+}
diff --git a/nixos/modules/services/databases/couchdb.nix b/nixos/modules/services/databases/couchdb.nix
index 5ddf8ba4bfbd..77e404116c8a 100644
--- a/nixos/modules/services/databases/couchdb.nix
+++ b/nixos/modules/services/databases/couchdb.nix
@@ -160,7 +160,7 @@ in {
 
     systemd.tmpfiles.rules = [
       "d '${dirOf cfg.uriFile}' - ${cfg.user} ${cfg.group} - -"
-      "d '${dirOf cfg.logFile}' - ${cfg.user} ${cfg.group} - -"
+      "f '${cfg.logFile}' - ${cfg.user} ${cfg.group} - -"
       "d '${cfg.databaseDir}' -  ${cfg.user} ${cfg.group} - -"
       "d '${cfg.viewIndexDir}' -  ${cfg.user} ${cfg.group} - -"
     ];
@@ -169,11 +169,9 @@ in {
       description = "CouchDB Server";
       wantedBy = [ "multi-user.target" ];
 
-      preStart =
-        ''
+      preStart = ''
         touch ${cfg.configFile}
-        touch -a ${cfg.logFile}
-        '';
+      '';
 
       environment = mkIf useVersion2 {
         # we are actually specifying 4 configuration files:
diff --git a/nixos/modules/services/databases/postgresql.nix b/nixos/modules/services/databases/postgresql.nix
index 7ff899970ccd..10250bb5193a 100644
--- a/nixos/modules/services/databases/postgresql.nix
+++ b/nixos/modules/services/databases/postgresql.nix
@@ -330,13 +330,13 @@ in
             fi
           '' + optionalString (cfg.ensureDatabases != []) ''
             ${concatMapStrings (database: ''
-              $PSQL -tAc "SELECT 1 FROM pg_database WHERE datname = '${database}'" | grep -q 1 || $PSQL -tAc "CREATE DATABASE ${database}"
+              $PSQL -tAc "SELECT 1 FROM pg_database WHERE datname = '${database}'" | grep -q 1 || $PSQL -tAc 'CREATE DATABASE "${database}"'
             '') cfg.ensureDatabases}
           '' + ''
             ${concatMapStrings (user: ''
               $PSQL -tAc "SELECT 1 FROM pg_roles WHERE rolname='${user.name}'" | grep -q 1 || $PSQL -tAc "CREATE USER ${user.name}"
               ${concatStringsSep "\n" (mapAttrsToList (database: permission: ''
-                $PSQL -tAc "GRANT ${permission} ON ${database} TO ${user.name}"
+                $PSQL -tAc 'GRANT ${permission} ON ${database} TO ${user.name}'
               '') user.ensurePermissions)}
             '') cfg.ensureUsers}
           '';
diff --git a/nixos/modules/services/monitoring/grafana.nix b/nixos/modules/services/monitoring/grafana.nix
index c2f6b585d493..bf1084eecc3a 100644
--- a/nixos/modules/services/monitoring/grafana.nix
+++ b/nixos/modules/services/monitoring/grafana.nix
@@ -503,12 +503,12 @@ in {
         message = "Cannot set both adminPassword and adminPasswordFile";
       }
       {
-        assertion = cfg.security.secretKeyFile != opt.security.secretKeyFile.default -> cfg.security.secretKeyFile == null;
+        assertion = cfg.security.secretKey != opt.security.secretKey.default -> cfg.security.secretKeyFile == null;
         message = "Cannot set both secretKey and secretKeyFile";
       }
       {
         assertion = cfg.smtp.password != opt.smtp.password.default -> cfg.smtp.passwordFile == null;
-        message = "Cannot set both password and secretKeyFile";
+        message = "Cannot set both password and passwordFile";
       }
     ];
 
diff --git a/nixos/modules/services/x11/desktop-managers/gnome3.nix b/nixos/modules/services/x11/desktop-managers/gnome3.nix
index cd7502421255..5e1e652a5089 100644
--- a/nixos/modules/services/x11/desktop-managers/gnome3.nix
+++ b/nixos/modules/services/x11/desktop-managers/gnome3.nix
@@ -123,12 +123,8 @@ in {
     services.dleyna-renderer.enable = mkDefault true;
     services.dleyna-server.enable = mkDefault true;
     services.gnome3.at-spi2-core.enable = true;
-    services.gnome3.evince.enable = mkDefault true;
     services.gnome3.evolution-data-server.enable = true;
-    services.gnome3.file-roller.enable = mkDefault true;
     services.gnome3.glib-networking.enable = true;
-    services.gnome3.gnome-disks.enable = mkDefault true;
-    services.gnome3.gnome-documents.enable = mkDefault true;
     services.gnome3.gnome-keyring.enable = true;
     services.gnome3.gnome-online-accounts.enable = mkDefault true;
     services.gnome3.gnome-remote-desktop.enable = mkDefault true;
@@ -157,6 +153,12 @@ in {
     xdg.portal.enable = true;
     xdg.portal.extraPortals = [ pkgs.xdg-desktop-portal-gtk ];
 
+    # Enable default programs
+    programs.evince.enable = mkDefault true;
+    programs.file-roller.enable = mkDefault true;
+    programs.gnome-disks.enable = mkDefault true;
+    programs.gnome-documents.enable = mkDefault true;
+
     # If gnome3 is installed, build vim for gtk3 too.
     nixpkgs.config.vim.gui = "gtk3";
 
diff --git a/nixos/release-combined.nix b/nixos/release-combined.nix
index b9a9515f94ef..7146aebf54be 100644
--- a/nixos/release-combined.nix
+++ b/nixos/release-combined.nix
@@ -68,8 +68,9 @@ in rec {
         nixos.tests.chromium.x86_64-linux or []
         (all nixos.tests.firefox)
         (all nixos.tests.firewall)
-        (except ["aarch64-linux"] nixos.tests.gnome3)
-        (except ["aarch64-linux"] nixos.tests.pantheon)
+        (all nixos.tests.gnome3-xorg)
+        (all nixos.tests.gnome3)
+        (all nixos.tests.pantheon)
         nixos.tests.installer.zfsroot.x86_64-linux or [] # ZFS is 64bit only
         (except ["aarch64-linux"] nixos.tests.installer.lvm)
         (except ["aarch64-linux"] nixos.tests.installer.luksroot)
@@ -103,7 +104,7 @@ in rec {
         #(all nixos.tests.keymap.neo)
         #(all nixos.tests.keymap.qwertz)
         (all nixos.tests.plasma5)
-        #(all nixos.tests.lightdm)
+        (all nixos.tests.lightdm)
         (all nixos.tests.login)
         (all nixos.tests.misc)
         (all nixos.tests.mutableUsers)
diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix
index 25dd9f3f4283..c24c8ae61a58 100644
--- a/nixos/tests/all-tests.nix
+++ b/nixos/tests/all-tests.nix
@@ -56,7 +56,7 @@ in
   containers-physical_interfaces = handleTest ./containers-physical_interfaces.nix {};
   containers-restart_networking = handleTest ./containers-restart_networking.nix {};
   containers-tmpfs = handleTest ./containers-tmpfs.nix {};
-  #couchdb = handleTest ./couchdb.nix {}; # spidermonkey-1.8.5 is marked as broken
+  couchdb = handleTest ./couchdb.nix {};
   deluge = handleTest ./deluge.nix {};
   dhparams = handleTest ./dhparams.nix {};
   dnscrypt-proxy = handleTestOn ["x86_64-linux"] ./dnscrypt-proxy.nix {};
@@ -93,8 +93,8 @@ in
   gitlab = handleTest ./gitlab.nix {};
   gitolite = handleTest ./gitolite.nix {};
   gjs = handleTest ./gjs.nix {};
-  gnome3 = handleTestOn ["x86_64-linux"] ./gnome3.nix {}; # libsmbios is unsupported on aarch64
-  gnome3-gdm = handleTestOn ["x86_64-linux"] ./gnome3-gdm.nix {}; # libsmbios is unsupported on aarch64
+  gnome3-xorg = handleTest ./gnome3-xorg.nix {};
+  gnome3 = handleTest ./gnome3.nix {};
   gocd-agent = handleTest ./gocd-agent.nix {};
   gocd-server = handleTest ./gocd-server.nix {};
   google-oslogin = handleTest ./google-oslogin {};
@@ -139,7 +139,7 @@ in
   ldap = handleTest ./ldap.nix {};
   leaps = handleTest ./leaps.nix {};
   lidarr = handleTest ./lidarr.nix {};
-  #lightdm = handleTest ./lightdm.nix {};
+  lightdm = handleTest ./lightdm.nix {};
   limesurvey = handleTest ./limesurvey.nix {};
   login = handleTest ./login.nix {};
   loki = handleTest ./loki.nix {};
@@ -210,6 +210,7 @@ in
   plotinus = handleTest ./plotinus.nix {};
   postgis = handleTest ./postgis.nix {};
   postgresql = handleTest ./postgresql.nix {};
+  postgresql-wal-receiver = handleTest ./postgresql-wal-receiver.nix {};
   powerdns = handleTest ./powerdns.nix {};
   predictable-interface-names = handleTest ./predictable-interface-names.nix {};
   printing = handleTest ./printing.nix {};
diff --git a/nixos/tests/gnome3-gdm.nix b/nixos/tests/gnome3-gdm.nix
deleted file mode 100644
index c2808d87d99d..000000000000
--- a/nixos/tests/gnome3-gdm.nix
+++ /dev/null
@@ -1,63 +0,0 @@
-import ./make-test.nix ({ pkgs, ...} : {
-  name = "gnome3-gdm";
-  meta = with pkgs.stdenv.lib.maintainers; {
-    maintainers = [ lethalman ];
-  };
-
-  machine =
-    { ... }:
-
-    { imports = [ ./common/user-account.nix ];
-
-      services.xserver.enable = true;
-
-      services.xserver.displayManager.gdm = {
-        enable = true;
-        autoLogin = {
-          enable = true;
-          user = "alice";
-        };
-      };
-      services.xserver.desktopManager.gnome3.enable = true;
-
-      virtualisation.memorySize = 1024;
-    };
-
-  testScript = let
-    # Keep line widths somewhat managable
-    bus = "DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus";
-    gdbus = "${bus} gdbus";
-    # Call javascript in gnome shell, returns a tuple (success, output), where
-    # `success` is true if the dbus call was successful and output is what the
-    # javascript evaluates to.
-    eval = "call --session -d org.gnome.Shell -o /org/gnome/Shell -m org.gnome.Shell.Eval";
-    # False when startup is done
-    startingUp = "${gdbus} ${eval} Main.layoutManager._startingUp";
-    # Hopefully gnome-terminal's wm class
-    wmClass = "${gdbus} ${eval} global.display.focus_window.wm_class";
-  in ''
-      # wait for gdm to start
-      $machine->waitForUnit("display-manager.service");
-
-      # wait for alice to be logged in
-      $machine->waitForUnit("default.target","alice");
-
-      # Check that logging in has given the user ownership of devices.
-      $machine->succeed("getfacl /dev/snd/timer | grep -q alice");
-
-      # Wait for the wayland server
-      $machine->waitForFile("/run/user/1000/wayland-0");
-
-      # Wait for gnome shell, correct output should be "(true, 'false')"
-      $machine->waitUntilSucceeds("su - alice -c '${startingUp} | grep -q true,..false'");
-
-      # open a terminal
-      $machine->succeed("su - alice -c '${bus} gnome-terminal'");
-      # and check it's there
-      $machine->waitUntilSucceeds("su - alice -c '${wmClass} | grep -q gnome-terminal-server'");
-
-      # wait to get a nice screenshot
-      $machine->sleep(20);
-      $machine->screenshot("screen");
-    '';
-})
diff --git a/nixos/tests/gnome3-xorg.nix b/nixos/tests/gnome3-xorg.nix
new file mode 100644
index 000000000000..f12361da0372
--- /dev/null
+++ b/nixos/tests/gnome3-xorg.nix
@@ -0,0 +1,41 @@
+import ./make-test.nix ({ pkgs, ...} : {
+  name = "gnome3-xorg";
+  meta = with pkgs.stdenv.lib.maintainers; {
+    maintainers = pkgs.gnome3.maintainers;
+  };
+
+  machine =
+    { ... }:
+
+    { imports = [ ./common/user-account.nix ];
+
+      services.xserver.enable = true;
+
+      services.xserver.displayManager.gdm.enable = false;
+      services.xserver.displayManager.lightdm.enable = true;
+      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-xorg";
+
+      virtualisation.memorySize = 1024;
+    };
+
+  testScript =
+    ''
+      $machine->waitForX;
+
+      # wait for alice to be logged in
+      $machine->waitForUnit("default.target","alice");
+
+      # Check that logging in has given the user ownership of devices.
+      $machine->succeed("getfacl /dev/snd/timer | grep -q alice");
+
+      $machine->succeed("su - alice -c 'DISPLAY=:0.0 gnome-terminal &'");
+      $machine->succeed("xauth merge ~alice/.Xauthority");
+      $machine->waitForWindow(qr/alice.*machine/);
+      $machine->succeed("timeout 900 bash -c 'while read msg; do if [[ \$msg =~ \"GNOME Shell started\" ]]; then break; fi; done < <(journalctl -f)'");
+      $machine->sleep(10);
+      $machine->screenshot("screen");
+    '';
+})
diff --git a/nixos/tests/gnome3.nix b/nixos/tests/gnome3.nix
index b58c9e5a0e32..b6fe602a7327 100644
--- a/nixos/tests/gnome3.nix
+++ b/nixos/tests/gnome3.nix
@@ -1,7 +1,7 @@
 import ./make-test.nix ({ pkgs, ...} : {
   name = "gnome3";
   meta = with pkgs.stdenv.lib.maintainers; {
-    maintainers = [ domenkozar eelco lethalman ];
+    maintainers = pkgs.gnome3.maintainers;
   };
 
   machine =
@@ -11,19 +11,34 @@ import ./make-test.nix ({ pkgs, ...} : {
 
       services.xserver.enable = true;
 
-      services.xserver.displayManager.gdm.enable = false;
-      services.xserver.displayManager.lightdm.enable = true;
-      services.xserver.displayManager.lightdm.autoLogin.enable = true;
-      services.xserver.displayManager.lightdm.autoLogin.user = "alice";
+      services.xserver.displayManager.gdm = {
+        enable = true;
+        autoLogin = {
+          enable = true;
+          user = "alice";
+        };
+      };
+
       services.xserver.desktopManager.gnome3.enable = true;
-      services.xserver.desktopManager.default = "gnome-xorg";
 
       virtualisation.memorySize = 1024;
     };
 
-  testScript =
-    ''
-      $machine->waitForX;
+  testScript = let
+    # Keep line widths somewhat managable
+    bus = "DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus";
+    gdbus = "${bus} gdbus";
+    # Call javascript in gnome shell, returns a tuple (success, output), where
+    # `success` is true if the dbus call was successful and output is what the
+    # javascript evaluates to.
+    eval = "call --session -d org.gnome.Shell -o /org/gnome/Shell -m org.gnome.Shell.Eval";
+    # False when startup is done
+    startingUp = "${gdbus} ${eval} Main.layoutManager._startingUp";
+    # Hopefully gnome-terminal's wm class
+    wmClass = "${gdbus} ${eval} global.display.focus_window.wm_class";
+  in ''
+      # wait for gdm to start
+      $machine->waitForUnit("display-manager.service");
 
       # wait for alice to be logged in
       $machine->waitForUnit("default.target","alice");
@@ -31,11 +46,19 @@ import ./make-test.nix ({ pkgs, ...} : {
       # Check that logging in has given the user ownership of devices.
       $machine->succeed("getfacl /dev/snd/timer | grep -q alice");
 
-      $machine->succeed("su - alice -c 'DISPLAY=:0.0 gnome-terminal &'");
-      $machine->succeed("xauth merge ~alice/.Xauthority");
-      $machine->waitForWindow(qr/alice.*machine/);
-      $machine->succeed("timeout 900 bash -c 'while read msg; do if [[ \$msg =~ \"GNOME Shell started\" ]]; then break; fi; done < <(journalctl -f)'");
-      $machine->sleep(10);
+      # Wait for the wayland server
+      $machine->waitForFile("/run/user/1000/wayland-0");
+
+      # Wait for gnome shell, correct output should be "(true, 'false')"
+      $machine->waitUntilSucceeds("su - alice -c '${startingUp} | grep -q true,..false'");
+
+      # open a terminal
+      $machine->succeed("su - alice -c '${bus} gnome-terminal'");
+      # and check it's there
+      $machine->waitUntilSucceeds("su - alice -c '${wmClass} | grep -q gnome-terminal-server'");
+
+      # wait to get a nice screenshot
+      $machine->sleep(20);
       $machine->screenshot("screen");
     '';
 })
diff --git a/nixos/tests/lightdm.nix b/nixos/tests/lightdm.nix
index 8a9a7408d292..c805f1ed9f3c 100644
--- a/nixos/tests/lightdm.nix
+++ b/nixos/tests/lightdm.nix
@@ -1,7 +1,7 @@
 import ./make-test.nix ({ pkgs, ...} : {
   name = "lightdm";
   meta = with pkgs.stdenv.lib.maintainers; {
-    maintainers = [ aszlig ];
+    maintainers = [ aszlig worldofpeace ];
   };
 
   machine = { ... }: {
diff --git a/nixos/tests/postgresql-wal-receiver.nix b/nixos/tests/postgresql-wal-receiver.nix
new file mode 100644
index 000000000000..791b041ba95b
--- /dev/null
+++ b/nixos/tests/postgresql-wal-receiver.nix
@@ -0,0 +1,86 @@
+{ system ? builtins.currentSystem
+, config ? { }
+, pkgs ? import ../.. { inherit system config; } }:
+
+with import ../lib/testing.nix { inherit system pkgs; };
+with pkgs.lib;
+
+let
+  postgresqlDataDir = "/var/db/postgresql/test";
+  replicationUser = "wal_receiver_user";
+  replicationSlot = "wal_receiver_slot";
+  replicationConn = "postgresql://${replicationUser}@localhost";
+  baseBackupDir = "/tmp/pg_basebackup";
+  walBackupDir = "/tmp/pg_wal";
+  recoveryConf = pkgs.writeText "recovery.conf" ''
+    restore_command = 'cp ${walBackupDir}/%f %p'
+  '';
+
+  makePostgresqlWalReceiverTest = subTestName: postgresqlPackage: makeTest {
+    name = "postgresql-wal-receiver-${subTestName}";
+    meta.maintainers = with maintainers; [ pacien ];
+
+    machine = { ... }: {
+      services.postgresql = {
+        package = postgresqlPackage;
+        enable = true;
+        dataDir = postgresqlDataDir;
+        extraConfig = ''
+          wal_level = archive # alias for replica on pg >= 9.6
+          max_wal_senders = 10
+          max_replication_slots = 10
+        '';
+        authentication = ''
+          host replication ${replicationUser} all trust
+        '';
+        initialScript = pkgs.writeText "init.sql" ''
+          create user ${replicationUser} replication;
+          select * from pg_create_physical_replication_slot('${replicationSlot}');
+        '';
+      };
+
+      services.postgresqlWalReceiver.receivers.main = {
+        inherit postgresqlPackage;
+        connection = replicationConn;
+        slot = replicationSlot;
+        directory = walBackupDir;
+      };
+    };
+
+    testScript = ''
+      # make an initial base backup
+      $machine->waitForUnit('postgresql');
+      $machine->waitForUnit('postgresql-wal-receiver-main');
+      # WAL receiver healthchecks PG every 5 seconds, so let's be sure they have connected each other
+      # required only for 9.4
+      $machine->sleep(5);
+      $machine->succeed('${postgresqlPackage}/bin/pg_basebackup --dbname=${replicationConn} --pgdata=${baseBackupDir}');
+
+      # create a dummy table with 100 records
+      $machine->succeed('sudo -u postgres psql --command="create table dummy as select * from generate_series(1, 100) as val;"');
+
+      # stop postgres and destroy data
+      $machine->systemctl('stop postgresql');
+      $machine->systemctl('stop postgresql-wal-receiver-main');
+      $machine->succeed('rm -r ${postgresqlDataDir}/{base,global,pg_*}');
+
+      # restore the base backup
+      $machine->succeed('cp -r ${baseBackupDir}/* ${postgresqlDataDir} && chown postgres:postgres -R ${postgresqlDataDir}');
+
+      # prepare WAL and recovery
+      $machine->succeed('chmod a+rX -R ${walBackupDir}');
+      $machine->execute('for part in ${walBackupDir}/*.partial; do mv $part ''${part%%.*}; done'); # make use of partial segments too
+      $machine->succeed('cp ${recoveryConf} ${postgresqlDataDir}/recovery.conf && chmod 666 ${postgresqlDataDir}/recovery.conf');
+
+      # replay WAL
+      $machine->systemctl('start postgresql');
+      $machine->waitForFile('${postgresqlDataDir}/recovery.done');
+      $machine->systemctl('restart postgresql');
+      $machine->waitForUnit('postgresql');
+
+      # check that our records have been restored
+      $machine->succeed('test $(sudo -u postgres psql --pset="pager=off" --tuples-only --command="select count(distinct val) from dummy;") -eq 100');
+    '';
+  };
+
+in mapAttrs makePostgresqlWalReceiverTest (import ../../pkgs/servers/sql/postgresql pkgs)
diff --git a/nixos/tests/syncthing-init.nix b/nixos/tests/syncthing-init.nix
index 811a466ff941..0de76b688bdc 100644
--- a/nixos/tests/syncthing-init.nix
+++ b/nixos/tests/syncthing-init.nix
@@ -22,9 +22,13 @@ in {
   };
 
   testScript = ''
+    my $config;
+
     $machine->waitForUnit("syncthing-init.service");
-    $machine->succeed("cat /var/lib/syncthing/config.xml") =~ /${testId}/ or die;
-    $machine->succeed("cat /var/lib/syncthing/config.xml") =~ /testFolder/ or die;
+    $config = $machine->succeed("cat /var/lib/syncthing/.config/syncthing/config.xml");
+   
+    $config =~ /${testId}/ or die;
+    $config =~ /testFolder/ or die;
   '';
 })