summary refs log tree commit diff
path: root/nixos
diff options
context:
space:
mode:
Diffstat (limited to 'nixos')
-rw-r--r--nixos/doc/manual/release-notes/rl-1903.xml6
-rw-r--r--nixos/lib/make-iso9660-image.sh5
-rw-r--r--nixos/lib/testing.nix22
-rw-r--r--nixos/modules/config/appstream.nix25
-rw-r--r--nixos/modules/config/xdg/sounds.nix22
-rw-r--r--nixos/modules/hardware/bladeRF.nix28
-rw-r--r--nixos/modules/installer/cd-dvd/iso-image.nix78
-rw-r--r--nixos/modules/module-list.nix3
-rw-r--r--nixos/modules/programs/bash/bash.nix7
-rw-r--r--nixos/modules/programs/zsh/oh-my-zsh.xml8
-rw-r--r--nixos/modules/services/databases/clickhouse.nix5
-rw-r--r--nixos/modules/services/hardware/bluetooth.nix7
-rw-r--r--nixos/modules/services/networking/networkmanager.nix2
-rw-r--r--nixos/modules/services/networking/prosody.nix1
-rw-r--r--nixos/modules/services/networking/shairport-sync.nix2
-rw-r--r--nixos/modules/services/web-apps/nextcloud.nix2
-rw-r--r--nixos/modules/services/web-apps/nextcloud.xml99
-rw-r--r--nixos/modules/services/web-servers/apache-httpd/limesurvey.nix2
-rw-r--r--nixos/modules/services/web-servers/apache-httpd/owncloud.nix608
-rw-r--r--nixos/release.nix2
-rw-r--r--nixos/tests/all-tests.nix2
-rw-r--r--nixos/tests/clickhouse.nix25
-rw-r--r--nixos/tests/gitlab.nix2
-rw-r--r--nixos/tests/home-assistant.nix8
-rw-r--r--nixos/tests/kubernetes/kubernetes-common.nix1
-rw-r--r--nixos/tests/owncloud.nix39
26 files changed, 318 insertions, 693 deletions
diff --git a/nixos/doc/manual/release-notes/rl-1903.xml b/nixos/doc/manual/release-notes/rl-1903.xml
index 9405bf063d5..69e94fbccc5 100644
--- a/nixos/doc/manual/release-notes/rl-1903.xml
+++ b/nixos/doc/manual/release-notes/rl-1903.xml
@@ -364,6 +364,12 @@
        of maintainers.
      </para>
    </listitem>
+   <listitem>
+     <para>
+       The owncloud server packages and httpd subservice module were removed
+       from nixpkgs due to the lack of maintainers.
+     </para>
+   </listitem>
   </itemizedlist>
  </section>
 </section>
diff --git a/nixos/lib/make-iso9660-image.sh b/nixos/lib/make-iso9660-image.sh
index 45cdef1ef4d..b7b1ab52a63 100644
--- a/nixos/lib/make-iso9660-image.sh
+++ b/nixos/lib/make-iso9660-image.sh
@@ -47,7 +47,8 @@ if test -n "$bootable"; then
 
     isoBootFlags="-eltorito-boot ${bootImage}
                   -eltorito-catalog .boot.cat
-                  -no-emul-boot -boot-load-size 4 -boot-info-table"
+                  -no-emul-boot -boot-load-size 4 -boot-info-table
+                  --sort-weight 1 /isolinux" # Make sure isolinux is near the beginning of the ISO
 fi
 
 if test -n "$usbBootable"; then
@@ -112,7 +113,7 @@ xorriso="xorriso
  -r
  -path-list pathlist
  --sort-weight 0 /
- --sort-weight 1 /isolinux" # Make sure isolinux is near the beginning of the ISO
+"
 
 $xorriso -output $out/iso/$isoName
 
diff --git a/nixos/lib/testing.nix b/nixos/lib/testing.nix
index 0bb3fd53e85..c0b4041d7e3 100644
--- a/nixos/lib/testing.nix
+++ b/nixos/lib/testing.nix
@@ -116,7 +116,7 @@ in rec {
 
       vms = map (m: m.config.system.build.vm) (lib.attrValues nodes);
 
-      ocrProg = tesseract_4.override { enableLanguages = [ "eng" ]; };
+      ocrProg = tesseract4.override { enableLanguages = [ "eng" ]; };
 
       imagemagick_tiff = imagemagick_light.override { inherit libtiff; };
 
@@ -156,9 +156,23 @@ in rec {
       test = passMeta (runTests driver);
       report = passMeta (releaseTools.gcovReport { coverageRuns = [ test ]; });
 
-    in (if makeCoverageReport then report else test) // {
-      inherit nodes driver test;
-    };
+      nodeNames = builtins.attrNames nodes;
+      invalidNodeNames = lib.filter
+        (node: builtins.match "^[A-z_][A-z0-9_]+$" node == null) nodeNames;
+
+    in
+      if lib.length invalidNodeNames > 0 then
+        throw ''
+          Cannot create machines out of (${lib.concatStringsSep ", " invalidNodeNames})!
+          All machines are referenced as perl variables in the testing framework which will break the
+          script when special characters are used.
+
+          Please stick to alphanumeric chars and underscores as separation.
+        ''
+      else
+        (if makeCoverageReport then report else test) // {
+          inherit nodes driver test;
+        };
 
   runInMachine =
     { drv
diff --git a/nixos/modules/config/appstream.nix b/nixos/modules/config/appstream.nix
new file mode 100644
index 00000000000..483ac9c3cd7
--- /dev/null
+++ b/nixos/modules/config/appstream.nix
@@ -0,0 +1,25 @@
+{ config, lib, ... }:
+
+with lib;
+{
+  options = {
+    appstream.enable = mkOption {
+      type = types.bool;
+      default = true;
+      description = ''
+        Whether to install files to support the 
+        <link xlink:href="https://www.freedesktop.org/software/appstream/docs/index.html">AppStream metadata specification</link>.
+      '';
+    };
+  };
+
+  config = mkIf config.appstream.enable {
+    environment.pathsToLink = [ 
+      # per component metadata
+      "/share/metainfo" 
+      # legacy path for above
+      "/share/appdata" 
+    ];
+  };
+
+}
diff --git a/nixos/modules/config/xdg/sounds.nix b/nixos/modules/config/xdg/sounds.nix
new file mode 100644
index 00000000000..148240d631c
--- /dev/null
+++ b/nixos/modules/config/xdg/sounds.nix
@@ -0,0 +1,22 @@
+{ config, lib, ... }:
+
+with lib;
+{
+  options = {
+    xdg.sounds.enable = mkOption {
+      type = types.bool;
+      default = true;
+      description = ''
+        Whether to install files to support the
+        <link xlink:href="https://www.freedesktop.org/wiki/Specifications/sound-theme-spec/">XDG Sound Theme specification</link>.
+      '';
+    };
+  };
+
+  config = mkIf config.xdg.sounds.enable {
+    environment.pathsToLink = [
+      "/share/sounds"
+    ];
+  };
+
+}
diff --git a/nixos/modules/hardware/bladeRF.nix b/nixos/modules/hardware/bladeRF.nix
new file mode 100644
index 00000000000..92544347714
--- /dev/null
+++ b/nixos/modules/hardware/bladeRF.nix
@@ -0,0 +1,28 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.hardware.bladeRF;
+
+in
+
+{
+  options.hardware.bladeRF = {
+    enable = mkOption {
+      type = types.bool;
+      default = false;
+      description = ''
+        Enables udev rules for BladeRF devices. By default grants access
+        to users in the "bladerf" group. You may want to install the
+        libbladeRF package.
+      '';
+    };
+
+  };
+
+  config = mkIf cfg.enable {
+    services.udev.packages = [ pkgs.libbladeRF ];
+    users.groups.bladerf = {};
+  };
+}
\ No newline at end of file
diff --git a/nixos/modules/installer/cd-dvd/iso-image.nix b/nixos/modules/installer/cd-dvd/iso-image.nix
index aa8003fef2c..9475da23b1f 100644
--- a/nixos/modules/installer/cd-dvd/iso-image.nix
+++ b/nixos/modules/installer/cd-dvd/iso-image.nix
@@ -50,7 +50,7 @@ let
     finalCfg = {
       name = "NixOS ${config.system.nixos.label}${config.isoImage.appendToMenuLabel}";
       params = "init=${config.system.build.toplevel}/init ${additional} ${toString config.boot.kernelParams}";
-      image = "/boot/bzImage";
+      image = "/boot/${config.system.boot.loader.kernelFile}";
       initrd = "/boot/initrd";
     };
   in
@@ -163,7 +163,7 @@ let
       cp -v ${pkgs.refind}/share/refind/refind_x64.efi $out/EFI/boot/
       ''
     else
-      "# No refind for ia32"
+      "# No refind for ${targetArch}"
   ;
 
   grubMenuCfg = ''
@@ -222,18 +222,34 @@ let
   efiDir = pkgs.runCommand "efi-directory" {} ''
     mkdir -p $out/EFI/boot/
 
+    # ALWAYS required modules.
     MODULES="fat iso9660 part_gpt part_msdos \
              normal boot linux configfile loopback chain halt \
-             efifwsetup efi_gop efi_uga \
+             efifwsetup efi_gop \
              ls search search_label search_fs_uuid search_fs_file \
              gfxmenu gfxterm gfxterm_background gfxterm_menu test all_video loadenv \
              exfat ext2 ntfs btrfs hfsplus udf \
              videoinfo png \
              echo serial \
             "
+
+    echo "Building GRUB with modules:"
+    for mod in $MODULES; do
+      echo " - $mod"
+    done
+
+    # Modules that may or may not be available per-platform.
+    echo "Adding additional modules:"
+    for mod in efi_uga; do
+      if [ -f ${pkgs.grub2_efi}/lib/grub/${pkgs.grub2_efi.grubTarget}/$mod.mod ]; then
+        echo " - $mod"
+        MODULES+=" $mod"
+      fi
+    done
+
     # Make our own efi program, we can't rely on "grub-install" since it seems to
     # probe for devices, even with --skip-fs-probe.
-    ${pkgs.grub2_efi}/bin/grub-mkimage -o $out/EFI/boot/${if targetArch == "x64" then "bootx64" else "bootia32"}.efi -p /EFI/boot -O ${if targetArch == "x64" then "x86_64" else "i386"}-efi \
+    ${pkgs.grub2_efi}/bin/grub-mkimage -o $out/EFI/boot/boot${targetArch}.efi -p /EFI/boot -O ${pkgs.grub2_efi.grubTarget} \
       $MODULES
     cp ${pkgs.grub2_efi}/share/grub/unicode.pf2 $out/EFI/boot/
 
@@ -344,12 +360,19 @@ let
       ${pkgs.dosfstools}/sbin/fsck.vfat -vn "$out"
     ''; # */
 
-  targetArch = if pkgs.stdenv.isi686 then
-    "ia32"
-  else if pkgs.stdenv.isx86_64 then
-    "x64"
-  else
-    throw "Unsupported architecture";
+  # Name used by UEFI for architectures.
+  targetArch =
+    if pkgs.stdenv.isi686 then
+      "ia32"
+    else if pkgs.stdenv.isx86_64 then
+      "x64"
+    else if pkgs.stdenv.isAarch64 then
+      "aa64"
+    else
+      throw "Unsupported architecture";
+
+  # Syslinux (and isolinux) only supports x86-based architectures.
+  canx86BiosBoot = pkgs.stdenv.isi686 || pkgs.stdenv.isx86_64;
 
 in
 
@@ -483,9 +506,9 @@ in
     # here and it causes a cyclic dependency.
     boot.loader.grub.enable = false;
 
-    # !!! Hack - attributes expected by other modules.
-    system.boot.loader.kernelFile = "bzImage";
-    environment.systemPackages = [ pkgs.grub2 pkgs.grub2_efi pkgs.syslinux ];
+    environment.systemPackages = [ pkgs.grub2 pkgs.grub2_efi ]
+      ++ optional canx86BiosBoot pkgs.syslinux
+    ;
 
     # In stage 1 of the boot, mount the CD as the root FS by label so
     # that we don't need to know its device.  We pass the label of the
@@ -556,13 +579,7 @@ in
     # Individual files to be included on the CD, outside of the Nix
     # store on the CD.
     isoImage.contents =
-      [ { source = pkgs.substituteAll  {
-            name = "isolinux.cfg";
-            src = pkgs.writeText "isolinux.cfg-in" isolinuxCfg;
-            bootRoot = "/boot";
-          };
-          target = "/isolinux/isolinux.cfg";
-        }
+      [
         { source = config.boot.kernelPackages.kernel + "/" + config.system.boot.loader.kernelFile;
           target = "/boot/" + config.system.boot.loader.kernelFile;
         }
@@ -572,9 +589,6 @@ in
         { source = config.system.build.squashfsStore;
           target = "/nix-store.squashfs";
         }
-        { source = "${pkgs.syslinux}/share/syslinux";
-          target = "/isolinux";
-        }
         { source = config.isoImage.efiSplashImage;
           target = "/EFI/boot/efi-background.png";
         }
@@ -584,6 +598,17 @@ in
         { source = pkgs.writeText "version" config.system.nixos.label;
           target = "/version.txt";
         }
+      ] ++ optionals canx86BiosBoot [
+        { source = pkgs.substituteAll  {
+            name = "isolinux.cfg";
+            src = pkgs.writeText "isolinux.cfg-in" isolinuxCfg;
+            bootRoot = "/boot";
+          };
+          target = "/isolinux/isolinux.cfg";
+        }
+        { source = "${pkgs.syslinux}/share/syslinux";
+          target = "/isolinux";
+        }
       ] ++ optionals config.isoImage.makeEfiBootable [
         { source = efiImg;
           target = "/boot/efi.img";
@@ -591,7 +616,7 @@ in
         { source = "${efiDir}/EFI";
           target = "/EFI";
         }
-      ] ++ optionals config.boot.loader.grub.memtest86.enable [
+      ] ++ optionals (config.boot.loader.grub.memtest86.enable && canx86BiosBoot) [
         { source = "${pkgs.memtest86plus}/memtest.bin";
           target = "/boot/memtest.bin";
         }
@@ -606,9 +631,10 @@ in
     # Create the ISO image.
     system.build.isoImage = pkgs.callPackage ../../../lib/make-iso9660-image.nix ({
       inherit (config.isoImage) isoName compressImage volumeID contents;
-      bootable = true;
+      bootable = canx86BiosBoot;
       bootImage = "/isolinux/isolinux.bin";
-    } // optionalAttrs config.isoImage.makeUsbBootable {
+      syslinux = if canx86BiosBoot then pkgs.syslinux else null;
+    } // optionalAttrs (config.isoImage.makeUsbBootable && canx86BiosBoot) {
       usbBootable = true;
       isohybridMbrImage = "${pkgs.syslinux}/share/syslinux/isohdpfx.bin";
     } // optionalAttrs config.isoImage.makeEfiBootable {
diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix
index 5ffb0c5ab22..8fda7ee0b0a 100644
--- a/nixos/modules/module-list.nix
+++ b/nixos/modules/module-list.nix
@@ -11,6 +11,8 @@
   ./config/xdg/icons.nix
   ./config/xdg/menus.nix
   ./config/xdg/mime.nix
+  ./config/appstream.nix
+  ./config/xdg/sounds.nix
   ./config/gtk/gtk-icon-cache.nix
   ./config/gnu.nix
   ./config/i18n.nix
@@ -34,6 +36,7 @@
   ./config/vpnc.nix
   ./config/zram.nix
   ./hardware/all-firmware.nix
+  ./hardware/bladeRF.nix
   ./hardware/brightnessctl.nix
   ./hardware/ckb-next.nix
   ./hardware/cpu/amd-microcode.nix
diff --git a/nixos/modules/programs/bash/bash.nix b/nixos/modules/programs/bash/bash.nix
index 2b01c9d26c4..d22f9dfa319 100644
--- a/nixos/modules/programs/bash/bash.nix
+++ b/nixos/modules/programs/bash/bash.nix
@@ -98,7 +98,12 @@ in
           if [ "$TERM" != "dumb" -o -n "$INSIDE_EMACS" ]; then
             PROMPT_COLOR="1;31m"
             let $UID && PROMPT_COLOR="1;32m"
-            PS1="\n\[\033[$PROMPT_COLOR\][\[\e]0;\u@\h: \w\a\]\u@\h:\w]\$\[\033[0m\] "
+            if [ -n "$INSIDE_EMACS" ]; then
+              # Emacs term mode doesn't support xterm title escape sequence (\e]0;)
+              PS1="\n\[\033[$PROMPT_COLOR\][\u@\h:\w]\\$\[\033[0m\] "
+            else
+              PS1="\n\[\033[$PROMPT_COLOR\][\[\e]0;\u@\h: \w\a\]\u@\h:\w]\$\[\033[0m\] "
+            fi
             if test "$TERM" = "xterm"; then
               PS1="\[\033]2;\h:\u:\w\007\]$PS1"
             fi
diff --git a/nixos/modules/programs/zsh/oh-my-zsh.xml b/nixos/modules/programs/zsh/oh-my-zsh.xml
index 5cf690c1a56..b26980daf06 100644
--- a/nixos/modules/programs/zsh/oh-my-zsh.xml
+++ b/nixos/modules/programs/zsh/oh-my-zsh.xml
@@ -19,7 +19,7 @@
    configuration format of <literal>oh-my-zsh</literal>.
 <programlisting>
 {
-  programs.ohMyZsh = {
+  programs.zsh.ohMyZsh = {
     enable = true;
     plugins = [ "git" "python" "man" ];
     theme = "agnoster";
@@ -51,7 +51,7 @@
    The module can do this as well:
 <programlisting>
 {
-  programs.ohMyZsh.custom = "~/path/to/custom/scripts";
+  programs.zsh.ohMyZsh.custom = "~/path/to/custom/scripts";
 }
 </programlisting>
   </para>
@@ -73,7 +73,7 @@
 <programlisting>
 { pkgs, ... }:
 {
-  programs.ohMyZsh.customPkgs = with pkgs; [
+  programs.zsh.ohMyZsh.customPkgs = with pkgs; [
     pkgs.nix-zsh-completions
     # and even more...
   ];
@@ -87,7 +87,7 @@
 
   <para>
    <emphasis>Please keep in mind that this is not compatible with
-   <literal>programs.ohMyZsh.custom</literal> as it requires an immutable store
+   <literal>programs.zsh.ohMyZsh.custom</literal> as it requires an immutable store
    path while <literal>custom</literal> shall remain mutable! An evaluation
    failure will be thrown if both <literal>custom</literal> and
    <literal>customPkgs</literal> are set.</emphasis>
diff --git a/nixos/modules/services/databases/clickhouse.nix b/nixos/modules/services/databases/clickhouse.nix
index 1b8771cec39..21e0cee3415 100644
--- a/nixos/modules/services/databases/clickhouse.nix
+++ b/nixos/modules/services/databases/clickhouse.nix
@@ -70,6 +70,11 @@ with lib;
       };
     };
 
+    environment.systemPackages = [ pkgs.clickhouse ];
+
+    # startup requires a `/etc/localtime` which only if exists if `time.timeZone != null`
+    time.timeZone = mkDefault "UTC";
+
   };
 
 }
diff --git a/nixos/modules/services/hardware/bluetooth.nix b/nixos/modules/services/hardware/bluetooth.nix
index d7ca8a43179..2a8dfe4a66c 100644
--- a/nixos/modules/services/hardware/bluetooth.nix
+++ b/nixos/modules/services/hardware/bluetooth.nix
@@ -25,9 +25,14 @@ in {
         type = types.package;
         default = pkgs.bluez;
         defaultText = "pkgs.bluez";
-        example = "pkgs.bluez.override { enableMidi = true; }";
+        example = "pkgs.bluezFull";
         description = ''
           Which BlueZ package to use.
+
+          <note><para>
+            Use the <literal>pkgs.bluezFull</literal> package to enable all
+            bluez plugins.
+          </para></note>
         '';
       };
 
diff --git a/nixos/modules/services/networking/networkmanager.nix b/nixos/modules/services/networking/networkmanager.nix
index 2d76e0676b2..d372dfd8f41 100644
--- a/nixos/modules/services/networking/networkmanager.nix
+++ b/nixos/modules/services/networking/networkmanager.nix
@@ -488,7 +488,7 @@ in {
       '') cfg.dynamicHosts.hostsDirs);
       serviceConfig = {
         Type = "oneshot";
-        RemainAfterExist = true;
+        RemainAfterExit = true;
       };
     };
 
diff --git a/nixos/modules/services/networking/prosody.nix b/nixos/modules/services/networking/prosody.nix
index a37ef98caec..25b7d6dbeba 100644
--- a/nixos/modules/services/networking/prosody.nix
+++ b/nixos/modules/services/networking/prosody.nix
@@ -228,6 +228,7 @@ let
 
   createSSLOptsStr = o: ''
     ssl = {
+      cafile = "/etc/ssl/certs/ca-bundle.crt";
       key = "${o.key}";
       certificate = "${o.cert}";
       ${concatStringsSep "\n" (mapAttrsToList (name: value: "${name} = ${toLua value};") o.extraOptions)}
diff --git a/nixos/modules/services/networking/shairport-sync.nix b/nixos/modules/services/networking/shairport-sync.nix
index 36ecb74ffc9..90c0689dc7b 100644
--- a/nixos/modules/services/networking/shairport-sync.nix
+++ b/nixos/modules/services/networking/shairport-sync.nix
@@ -27,7 +27,7 @@ in
       };
 
       arguments = mkOption {
-        default = "-v -d pulse";
+        default = "-v pulse";
         description = ''
           Arguments to pass to the daemon. Defaults to a local pulseaudio
           server.
diff --git a/nixos/modules/services/web-apps/nextcloud.nix b/nixos/modules/services/web-apps/nextcloud.nix
index d0efdf88d73..ecb1c5615d5 100644
--- a/nixos/modules/services/web-apps/nextcloud.nix
+++ b/nixos/modules/services/web-apps/nextcloud.nix
@@ -484,4 +484,6 @@ in {
       };
     })
   ]);
+
+  meta.doc = ./nextcloud.xml;
 }
diff --git a/nixos/modules/services/web-apps/nextcloud.xml b/nixos/modules/services/web-apps/nextcloud.xml
new file mode 100644
index 00000000000..9600d1be7c8
--- /dev/null
+++ b/nixos/modules/services/web-apps/nextcloud.xml
@@ -0,0 +1,99 @@
+<chapter xmlns="http://docbook.org/ns/docbook"
+         xmlns:xlink="http://www.w3.org/1999/xlink"
+         xmlns:xi="http://www.w3.org/2001/XInclude"
+         version="5.0"
+         xml:id="module-services-nextcloud">
+ <title>Nextcloud</title>
+
+ <para>
+  <link xlink:href="https://nextcloud.com/">Nextcloud</link> is an open-source, self-hostable cloud
+  platform. The server setup can be automated using
+  <link linkend="opt-services.nextcloud.enable">services.nextcloud</link>. A desktop client is packaged
+  at <literal>pkgs.nextcloud-client</literal>.
+ </para>
+
+ <section xml:id="module-services-nextcloud-basic-usage">
+  <title>Basic usage</title>
+  <para>
+   Nextcloud is a PHP-based application which requires an HTTP server
+   (<literal><link linkend="opt-services.nextcloud.enable">services.nextcloud</link></literal> optionally supports
+   <literal><link linkend="opt-services.nginx.enable">services.nginx</link></literal>) and a database
+   (it's recommended to use <literal><link linkend="opt-services.postgresql.enable">services.postgresql</link></literal>).
+  </para>
+  <para>
+    A very basic configuration may look like this:
+<programlisting>{ pkgs, ... }:
+{
+  services.nextcloud = {
+    <link linkend="opt-services.nextcloud.enable">enable</link> = true;
+    <link linkend="opt-services.nextcloud.hostName">hostName</link> = "nextcloud.tld";
+    <link linkend="opt-services.nextcloud.nginx.enable">nginx.enable</link> = true;
+    config = {
+      <link linkend="opt-services.nextcloud.config.dbtype">dbtype</link> = "pgsql";
+      <link linkend="opt-services.nextcloud.config.dbuser">dbuser</link> = "nextcloud";
+      <link linkend="opt-services.nextcloud.config.dbhost">dbhost</link> = "/tmp"; # nextcloud will add /.s.PGSQL.5432 by itself
+      <link linkend="opt-services.nextcloud.config.dbname">dbname</link> = "nextcloud";
+      <link linkend="opt-services.nextcloud.config.adminpassFile">adminpassFile</link> = "/path/to/admin-pass-file";
+      <link linkend="opt-services.nextcloud.config.adminuser">adminuser</link> = "root";
+    };
+  };
+
+  services.postgresql = {
+    <link linkend="opt-services.postgresql.enable">enable</link> = true;
+    <link linkend="opt-services.postgresql.initialScript">initialScript</link> = pkgs.writeText "psql-init" ''
+      CREATE ROLE nextcloud WITH LOGIN;
+      CREATE DATABASE nextcloud WITH OWNER nextcloud;
+    '';
+  };
+
+  # ensure that postgres is running *before* running the setup
+  systemd.services."nextcloud-setup" = {
+    requires = ["postgresql.service"];
+    after = ["postgresql.service"];
+  };
+
+  <link linkend="opt-networking.firewall.allowedTCPPorts">networking.firewall.allowedTCPPorts</link> = [ 80 443 ];
+}</programlisting>
+  </para>
+  <para>
+   The options <literal>hostName</literal> and <literal>nginx.enable</literal> are used internally to configure an
+   HTTP server using <literal><link xlink:href="https://php-fpm.org/">PHP-FPM</link></literal> and <literal>nginx</literal>.
+   The <literal>config</literal> attribute set is used for the <literal>config.php</literal> which is used
+   for the application's configuration.
+   <emphasis>Beware: this isn't entirely pure since the config is modified by the application's runtime!</emphasis>
+  </para>
+  <para>
+    In case the application serves multiple hosts (those are checked with
+    <literal><link xlink:href="http://php.net/manual/en/reserved.variables.server.php">$_SERVER['HTTP_HOST']</link></literal>)
+    those can be added using
+    <literal><link linkend="opt-services.nextcloud.config.extraTrustedDomains">services.nextcloud.config.extraTrustedDomains</link></literal>.
+  </para>
+ </section>
+
+ <section xml:id="module-services-nextcloud-pitfalls-during-upgrade">
+  <title>Pitfalls</title>
+  <para>
+   Unfortunately Nextcloud appears to be very stateful when it comes to managing its own configuration. The
+   config file lives in the home directory of the <literal>nextcloud</literal> user (by default
+   <literal>/var/lib/nextcloud/config/config.php</literal>) and is also used to track several
+   states of the application (e.g. whether installed or not).
+  </para>
+  <para>
+   Right now changes to the <literal>services.nextcloud.config</literal> attribute set won't take effect
+   after the first install
+   (except <literal><link linkend="opt-services.nextcloud.config.extraTrustedDomains">services.nextcloud.config.extraTrustedDomains</link></literal>) since the actual configuration
+   file is generated by the NextCloud installer which also sets up critical parts such as the database
+   structure.
+  </para>
+  <para>
+   <emphasis>Warning: don't delete <literal>config.php</literal>! This file tracks the application's state and a deletion can cause unwanted side-effects!</emphasis>
+  </para>
+  <para>
+   <emphasis>Warning: don't rerun <literal>nextcloud-occ maintenance:install</literal>! This command tries to install the application and can cause unwanted side-effects!</emphasis>
+  </para>
+  <para>
+    The issues are known and reported in <link xlink:href="https://github.com/NixOS/nixpkgs/issues/49783">#49783</link>, for now it's unfortunately necessary to manually work around these issues.
+  </para>
+ </section>
+
+</chapter>
diff --git a/nixos/modules/services/web-servers/apache-httpd/limesurvey.nix b/nixos/modules/services/web-servers/apache-httpd/limesurvey.nix
index 77194f34749..5c387700a5d 100644
--- a/nixos/modules/services/web-servers/apache-httpd/limesurvey.nix
+++ b/nixos/modules/services/web-servers/apache-httpd/limesurvey.nix
@@ -85,7 +85,7 @@ in rec {
     id = mkOption {
       default = "main";
       description = ''
-        A unique identifier necessary to keep multiple owncloud server
+        A unique identifier necessary to keep multiple Limesurvey server
         instances on the same machine apart.  This is used to
         disambiguate the administrative scripts, which get names like
         mediawiki-$id-change-password.
diff --git a/nixos/modules/services/web-servers/apache-httpd/owncloud.nix b/nixos/modules/services/web-servers/apache-httpd/owncloud.nix
deleted file mode 100644
index 6345a9a5693..00000000000
--- a/nixos/modules/services/web-servers/apache-httpd/owncloud.nix
+++ /dev/null
@@ -1,608 +0,0 @@
-{ config, lib, pkgs, serverInfo, php, ... }:
-
-with lib;
-
-let
-
-  owncloudConfig = pkgs.writeText "config.php"
-    ''
-      <?php
-
-      /* Only enable this for local development and not in productive environments */
-      /* This will disable the minifier and outputs some additional debug informations */
-      define("DEBUG", false);
-
-      $CONFIG = array(
-      /* Flag to indicate ownCloud is successfully installed (true = installed) */
-      "installed" => true,
-
-      /* Type of database, can be sqlite, mysql or pgsql */
-      "dbtype" => "${config.dbType}",
-
-      /* Name of the ownCloud database */
-      "dbname" => "${config.dbName}",
-
-      /* User to access the ownCloud database */
-      "dbuser" => "${config.dbUser}",
-
-      /* Password to access the ownCloud database */
-      "dbpassword" => "${config.dbPassword}",
-
-      /* Host running the ownCloud database. To specify a port use "HOSTNAME:####"; to specify a unix sockets use "localhost:/path/to/socket". */
-      "dbhost" => "${config.dbServer}",
-
-      /* Prefix for the ownCloud tables in the database */
-      "dbtableprefix" => "",
-
-      /* Force use of HTTPS connection (true = use HTTPS) */
-      "forcessl" => ${config.forceSSL},
-
-      /* Blacklist a specific file and disallow the upload of files with this name - WARNING: USE THIS ONLY IF YOU KNOW WHAT YOU ARE DOING. */
-      "blacklisted_files" => array('.htaccess'),
-
-      /* The automatic hostname detection of ownCloud can fail in certain reverse proxy and CLI/cron situations. This option allows to manually override the automatic detection. You can also add a port. For example "www.example.com:88" */
-      "overwritehost" => "${config.overwriteHost}",
-
-      /* The automatic protocol detection of ownCloud can fail in certain reverse proxy and CLI/cron situations. This option allows to manually override the protocol detection. For example "https" */
-      "overwriteprotocol" => "${config.overwriteProtocol}",
-
-      /* The automatic webroot detection of ownCloud can fail in certain reverse proxy and CLI/cron situations. This option allows to manually override the automatic detection. For example "/domain.tld/ownCloud". The value "/" can be used to remove the root. */
-      "overwritewebroot" => "${config.overwriteWebRoot}",
-
-      /* The automatic detection of ownCloud can fail in certain reverse proxy and CLI/cron situations. This option allows to define a manually override condition as regular expression for the remote ip address. For example "^10\.0\.0\.[1-3]$" */
-      "overwritecondaddr" => "",
-
-      /* A proxy to use to connect to the internet. For example "myproxy.org:88" */
-      "proxy" => "",
-
-      /* The optional authentication for the proxy to use to connect to the internet. The format is: [username]:[password] */
-      "proxyuserpwd" => "",
-
-      /* List of trusted domains, to prevent host header poisoning ownCloud is only using these Host headers */
-      ${if config.trustedDomain != "" then "'trusted_domains' => array('${config.trustedDomain}')," else ""}
-
-      /* Theme to use for ownCloud */
-      "theme" => "",
-
-      /* Optional ownCloud default language - overrides automatic language detection on public pages like login or shared items. This has no effect on the user's language preference configured under "personal -> language" once they have logged in */
-      "default_language" => "${config.defaultLang}",
-
-      /* Path to the parent directory of the 3rdparty directory */
-      "3rdpartyroot" => "",
-
-      /* URL to the parent directory of the 3rdparty directory, as seen by the browser */
-      "3rdpartyurl" => "",
-
-      /* Default app to open on login.
-       * This can be a comma-separated list of app ids.
-       * If the first app is not enabled for the current user,
-       * it will try with the second one and so on. If no enabled app could be found,
-       * the "files" app will be displayed instead. */
-      "defaultapp" => "${config.defaultApp}",
-
-      /* Enable the help menu item in the settings */
-      "knowledgebaseenabled" => true,
-
-      /* Enable installing apps from the appstore */
-      "appstoreenabled" => ${config.appStoreEnable},
-
-      /* URL of the appstore to use, server should understand OCS */
-      "appstoreurl" => "https://api.owncloud.com/v1",
-
-      /* Domain name used by ownCloud for the sender mail address, e.g. no-reply@example.com */
-      "mail_domain" => "${config.mailFromDomain}",
-
-      /* FROM address used by ownCloud for the sender mail address, e.g. owncloud@example.com
-         This setting overwrites the built in 'sharing-noreply' and 'lostpassword-noreply'
-         FROM addresses, that ownCloud uses
-      */
-      "mail_from_address" => "${config.mailFrom}",
-
-      /* Enable SMTP class debugging */
-      "mail_smtpdebug" => false,
-
-      /* Mode to use for sending mail, can be sendmail, smtp, qmail or php, see PHPMailer docs */
-      "mail_smtpmode" => "${config.SMTPMode}",
-
-      /* Host to use for sending mail, depends on mail_smtpmode if this is used */
-      "mail_smtphost" => "${config.SMTPHost}",
-
-      /* Port to use for sending mail, depends on mail_smtpmode if this is used */
-      "mail_smtpport" => ${config.SMTPPort},
-
-      /* SMTP server timeout in seconds for sending mail, depends on mail_smtpmode if this is used */
-      "mail_smtptimeout" => ${config.SMTPTimeout},
-
-      /* SMTP connection prefix or sending mail, depends on mail_smtpmode if this is used.
-         Can be "", ssl or tls */
-      "mail_smtpsecure" => "${config.SMTPSecure}",
-
-      /* authentication needed to send mail, depends on mail_smtpmode if this is used
-       * (false = disable authentication)
-       */
-      "mail_smtpauth" => ${config.SMTPAuth},
-
-      /* authentication type needed to send mail, depends on mail_smtpmode if this is used
-       * Can be LOGIN (default), PLAIN or NTLM */
-      "mail_smtpauthtype" => "${config.SMTPAuthType}",
-
-      /* Username to use for sendmail mail, depends on mail_smtpauth if this is used */
-      "mail_smtpname" => "${config.SMTPUser}",
-
-      /* Password to use for sendmail mail, depends on mail_smtpauth if this is used */
-      "mail_smtppassword" => "${config.SMTPPass}",
-
-      /* memcached servers (Only used when xCache, APC and APCu are absent.) */
-      "memcached_servers" => array(
-          // hostname, port and optional weight. Also see:
-          // http://www.php.net/manual/en/memcached.addservers.php
-          // http://www.php.net/manual/en/memcached.addserver.php
-          //array('localhost', 11211),
-          //array('other.host.local', 11211),
-      ),
-
-      /* How long should ownCloud keep deleted files in the trash bin, default value:  30 days */
-      'trashbin_retention_obligation' => 30,
-
-      /* Disable/Enable auto expire for the trash bin, by default auto expire is enabled */
-      'trashbin_auto_expire' => true,
-
-      /* allow user to change his display name, if it is supported by the back-end */
-      'allow_user_to_change_display_name' => true,
-
-      /* Check 3rdparty apps for malicious code fragments */
-      "appcodechecker" => true,
-
-      /* Check if ownCloud is up to date */
-      "updatechecker" => true,
-
-      /* Are we connected to the internet or are we running in a closed network? */
-      "has_internet_connection" => true,
-
-      /* Check if the ownCloud WebDAV server is working correctly. Can be disabled if not needed in special situations*/
-      "check_for_working_webdav" => true,
-
-      /* Check if .htaccess protection of data is working correctly. Can be disabled if not needed in special situations*/
-      "check_for_working_htaccess" => true,
-
-      /* Place to log to, can be owncloud and syslog (owncloud is log menu item in admin menu) */
-      "log_type" => "owncloud",
-
-      /* File for the owncloud logger to log to, (default is ownloud.log in the data dir) */
-      "logfile" => "${config.dataDir}/owncloud.log",
-
-      /* Loglevel to start logging at. 0=DEBUG, 1=INFO, 2=WARN, 3=ERROR (default is WARN) */
-      "loglevel" => "2",
-
-      /* date format to be used while writing to the owncloud logfile */
-      'logdateformat' => 'F d, Y H:i:s',
-
-      ${tzSetting}
-
-      /* Append all database queries and parameters to the log file.
-       (watch out, this option can increase the size of your log file)*/
-      "log_query" => false,
-
-      /* Whether ownCloud should log the last successfull cron exec */
-      "cron_log" => true,
-
-      /*
-       * Configure the size in bytes log rotation should happen, 0 or false disables the rotation.
-       * This rotates the current owncloud logfile to a new name, this way the total log usage
-       * will stay limited and older entries are available for a while longer. The
-       * total disk usage is twice the configured size.
-       * WARNING: When you use this, the log entries will eventually be lost.
-       */
-      'log_rotate_size' => "104857600", // 104857600, // 100 MiB
-
-      /* Lifetime of the remember login cookie, default is 15 days */
-      "remember_login_cookie_lifetime" => 1296000,
-
-      /* Life time of a session after inactivity */
-      "session_lifetime" => 86400,
-
-      /*
-       * Enable/disable session keep alive when a user is logged in in the Web UI.
-       * This is achieved by sending a "heartbeat" to the server to prevent
-       * the session timing out.
-       */
-      "session_keepalive" => true,
-
-      /* Custom CSP policy, changing this will overwrite the standard policy */
-      "custom_csp_policy" => "default-src 'self'; script-src 'self' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; frame-src *; img-src *; font-src 'self' data:; media-src *",
-
-      /* Enable/disable X-Frame-Restriction */
-      /* HIGH SECURITY RISK IF DISABLED*/
-      "xframe_restriction" => true,
-
-      /* The directory where the user data is stored, default to data in the owncloud
-       * directory. The sqlite database is also stored here, when sqlite is used.
-       */
-      "datadirectory" => "${config.dataDir}/storage",
-
-      /* The directory where the skeleton files are located. These files will be copied to the data
-       * directory of new users. Leave empty to not copy any skeleton files.
-       */
-      // "skeletondirectory" => "",
-
-      /* Enable maintenance mode to disable ownCloud
-         If you want to prevent users to login to ownCloud before you start doing some maintenance work,
-         you need to set the value of the maintenance parameter to true.
-         Please keep in mind that users who are already logged-in are kicked out of ownCloud instantly.
-      */
-      "maintenance" => false,
-
-      "apps_paths" => array(
-
-      /* Set an array of path for your apps directories
-       key 'path' is for the fs path and the key 'url' is for the http path to your
-       applications paths. 'writable' indicates whether the user can install apps in this folder.
-       You must have at least 1 app folder writable or you must set the parameter 'appstoreenabled' to false
-      */
-          array(
-              'path'=> '${config.dataDir}/apps',
-              'url' => '/apps',
-              'writable' => true,
-          ),
-      ),
-      'user_backends'=>array(
-          /*
-          array(
-              'class'=>'OC_User_IMAP',
-              'arguments'=>array('{imap.gmail.com:993/imap/ssl}INBOX')
-          )
-          */
-      ),
-      //links to custom clients
-      'customclient_desktop' => ''', //http://owncloud.org/sync-clients/
-      'customclient_android' => ''', //https://play.google.com/store/apps/details?id=com.owncloud.android
-      'customclient_ios' => ''', //https://itunes.apple.com/us/app/owncloud/id543672169?mt=8
-
-      // PREVIEW
-      'enable_previews' => true,
-      /* the max width of a generated preview, if value is null, there is no limit */
-      'preview_max_x' => null,
-      /* the max height of a generated preview, if value is null, there is no limit */
-      'preview_max_y' => null,
-      /* the max factor to scale a preview, default is set to 10 */
-      'preview_max_scale_factor' => 10,
-      /* custom path for libreoffice / openoffice binary */
-      'preview_libreoffice_path' => '${config.libreofficePath}',
-      /* cl parameters for libreoffice / openoffice */
-      'preview_office_cl_parameters' => ''',
-
-      /* whether avatars should be enabled */
-      'enable_avatars' => true,
-
-      // Extra SSL options to be used for configuration
-      'openssl' => array(
-          'config' => '/etc/ssl/openssl.cnf',
-      ),
-
-      // default cipher used for file encryption, currently we support AES-128-CFB and AES-256-CFB
-      'cipher' => 'AES-256-CFB',
-
-      /* whether usage of the instance should be restricted to admin users only */
-      'singleuser' => false,
-
-      /* all css and js files will be served by the web server statically in one js file and ons css file*/
-      'asset-pipeline.enabled' => false,
-
-      /* where mount.json file should be stored, defaults to data/mount.json */
-      'mount_file' => ''',
-
-      /*
-       * Location of the cache folder, defaults to "data/$user/cache" where "$user" is the current user.
-       *
-       * When specified, the format will change to "$cache_path/$user" where "$cache_path" is the configured
-       * cache directory and "$user" is the user.
-       *
-       */
-      'cache_path' => ''',
-
-      /* EXPERIMENTAL: option whether to include external storage in quota calculation, defaults to false */
-      'quota_include_external_storage' => false,
-
-      /*
-       * specifies how often the filesystem is checked for changes made outside owncloud
-       * 0 -> never check the filesystem for outside changes, provides a performance increase when it's certain that no changes are made directly to the filesystem
-       * 1 -> check each file or folder at most once per request, recomended for general use if outside changes might happen
-       * 2 -> check every time the filesystem is used, causes a performance hit when using external storages, not recomended for regular use
-       */
-      'filesystem_check_changes' => 1,
-
-      /* If true, prevent owncloud from changing the cache due to changes in the filesystem for all storage */
-      'filesystem_cache_readonly' => false,
-
-      /**
-       * define default folder for shared files and folders
-       */
-      'share_folder' => '/',
-
-      'version' => '${config.package.version}',
-
-      'openssl' => '${pkgs.openssl.bin}/bin/openssl'
-
-      );
-
-    '';
-
-  tzSetting = let tz = serverInfo.fullConfig.time.timeZone; in optionalString (!isNull tz) ''
-    /* timezone used while writing to the owncloud logfile (default: UTC) */
-    'logtimezone' => '${tz}',
-  '';
-
-  postgresql = serverInfo.fullConfig.services.postgresql.package;
-
-  setupDb = pkgs.writeScript "setup-owncloud-db" ''
-    #!${pkgs.runtimeShell}
-    PATH="${postgresql}/bin"
-    createuser --no-superuser --no-createdb --no-createrole "${config.dbUser}" || true
-    createdb "${config.dbName}" -O "${config.dbUser}" || true
-    psql -U postgres -d postgres -c "alter user ${config.dbUser} with password '${config.dbPassword}';" || true
-
-    QUERY="CREATE TABLE appconfig
-             ( appid       VARCHAR( 255 ) NOT NULL
-             , configkey   VARCHAR( 255 ) NOT NULL
-             , configvalue VARCHAR( 255 ) NOT NULL
-             );
-           GRANT ALL ON appconfig TO ${config.dbUser};
-           ALTER TABLE appconfig OWNER TO ${config.dbUser};"
-
-    psql -h "/tmp" -U postgres -d ${config.dbName} -Atw -c "$QUERY" || true
-  '';
-
-in
-
-rec {
-
-  extraConfig =
-    ''
-      ${if config.urlPrefix != "" then "Alias ${config.urlPrefix} ${config.package}" else ''
-
-        RewriteEngine On
-        RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} !-f
-        RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} !-d
-      ''}
-
-      <Directory ${config.package}>
-        Include ${config.package}/.htaccess
-      </Directory>
-    '';
-
-  globalEnvVars = [
-    { name = "OC_CONFIG_PATH"; value = "${config.dataDir}/config/"; }
-  ];
-
-  documentRoot = if config.urlPrefix == "" then config.package else null;
-
-  enablePHP = true;
-
-  options = {
-
-    package = mkOption {
-      type = types.package;
-      default = pkgs.owncloud70;
-      defaultText = "pkgs.owncloud70";
-      example = literalExample "pkgs.owncloud70";
-      description = ''
-          ownCloud package to use.
-      '';
-    };
-
-    urlPrefix = mkOption {
-      default = "";
-      example = "/owncloud";
-      description = ''
-        The URL prefix under which the owncloud service appears.
-      '';
-    };
-
-    id = mkOption {
-      default = "main";
-      description = ''
-        A unique identifier necessary to keep multiple owncloud server
-        instances on the same machine apart.  This is used to
-        disambiguate the administrative scripts, which get names like
-        mediawiki-$id-change-password.
-      '';
-    };
-
-    adminUser = mkOption {
-      default = "owncloud";
-      description = "The admin user name for accessing owncloud.";
-    };
-
-    adminPassword = mkOption {
-      description = "The admin password for accessing owncloud.";
-    };
-
-    dbType = mkOption {
-      default = "pgsql";
-      description = "Type of database, in NixOS, for now, only pgsql.";
-    };
-
-    dbName = mkOption {
-      default = "owncloud";
-      description = "Name of the database that holds the owncloud data.";
-    };
-
-    dbServer = mkOption {
-      default = "localhost:5432";
-      description = ''
-        The location of the database server.
-      '';
-    };
-
-    dbUser = mkOption {
-      default = "owncloud";
-      description = "The user name for accessing the database.";
-    };
-
-    dbPassword = mkOption {
-      example = "foobar";
-      description = ''
-        The password of the database user.  Warning: this is stored in
-        cleartext in the Nix store!
-      '';
-    };
-
-    forceSSL = mkOption {
-      default = "false";
-      description = "Force use of HTTPS connection.";
-    };
-
-    adminAddr = mkOption {
-      default = serverInfo.serverConfig.adminAddr;
-      example = "admin@example.com";
-      description = ''
-        Emergency contact e-mail address.  Defaults to the Apache
-        admin address.
-      '';
-    };
-
-    siteName = mkOption {
-      default = "owncloud";
-      example = "Foobar owncloud";
-      description = "Name of the owncloud";
-    };
-
-    trustedDomain = mkOption {
-      default = "";
-      description = "Trusted domain";
-    };
-
-    defaultLang = mkOption {
-      default = "";
-      description = "Default language";
-    };
-
-    defaultApp = mkOption {
-      default = "";
-      description = "Default application";
-    };
-
-    appStoreEnable = mkOption {
-      default = "true";
-      description = "Enable app store";
-    };
-
-    mailFrom = mkOption {
-      default = "no-reply";
-      description = "Mail from";
-    };
-
-    mailFromDomain = mkOption {
-      default = "example.xyz";
-      description = "Mail from domain";
-    };
-
-    SMTPMode = mkOption {
-      default = "smtp";
-      description = "Which mode to use for sending mail: sendmail, smtp, qmail or php.";
-    };
-
-    SMTPHost = mkOption {
-      default = "";
-      description = "SMTP host";
-    };
-
-    SMTPPort = mkOption {
-      default = "25";
-      description = "SMTP port";
-    };
-
-    SMTPTimeout = mkOption {
-      default = "10";
-      description = "SMTP mode";
-    };
-
-    SMTPSecure = mkOption {
-      default = "ssl";
-      description = "SMTP secure";
-    };
-
-    SMTPAuth = mkOption {
-      default = "true";
-      description = "SMTP auth";
-    };
-
-    SMTPAuthType = mkOption {
-      default = "LOGIN";
-      description = "SMTP auth type";
-    };
-
-    SMTPUser = mkOption {
-      default = "";
-      description = "SMTP user";
-    };
-
-    SMTPPass = mkOption {
-      default = "";
-      description = "SMTP pass";
-    };
-
-    dataDir = mkOption {
-      default = "/var/lib/owncloud";
-      description = "Data dir";
-    };
-
-    libreofficePath = mkOption {
-      default = "/usr/bin/libreoffice";
-      description = "Path for LibreOffice/OpenOffice binary.";
-    };
-
-    overwriteHost = mkOption {
-      default = "";
-      description = "The automatic hostname detection of ownCloud can fail in
-        certain reverse proxy and CLI/cron situations. This option allows to
-        manually override the automatic detection. You can also add a port.";
-    };
-
-    overwriteProtocol = mkOption {
-      default = "";
-      description = "The automatic protocol detection of ownCloud can fail in
-        certain reverse proxy and CLI/cron situations. This option allows to
-        manually override the protocol detection.";
-    };
-
-    overwriteWebRoot = mkOption {
-      default = "";
-      description = "The automatic webroot detection of ownCloud can fail in
-        certain reverse proxy and CLI/cron situations. This option allows to
-        manually override the automatic detection.";
-    };
-
-  };
-
-  startupScript = pkgs.writeScript "owncloud_startup.sh" ''
-
-    if [ ! -d ${config.dataDir}/config ]; then
-      mkdir -p ${config.dataDir}/config
-      cp ${owncloudConfig} ${config.dataDir}/config/config.php
-      mkdir -p ${config.dataDir}/storage
-      mkdir -p ${config.dataDir}/apps
-      cp -r ${config.package}/apps/* ${config.dataDir}/apps/
-      chmod -R ug+rw ${config.dataDir}
-      chmod -R o-rwx ${config.dataDir}
-      chown -R wwwrun:wwwrun ${config.dataDir}
-
-      ${pkgs.sudo}/bin/sudo -u postgres ${setupDb}
-    fi
-
-    if [ -e ${config.package}/config/ca-bundle.crt ]; then
-      cp -f ${config.package}/config/ca-bundle.crt ${config.dataDir}/config/
-    fi
-
-    ${php}/bin/php ${config.package}/occ upgrade >> ${config.dataDir}/upgrade.log || true
-
-    chown wwwrun:wwwrun ${config.dataDir}/owncloud.log || true
-
-    QUERY="INSERT INTO groups (gid) values('admin');
-           INSERT INTO users (uid,password)
-             values('${config.adminUser}','${builtins.hashString "sha1" config.adminPassword}');
-           INSERT INTO group_user (gid,uid)
-             values('admin','${config.adminUser}');"
-    ${pkgs.sudo}/bin/sudo -u postgres ${postgresql}/bin/psql -h "/tmp" -U postgres -d ${config.dbName} -Atw -c "$QUERY" || true
-  '';
-}
diff --git a/nixos/release.nix b/nixos/release.nix
index 1fcceed1261..e7952b33de6 100644
--- a/nixos/release.nix
+++ b/nixos/release.nix
@@ -273,7 +273,7 @@ in rec {
       { services.httpd.enable = true;
         services.httpd.adminAddr = "foo@example.org";
         services.postgresql.enable = true;
-        services.postgresql.package = pkgs.postgresql_9_3;
+        services.postgresql.package = pkgs.postgresql;
         environment.systemPackages = [ pkgs.php ];
       });
   };
diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix
index 10781168ee4..1e8e2213fac 100644
--- a/nixos/tests/all-tests.nix
+++ b/nixos/tests/all-tests.nix
@@ -39,6 +39,7 @@ in
   cfssl = handleTestOn ["x86_64-linux"] ./cfssl.nix {};
   chromium = (handleTestOn ["x86_64-linux"] ./chromium.nix {}).stable or {};
   cjdns = handleTest ./cjdns.nix {};
+  clickhouse = handleTest ./clickhouse.nix {};
   cloud-init = handleTest ./cloud-init.nix {};
   codimd = handleTest ./codimd.nix {};
   containers-bridge = handleTest ./containers-bridge.nix {};
@@ -156,7 +157,6 @@ in
   openssh = handleTest ./openssh.nix {};
   osquery = handleTest ./osquery.nix {};
   ostree = handleTest ./ostree.nix {};
-  owncloud = handleTest ./owncloud.nix {};
   pam-oath-login = handleTest ./pam-oath-login.nix {};
   peerflix = handleTest ./peerflix.nix {};
   pgjwt = handleTest ./pgjwt.nix {};
diff --git a/nixos/tests/clickhouse.nix b/nixos/tests/clickhouse.nix
new file mode 100644
index 00000000000..7d835069ec4
--- /dev/null
+++ b/nixos/tests/clickhouse.nix
@@ -0,0 +1,25 @@
+import ./make-test.nix ({ pkgs, ... }: {
+  name = "clickhouse";
+  meta.maintainers = with pkgs.stdenv.lib.maintainers; [ ma27 ];
+
+  machine = {
+    services.clickhouse.enable = true;
+  };
+
+  testScript =
+    let
+      # work around quote/substitution complexity by Nix, Perl, bash and SQL.
+      tableDDL = pkgs.writeText "ddl.sql" "CREATE TABLE `demo` (`value` FixedString(10)) engine = MergeTree PARTITION BY value ORDER BY tuple();";
+      insertQuery = pkgs.writeText "insert.sql" "INSERT INTO `demo` (`value`) VALUES ('foo');";
+      selectQuery = pkgs.writeText "select.sql" "SELECT * from `demo`";
+    in
+      ''
+        $machine->start();
+        $machine->waitForUnit("clickhouse.service");
+        $machine->waitForOpenPort(9000);
+
+        $machine->succeed("cat ${tableDDL} | clickhouse-client");
+        $machine->succeed("cat ${insertQuery} | clickhouse-client");
+        $machine->succeed("cat ${selectQuery} | clickhouse-client | grep foo");
+      '';
+})
diff --git a/nixos/tests/gitlab.nix b/nixos/tests/gitlab.nix
index f401fe098dc..16e0dd723ec 100644
--- a/nixos/tests/gitlab.nix
+++ b/nixos/tests/gitlab.nix
@@ -8,7 +8,7 @@ import ./make-test.nix ({ pkgs, lib, ...} : with lib; {
 
   nodes = {
     gitlab = { ... }: {
-      virtualisation.memorySize = 2047;
+      virtualisation.memorySize = if pkgs.stdenv.is64bit then 4096 else 2047;
       systemd.services.gitlab.serviceConfig.Restart = mkForce "no";
       systemd.services.gitlab-workhorse.serviceConfig.Restart = mkForce "no";
       systemd.services.gitaly.serviceConfig.Restart = mkForce "no";
diff --git a/nixos/tests/home-assistant.nix b/nixos/tests/home-assistant.nix
index 7627bb07901..73c1e71eb51 100644
--- a/nixos/tests/home-assistant.nix
+++ b/nixos/tests/home-assistant.nix
@@ -4,6 +4,7 @@ let
   configDir = "/var/lib/foobar";
   apiPassword = "some_secret";
   mqttPassword = "another_secret";
+  hassCli = "hass-cli --server http://hass:8123 --password '${apiPassword}'";
 
 in {
   name = "home-assistant";
@@ -16,7 +17,7 @@ in {
       { pkgs, ... }:
       {
         environment.systemPackages = with pkgs; [
-          mosquitto
+          mosquitto home-assistant-cli
         ];
         services.home-assistant = {
           inherit configDir;
@@ -71,6 +72,11 @@ in {
     $hass->waitUntilSucceeds("mosquitto_pub -V mqttv311 -t home-assistant/test -u homeassistant -P '${mqttPassword}' -m let_there_be_light");
     $hass->succeed("curl http://localhost:8123/api/states/binary_sensor.mqtt_binary_sensor -H 'x-ha-access: ${apiPassword}' | grep -qF '\"state\": \"on\"'");
 
+    # Toggle a binary sensor using hass-cli
+    $hass->succeed("${hassCli} entity get binary_sensor.mqtt_binary_sensor | grep -qF '\"state\": \"on\"'");
+    $hass->succeed("${hassCli} entity edit binary_sensor.mqtt_binary_sensor --json='{\"state\": \"off\"}'");
+    $hass->succeed("curl http://localhost:8123/api/states/binary_sensor.mqtt_binary_sensor -H 'x-ha-access: ${apiPassword}' | grep -qF '\"state\": \"off\"'");
+
     # Print log to ease debugging
     my $log = $hass->succeed("cat ${configDir}/home-assistant.log");
     print "\n### home-assistant.log ###\n";
diff --git a/nixos/tests/kubernetes/kubernetes-common.nix b/nixos/tests/kubernetes/kubernetes-common.nix
index 125c176f113..87c65b88365 100644
--- a/nixos/tests/kubernetes/kubernetes-common.nix
+++ b/nixos/tests/kubernetes/kubernetes-common.nix
@@ -3,7 +3,6 @@ with pkgs.lib;
 let
   base = {
     inherit roles;
-    featureGates = ["AllAlpha"];
     flannel.enable = true;
     addons.dashboard.enable = true;
 
diff --git a/nixos/tests/owncloud.nix b/nixos/tests/owncloud.nix
deleted file mode 100644
index c968569f200..00000000000
--- a/nixos/tests/owncloud.nix
+++ /dev/null
@@ -1,39 +0,0 @@
-import ./make-test.nix ({ ... }:
-
-{
-  name = "owncloud";
-  nodes =
-    { web =
-        { ... }:
-        {
-          services.postgresql.enable = true;
-          services.httpd = {
-            enable = true;
-            logPerVirtualHost = true;
-            adminAddr = "example@example.com";
-            virtualHosts = [
-              {
-                hostName = "owncloud";
-                extraSubservices =
-                  [
-                    {
-                      serviceType   = "owncloud";
-                      adminPassword = "secret";
-                      dbPassword    = "secret";
-                    }
-                  ];
-              }
-            ];
-          };
-        };
-    };
-
-  testScript = ''
-    startAll;
-
-    $web->waitForUnit("postgresql");
-    $web->waitForUnit("httpd");
-
-    $web->succeed("curl -L 127.0.0.1:80");
-  '';
-})