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/from_md/release-notes/rl-2111.section.xml11
-rw-r--r--nixos/doc/manual/release-notes/rl-2111.section.md5
-rw-r--r--nixos/modules/hardware/video/nvidia.nix13
-rw-r--r--nixos/modules/services/audio/roon-bridge.nix14
-rw-r--r--nixos/modules/services/audio/roon-server.nix14
-rw-r--r--nixos/modules/services/desktops/pipewire/bluez-hardware.conf.json11
-rw-r--r--nixos/modules/services/desktops/pipewire/pipewire-pulse.conf.json1
-rw-r--r--nixos/modules/services/network-filesystems/ipfs.nix110
-rw-r--r--nixos/modules/services/networking/syncthing.nix4
-rw-r--r--nixos/modules/services/search/elasticsearch.nix20
-rw-r--r--nixos/modules/services/web-apps/nextcloud.xml124
-rw-r--r--nixos/modules/services/x11/desktop-managers/gnome.nix7
-rw-r--r--nixos/modules/services/x11/window-managers/clfswm.nix16
-rw-r--r--nixos/tests/caddy.nix95
14 files changed, 286 insertions, 159 deletions
diff --git a/nixos/doc/manual/from_md/release-notes/rl-2111.section.xml b/nixos/doc/manual/from_md/release-notes/rl-2111.section.xml
index e4c765361d72..3c7f9a274b3d 100644
--- a/nixos/doc/manual/from_md/release-notes/rl-2111.section.xml
+++ b/nixos/doc/manual/from_md/release-notes/rl-2111.section.xml
@@ -22,7 +22,7 @@
       </listitem>
       <listitem>
         <para>
-          kOps now defaults to 1.21.0, which uses containerd as the
+          kOps now defaults to 1.21.1, which uses containerd as the
           default runtime.
         </para>
       </listitem>
@@ -1095,6 +1095,15 @@ Superuser created successfully.
           but instead use more of the YAML-specific syntax.
         </para>
       </listitem>
+      <listitem>
+        <para>
+          GNOME desktop environment now enables
+          <literal>QGnomePlatform</literal> as the Qt platform theme,
+          which should avoid crashes when opening file chooser dialogs
+          in Qt apps by using XDG desktop portal. Additionally, it will
+          make the apps fit better visually.
+        </para>
+      </listitem>
     </itemizedlist>
   </section>
 </section>
diff --git a/nixos/doc/manual/release-notes/rl-2111.section.md b/nixos/doc/manual/release-notes/rl-2111.section.md
index 14c51d418e69..c5a4b5bd98c0 100644
--- a/nixos/doc/manual/release-notes/rl-2111.section.md
+++ b/nixos/doc/manual/release-notes/rl-2111.section.md
@@ -7,7 +7,8 @@ In addition to numerous new and upgraded packages, this release has the followin
 ## Highlights {#sec-release-21.11-highlights}
 
 - PHP now defaults to PHP 8.0, updated from 7.4.
-- kOps now defaults to 1.21.0, which uses containerd as the default runtime.
+
+- kOps now defaults to 1.21.1, which uses containerd as the default runtime.
 
 - `python3` now defaults to Python 3.9, updated from Python 3.8.
 
@@ -313,3 +314,5 @@ To be able to access the web UI this port needs to be opened in the firewall.
 - Nginx will use the value of `sslTrustedCertificate` if provided for a virtual host, even if `enableACME` is set. This is useful for providers not using the same certificate to sign OCSP responses and server certificates.
 
 - `lib.formats.yaml`'s `generate` will not generate JSON anymore, but instead use more of the YAML-specific syntax.
+
+- GNOME desktop environment now enables `QGnomePlatform` as the Qt platform theme, which should avoid crashes when opening file chooser dialogs in Qt apps by using XDG desktop portal. Additionally, it will make the apps fit better visually.
diff --git a/nixos/modules/hardware/video/nvidia.nix b/nixos/modules/hardware/video/nvidia.nix
index 1e125eced2cb..cf87ca5377dd 100644
--- a/nixos/modules/hardware/video/nvidia.nix
+++ b/nixos/modules/hardware/video/nvidia.nix
@@ -23,6 +23,7 @@ let
   offloadCfg = pCfg.offload;
   primeEnabled = syncCfg.enable || offloadCfg.enable;
   nvidiaPersistencedEnabled =  cfg.nvidiaPersistenced;
+  nvidiaSettings = cfg.nvidiaSettings;
 in
 
 {
@@ -143,6 +144,15 @@ in
       '';
     };
 
+    hardware.nvidia.nvidiaSettings = mkOption {
+      default = true;
+      type = types.bool;
+      description = ''
+        Whether to add nvidia-settings, NVIDIA's GUI configuration tool, to
+        systemPackages.
+      '';
+    };
+
     hardware.nvidia.nvidiaPersistenced = mkOption {
       default = false;
       type = types.bool;
@@ -279,7 +289,8 @@ in
     hardware.opengl.extraPackages = optional offloadCfg.enable nvidia_x11.out;
     hardware.opengl.extraPackages32 = optional offloadCfg.enable nvidia_x11.lib32;
 
-    environment.systemPackages = [ nvidia_x11.bin nvidia_x11.settings ]
+    environment.systemPackages = [ nvidia_x11.bin ]
+      ++ optionals nvidiaSettings [ nvidia_x11.settings ]
       ++ optionals nvidiaPersistencedEnabled [ nvidia_x11.persistenced ];
 
     systemd.packages = optional cfg.powerManagement.enable nvidia_x11.out;
diff --git a/nixos/modules/services/audio/roon-bridge.nix b/nixos/modules/services/audio/roon-bridge.nix
index 85273a2039c3..e08f8a4f9e7a 100644
--- a/nixos/modules/services/audio/roon-bridge.nix
+++ b/nixos/modules/services/audio/roon-bridge.nix
@@ -14,9 +14,6 @@ in {
         default = false;
         description = ''
           Open ports in the firewall for the bridge.
-
-          UDP: 9003
-          TCP: 9100 - 9200
         '';
       };
       user = mkOption {
@@ -54,10 +51,15 @@ in {
     };
 
     networking.firewall = mkIf cfg.openFirewall {
-      allowedTCPPortRanges = [
-        { from = 9100; to = 9200; }
-      ];
+      allowedTCPPortRanges = [{ from = 9100; to = 9200; }];
       allowedUDPPorts = [ 9003 ];
+      extraCommands = ''
+        iptables -A INPUT -s 224.0.0.0/4 -j ACCEPT
+        iptables -A INPUT -d 224.0.0.0/4 -j ACCEPT
+        iptables -A INPUT -s 240.0.0.0/5 -j ACCEPT
+        iptables -A INPUT -m pkttype --pkt-type multicast -j ACCEPT
+        iptables -A INPUT -m pkttype --pkt-type broadcast -j ACCEPT
+      '';
     };
 
 
diff --git a/nixos/modules/services/audio/roon-server.nix b/nixos/modules/services/audio/roon-server.nix
index eceb65044c5b..42da5a100170 100644
--- a/nixos/modules/services/audio/roon-server.nix
+++ b/nixos/modules/services/audio/roon-server.nix
@@ -14,9 +14,6 @@ in {
         default = false;
         description = ''
           Open ports in the firewall for the server.
-
-          UDP: 9003
-          TCP: 9100 - 9200
         '';
       };
       user = mkOption {
@@ -54,10 +51,15 @@ in {
     };
 
     networking.firewall = mkIf cfg.openFirewall {
-      allowedTCPPortRanges = [
-        { from = 9100; to = 9200; }
-      ];
+      allowedTCPPortRanges = [{ from = 9100; to = 9200; }];
       allowedUDPPorts = [ 9003 ];
+      extraCommands = ''
+        iptables -A INPUT -s 224.0.0.0/4 -j ACCEPT
+        iptables -A INPUT -d 224.0.0.0/4 -j ACCEPT
+        iptables -A INPUT -s 240.0.0.0/5 -j ACCEPT
+        iptables -A INPUT -m pkttype --pkt-type multicast -j ACCEPT
+        iptables -A INPUT -m pkttype --pkt-type broadcast -j ACCEPT
+      '';
     };
 
 
diff --git a/nixos/modules/services/desktops/pipewire/bluez-hardware.conf.json b/nixos/modules/services/desktops/pipewire/bluez-hardware.conf.json
index cae9e1bdba06..46697ece4483 100644
--- a/nixos/modules/services/desktops/pipewire/bluez-hardware.conf.json
+++ b/nixos/modules/services/desktops/pipewire/bluez-hardware.conf.json
@@ -198,6 +198,17 @@
     },
     {
       "sysname": "Linux",
+      "release": "~^5\\.10\\.(1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31|32|33|34|35|36|37|38|39|40|41|42|43|44|45|46|47|48|49|50)($|[^0-9])"
+    },
+    {
+      "sysname": "Linux",
+      "release": "~^5\\.10\\.",
+      "no-features": [
+        "msbc-alt1"
+      ]
+    },
+    {
+      "sysname": "Linux",
       "release": "~^5\\.12\\.(1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17)($|[^0-9])"
     },
     {
diff --git a/nixos/modules/services/desktops/pipewire/pipewire-pulse.conf.json b/nixos/modules/services/desktops/pipewire/pipewire-pulse.conf.json
index 17bbbdef1179..3ed994f11145 100644
--- a/nixos/modules/services/desktops/pipewire/pipewire-pulse.conf.json
+++ b/nixos/modules/services/desktops/pipewire/pipewire-pulse.conf.json
@@ -37,5 +37,6 @@
       }
     }
   ],
+  "context.exec": [],
   "stream.properties": {}
 }
diff --git a/nixos/modules/services/network-filesystems/ipfs.nix b/nixos/modules/services/network-filesystems/ipfs.nix
index 1d5c03787496..57f5f6b006c8 100644
--- a/nixos/modules/services/network-filesystems/ipfs.nix
+++ b/nixos/modules/services/network-filesystems/ipfs.nix
@@ -5,36 +5,41 @@ let
   opt = options.services.ipfs;
 
   ipfsFlags = toString ([
-    (optionalString  cfg.autoMount                   "--mount")
-    (optionalString  cfg.enableGC                    "--enable-gc")
-    (optionalString (cfg.serviceFdlimit != null)     "--manage-fdlimit=false")
-    (optionalString (cfg.defaultMode == "offline")   "--offline")
+    (optionalString cfg.autoMount "--mount")
+    (optionalString cfg.enableGC "--enable-gc")
+    (optionalString (cfg.serviceFdlimit != null) "--manage-fdlimit=false")
+    (optionalString (cfg.defaultMode == "offline") "--offline")
     (optionalString (cfg.defaultMode == "norouting") "--routing=none")
   ] ++ cfg.extraFlags);
 
   splitMulitaddr = addrRaw: lib.tail (lib.splitString "/" addrRaw);
 
-  multiaddrToListenStream = addrRaw: let
+  multiaddrToListenStream = addrRaw:
+    let
       addr = splitMulitaddr addrRaw;
       s = builtins.elemAt addr;
-    in if s 0 == "ip4" && s 2 == "tcp"
-      then "${s 1}:${s 3}"
+    in
+    if s 0 == "ip4" && s 2 == "tcp"
+    then "${s 1}:${s 3}"
     else if s 0 == "ip6" && s 2 == "tcp"
-      then "[${s 1}]:${s 3}"
+    then "[${s 1}]:${s 3}"
     else if s 0 == "unix"
-      then "/${lib.concatStringsSep "/" (lib.tail addr)}"
+    then "/${lib.concatStringsSep "/" (lib.tail addr)}"
     else null; # not valid for listen stream, skip
 
-  multiaddrToListenDatagram = addrRaw: let
+  multiaddrToListenDatagram = addrRaw:
+    let
       addr = splitMulitaddr addrRaw;
       s = builtins.elemAt addr;
-    in if s 0 == "ip4" && s 2 == "udp"
-      then "${s 1}:${s 3}"
+    in
+    if s 0 == "ip4" && s 2 == "udp"
+    then "${s 1}:${s 3}"
     else if s 0 == "ip6" && s 2 == "udp"
-      then "[${s 1}]:${s 3}"
+    then "[${s 1}]:${s 3}"
     else null; # not valid for listen datagram, skip
 
-in {
+in
+{
 
   ###### interface
 
@@ -65,9 +70,10 @@ in {
 
       dataDir = mkOption {
         type = types.str;
-        default = if versionAtLeast config.system.stateVersion "17.09"
-                  then "/var/lib/ipfs"
-                  else "/var/lib/ipfs/.ipfs";
+        default =
+          if versionAtLeast config.system.stateVersion "17.09"
+          then "/var/lib/ipfs"
+          else "/var/lib/ipfs/.ipfs";
         description = "The data dir for IPFS";
       };
 
@@ -83,6 +89,12 @@ in {
         description = "Whether IPFS should try to mount /ipfs and /ipns at startup.";
       };
 
+      autoMigrate = mkOption {
+        type = types.bool;
+        default = true;
+        description = "Whether IPFS should try to run the fs-repo-migration at startup.";
+      };
+
       ipfsMountDir = mkOption {
         type = types.str;
         default = "/ipfs";
@@ -137,7 +149,7 @@ in {
           These are applied last, so may override configuration set by other options in this module.
           Keep in mind that this configuration is stateful; i.e., unsetting anything in here does not reset the value to the default!
         '';
-        default = {};
+        default = { };
         example = {
           Datastore.StorageMax = "100GB";
           Discovery.MDNS.Enabled = false;
@@ -153,7 +165,7 @@ in {
       extraFlags = mkOption {
         type = types.listOf types.str;
         description = "Extra flags passed to the IPFS daemon";
-        default = [];
+        default = [ ];
       };
 
       localDiscovery = mkOption {
@@ -168,7 +180,7 @@ in {
         type = types.nullOr types.int;
         default = null;
         description = "The fdlimit for the IPFS systemd unit or <literal>null</literal> to have the daemon attempt to manage it";
-        example = 64*1024;
+        example = 64 * 1024;
       };
 
       startWhenNeeded = mkOption {
@@ -186,6 +198,9 @@ in {
     environment.systemPackages = [ cfg.package ];
     environment.variables.IPFS_PATH = cfg.dataDir;
 
+    # https://github.com/lucas-clemente/quic-go/wiki/UDP-Receive-Buffer-Size
+    boot.kernel.sysctl."net.core.rmem_max" = mkDefault 2500000;
+
     programs.fuse = mkIf cfg.autoMount {
       userAllowOther = true;
     };
@@ -234,25 +249,28 @@ in {
         ipfs --offline config Mounts.FuseAllowOther --json true
         ipfs --offline config Mounts.IPFS ${cfg.ipfsMountDir}
         ipfs --offline config Mounts.IPNS ${cfg.ipnsMountDir}
+      '' + optionalString cfg.autoMigrate ''
+        ${pkgs.ipfs-migrator}/bin/fs-repo-migrations -y
       '' + concatStringsSep "\n" (collect
-            isString
-            (mapAttrsRecursive
-              (path: value:
-              # Using heredoc below so that the value is never improperly quoted
-              ''
-                read value <<EOF
-                ${builtins.toJSON value}
-                EOF
-                ipfs --offline config --json "${concatStringsSep "." path}" "$value"
-              '')
-              ({ Addresses.API = cfg.apiAddress;
-                 Addresses.Gateway = cfg.gatewayAddress;
-                 Addresses.Swarm = cfg.swarmAddress;
-              } //
-              cfg.extraConfig))
-          );
+        isString
+        (mapAttrsRecursive
+          (path: value:
+            # Using heredoc below so that the value is never improperly quoted
+            ''
+              read value <<EOF
+              ${builtins.toJSON value}
+              EOF
+              ipfs --offline config --json "${concatStringsSep "." path}" "$value"
+            '')
+          ({
+            Addresses.API = cfg.apiAddress;
+            Addresses.Gateway = cfg.gatewayAddress;
+            Addresses.Swarm = cfg.swarmAddress;
+          } //
+          cfg.extraConfig))
+      );
       serviceConfig = {
-        ExecStart = ["" "${cfg.package}/bin/ipfs daemon ${ipfsFlags}"];
+        ExecStart = [ "" "${cfg.package}/bin/ipfs daemon ${ipfsFlags}" ];
         User = cfg.user;
         Group = cfg.group;
       } // optionalAttrs (cfg.serviceFdlimit != null) { LimitNOFILE = cfg.serviceFdlimit; };
@@ -263,12 +281,16 @@ in {
     systemd.sockets.ipfs-gateway = {
       wantedBy = [ "sockets.target" ];
       socketConfig = {
-        ListenStream = let
+        ListenStream =
+          let
             fromCfg = multiaddrToListenStream cfg.gatewayAddress;
-          in [ "" ] ++ lib.optional (fromCfg != null) fromCfg;
-        ListenDatagram = let
+          in
+          [ "" ] ++ lib.optional (fromCfg != null) fromCfg;
+        ListenDatagram =
+          let
             fromCfg = multiaddrToListenDatagram cfg.gatewayAddress;
-          in [ "" ] ++ lib.optional (fromCfg != null) fromCfg;
+          in
+          [ "" ] ++ lib.optional (fromCfg != null) fromCfg;
       };
     };
 
@@ -276,9 +298,11 @@ in {
       wantedBy = [ "sockets.target" ];
       # We also include "%t/ipfs.sock" because there is no way to put the "%t"
       # in the multiaddr.
-      socketConfig.ListenStream = let
+      socketConfig.ListenStream =
+        let
           fromCfg = multiaddrToListenStream cfg.apiAddress;
-        in [ "" "%t/ipfs.sock" ] ++ lib.optional (fromCfg != null) fromCfg;
+        in
+        [ "" "%t/ipfs.sock" ] ++ lib.optional (fromCfg != null) fromCfg;
     };
 
   };
diff --git a/nixos/modules/services/networking/syncthing.nix b/nixos/modules/services/networking/syncthing.nix
index d77562701492..ebe4d89a0e7f 100644
--- a/nixos/modules/services/networking/syncthing.nix
+++ b/nixos/modules/services/networking/syncthing.nix
@@ -37,7 +37,7 @@ let
     do sleep 1; done
 
     curl() {
-        ${pkgs.curl}/bin/curl -sS -H "X-API-Key: $api_key" \
+        ${pkgs.curl}/bin/curl -sSLk -H "X-API-Key: $api_key" \
             --retry 1000 --retry-delay 1 --retry-all-errors \
             "$@"
     }
@@ -46,7 +46,7 @@ let
     old_cfg=$(curl ${cfg.guiAddress}/rest/config)
 
     # generate the new config by merging with the NixOS config options
-    new_cfg=$(echo "$old_cfg" | ${pkgs.jq}/bin/jq -c '. * {
+    new_cfg=$(printf '%s\n' "$old_cfg" | ${pkgs.jq}/bin/jq -c '. * {
         "devices": (${builtins.toJSON devices}${optionalString (! cfg.overrideDevices) " + .devices"}),
         "folders": (${builtins.toJSON folders}${optionalString (! cfg.overrideFolders) " + .folders"})
     } * ${builtins.toJSON cfg.extraOptions}')
diff --git a/nixos/modules/services/search/elasticsearch.nix b/nixos/modules/services/search/elasticsearch.nix
index 91d8f544e16b..440f34b3dc5c 100644
--- a/nixos/modules/services/search/elasticsearch.nix
+++ b/nixos/modules/services/search/elasticsearch.nix
@@ -5,8 +5,6 @@ with lib;
 let
   cfg = config.services.elasticsearch;
 
-  es6 = builtins.compareVersions cfg.package.version "6" >= 0;
-
   esConfig = ''
     network.host: ${cfg.listenAddress}
     cluster.name: ${cfg.cluster_name}
@@ -36,7 +34,8 @@ let
     postBuild = "${pkgs.coreutils}/bin/mkdir -p $out/plugins";
   };
 
-in {
+in
+{
 
   ###### interface
 
@@ -116,20 +115,20 @@ in {
 
     extraCmdLineOptions = mkOption {
       description = "Extra command line options for the elasticsearch launcher.";
-      default = [];
+      default = [ ];
       type = types.listOf types.str;
     };
 
     extraJavaOptions = mkOption {
       description = "Extra command line options for Java.";
-      default = [];
+      default = [ ];
       type = types.listOf types.str;
       example = [ "-Djava.net.preferIPv4Stack=true" ];
     };
 
     plugins = mkOption {
       description = "Extra elasticsearch plugins";
-      default = [];
+      default = [ ];
       type = types.listOf types.package;
       example = lib.literalExample "[ pkgs.elasticsearchPlugins.discovery-ec2 ]";
     };
@@ -146,9 +145,7 @@ in {
       path = [ pkgs.inetutils ];
       environment = {
         ES_HOME = cfg.dataDir;
-        ES_JAVA_OPTS = toString ( optional (!es6) [ "-Des.path.conf=${configDir}" ]
-                                  ++ cfg.extraJavaOptions);
-      } // optionalAttrs es6 {
+        ES_JAVA_OPTS = toString cfg.extraJavaOptions;
         ES_PATH_CONF = configDir;
       };
       serviceConfig = {
@@ -187,7 +184,10 @@ in {
         rm -f "${configDir}/logging.yml"
         cp ${loggingConfigFile} ${configDir}/${loggingConfigFilename}
         mkdir -p ${configDir}/scripts
-        ${optionalString es6 "cp ${cfg.package}/config/jvm.options ${configDir}/jvm.options"}
+        cp ${cfg.package}/config/jvm.options ${configDir}/jvm.options
+        # redirect jvm logs to the data directory
+        mkdir -m 0700 -p ${cfg.dataDir}/logs
+        ${pkgs.sd}/bin/sd 'logs/gc.log' '${cfg.dataDir}/logs/gc.log' ${configDir}/jvm.options \
 
         if [ "$(id -u)" = 0 ]; then chown -R elasticsearch:elasticsearch ${cfg.dataDir}; fi
       '';
diff --git a/nixos/modules/services/web-apps/nextcloud.xml b/nixos/modules/services/web-apps/nextcloud.xml
index 3af37b15dd56..ed84487d233a 100644
--- a/nixos/modules/services/web-apps/nextcloud.xml
+++ b/nixos/modules/services/web-apps/nextcloud.xml
@@ -84,47 +84,93 @@
 </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>
-   All configuration parameters are also stored in
-   <literal>/var/lib/nextcloud/config/override.config.php</literal> which is generated by
-   the module and linked from the store to ensure that all values from <literal>config.php</literal>
-   can be modified by the module.
-   However <literal>config.php</literal> manages the application's state and shouldn't be touched
-   manually because of that.
-  </para>
-
-  <warning>
-   <para>Don't delete <literal>config.php</literal>! This file
-   tracks the application's state and a deletion can cause unwanted
-   side-effects!</para>
-  </warning>
-
-  <warning>
-   <para>Don't rerun <literal>nextcloud-occ
-   maintenance:install</literal>! This command tries to install the application
-   and can cause unwanted side-effects!</para>
-  </warning>
+ <section xml:id="module-services-nextcloud-pitfalls-during-upgrade">
+  <title>Common problems</title>
+  <itemizedlist>
+   <listitem>
+    <formalpara>
+     <title>General notes</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>
+    </formalpara>
+    <para>
+     All configuration parameters are also stored in
+     <filename>/var/lib/nextcloud/config/override.config.php</filename> which is generated by
+     the module and linked from the store to ensure that all values from
+     <filename>config.php</filename> can be modified by the module.
+     However <filename>config.php</filename> manages the application's state and shouldn't be
+     touched manually because of that.
+    </para>
+    <warning>
+     <para>Don't delete <filename>config.php</filename>! This file
+     tracks the application's state and a deletion can cause unwanted
+     side-effects!</para>
+    </warning>
 
-  <para>
-   Nextcloud doesn't allow to move more than one major-version forward. If you're e.g. on
-   <literal>v16</literal>, you cannot upgrade to <literal>v18</literal>, you need to upgrade to
-   <literal>v17</literal> first. This is ensured automatically as long as the
-   <link linkend="opt-system.stateVersion">stateVersion</link> is declared properly. In that case
-   the oldest version available (one major behind the one from the previous NixOS
-   release) will be selected by default and the module will generate a warning that reminds
-   the user to upgrade to latest Nextcloud <emphasis>after</emphasis> that deploy.
-  </para>
+    <warning>
+     <para>Don't rerun <literal>nextcloud-occ
+     maintenance:install</literal>! This command tries to install the application
+     and can cause unwanted side-effects!</para>
+    </warning>
+   </listitem>
+   <listitem>
+    <formalpara>
+     <title>Multiple version upgrades</title>
+     <para>
+      Nextcloud doesn't allow to move more than one major-version forward. E.g., if you're on
+      <literal>v16</literal>, you cannot upgrade to <literal>v18</literal>, you need to upgrade to
+      <literal>v17</literal> first. This is ensured automatically as long as the
+      <link linkend="opt-system.stateVersion">stateVersion</link> is declared properly. In that case
+      the oldest version available (one major behind the one from the previous NixOS
+      release) will be selected by default and the module will generate a warning that reminds
+      the user to upgrade to latest Nextcloud <emphasis>after</emphasis> that deploy.
+     </para>
+    </formalpara>
+   </listitem>
+   <listitem>
+    <formalpara>
+     <title><literal>Error: Command "upgrade" is not defined.</literal></title>
+     <para>
+      This error usually occurs if the initial installation
+      (<command>nextcloud-occ maintenance:install</command>) has failed. After that, the application
+      is not installed, but the upgrade is attempted to be executed. Further context can
+      be found in <link xlink:href="https://github.com/NixOS/nixpkgs/issues/111175">NixOS/nixpkgs#111175</link>.
+     </para>
+    </formalpara>
+    <para>
+     First of all, it makes sense to find out what went wrong by looking at the logs
+     of the installation via <command>journalctl -u nextcloud-setup</command> and try to fix
+     the underlying issue.
+    </para>
+    <itemizedlist>
+     <listitem>
+      <para>
+       If this occurs on an <emphasis>existing</emphasis> setup, this is most likely because
+       the maintenance mode is active. It can be deactivated by running
+       <command>nextcloud-occ maintenance:mode --off</command>. It's advisable though to
+       check the logs first on why the maintenance mode was activated.
+      </para>
+     </listitem>
+     <listitem>
+      <warning><para>Only perform the following measures on
+      <emphasis>freshly installed instances!</emphasis></para></warning>
+      <para>
+       A re-run of the installer can be forced by <emphasis>deleting</emphasis>
+       <filename>/var/lib/nextcloud/config/config.php</filename>. This is the only time
+       advisable because the fresh install doesn't have any state that can be lost.
+       In case that doesn't help, an entire re-creation can be forced via
+       <command>rm -rf ~nextcloud/</command>.
+      </para>
+     </listitem>
+    </itemizedlist>
+   </listitem>
+  </itemizedlist>
  </section>
 
  <section xml:id="module-services-nextcloud-httpd">
diff --git a/nixos/modules/services/x11/desktop-managers/gnome.nix b/nixos/modules/services/x11/desktop-managers/gnome.nix
index b0859321a525..4bc42525906c 100644
--- a/nixos/modules/services/x11/desktop-managers/gnome.nix
+++ b/nixos/modules/services/x11/desktop-managers/gnome.nix
@@ -372,6 +372,13 @@ in
       xdg.portal.enable = true;
       xdg.portal.extraPortals = [ pkgs.xdg-desktop-portal-gtk ];
 
+      # Harmonize Qt5 application style and also make them use the portal for file chooser dialog.
+      qt5 = {
+        enable = mkDefault true;
+        platformTheme = mkDefault "gnome";
+        style = mkDefault "adwaita";
+      };
+
       networking.networkmanager.enable = mkDefault true;
 
       services.xserver.updateDbusEnvironment = true;
diff --git a/nixos/modules/services/x11/window-managers/clfswm.nix b/nixos/modules/services/x11/window-managers/clfswm.nix
index 171660c53ac3..5015852db69f 100644
--- a/nixos/modules/services/x11/window-managers/clfswm.nix
+++ b/nixos/modules/services/x11/window-managers/clfswm.nix
@@ -8,17 +8,27 @@ in
 
 {
   options = {
-    services.xserver.windowManager.clfswm.enable = mkEnableOption "clfswm";
+    services.xserver.windowManager.clfswm = {
+      enable = mkEnableOption "clfswm";
+      package = mkOption {
+        type        = types.package;
+        default     = pkgs.lispPackages.clfswm;
+        defaultText = "pkgs.lispPackages.clfswm";
+        description = ''
+          clfswm package to use.
+        '';
+      };
+    };
   };
 
   config = mkIf cfg.enable {
     services.xserver.windowManager.session = singleton {
       name = "clfswm";
       start = ''
-        ${pkgs.lispPackages.clfswm}/bin/clfswm &
+        ${cfg.package}/bin/clfswm &
         waitPID=$!
       '';
     };
-    environment.systemPackages = [ pkgs.lispPackages.clfswm ];
+    environment.systemPackages = [ cfg.package ];
   };
 }
diff --git a/nixos/tests/caddy.nix b/nixos/tests/caddy.nix
index 29b227c0409b..0902904b2086 100644
--- a/nixos/tests/caddy.nix
+++ b/nixos/tests/caddy.nix
@@ -50,57 +50,58 @@ import ./make-test-python.nix ({ pkgs, ... }: {
         };
       };
     };
+  };
 
-    testScript = { nodes, ... }:
-      let
-        etagSystem = "${nodes.webserver.config.system.build.toplevel}/specialisation/etag";
-        justReloadSystem = "${nodes.webserver.config.system.build.toplevel}/specialisation/config-reload";
-        multipleConfigs = "${nodes.webserver.config.system.build.toplevel}/specialisation/multiple-configs";
-      in
-      ''
-        url = "http://localhost/example.html"
-        webserver.wait_for_unit("caddy")
-        webserver.wait_for_open_port("80")
+  testScript = { nodes, ... }:
+    let
+      etagSystem = "${nodes.webserver.config.system.build.toplevel}/specialisation/etag";
+      justReloadSystem = "${nodes.webserver.config.system.build.toplevel}/specialisation/config-reload";
+      multipleConfigs = "${nodes.webserver.config.system.build.toplevel}/specialisation/multiple-configs";
+    in
+    ''
+      url = "http://localhost/example.html"
+      webserver.wait_for_unit("caddy")
+      webserver.wait_for_open_port("80")
 
 
-        def check_etag(url):
-            etag = webserver.succeed(
-                "curl --fail -v '{}' 2>&1 | sed -n -e \"s/^< [Ee][Tt][Aa][Gg]: *//p\"".format(
-                    url
-                )
-            )
-            etag = etag.replace("\r\n", " ")
-            http_code = webserver.succeed(
-                "curl --fail --silent --show-error -o /dev/null -w \"%{{http_code}}\" --head -H 'If-None-Match: {}' {}".format(
-                    etag, url
-                )
-            )
-            assert int(http_code) == 304, "HTTP code is {}, expected 304".format(http_code)
-            return etag
+      def check_etag(url):
+          etag = webserver.succeed(
+              "curl --fail -v '{}' 2>&1 | sed -n -e \"s/^< [Ee][Tt][Aa][Gg]: *//p\"".format(
+                  url
+              )
+          )
+          etag = etag.replace("\r\n", " ")
+          http_code = webserver.succeed(
+              "curl --fail --silent --show-error -o /dev/null -w \"%{{http_code}}\" --head -H 'If-None-Match: {}' {}".format(
+                  etag, url
+              )
+          )
+          assert int(http_code) == 304, "HTTP code is {}, expected 304".format(http_code)
+          return etag
 
 
-        with subtest("check ETag if serving Nix store paths"):
-            old_etag = check_etag(url)
-            webserver.succeed(
-                "${etagSystem}/bin/switch-to-configuration test >&2"
-            )
-            webserver.sleep(1)
-            new_etag = check_etag(url)
-            assert old_etag != new_etag, "Old ETag {} is the same as {}".format(
-                old_etag, new_etag
-            )
+      with subtest("check ETag if serving Nix store paths"):
+          old_etag = check_etag(url)
+          webserver.succeed(
+              "${etagSystem}/bin/switch-to-configuration test >&2"
+          )
+          webserver.sleep(1)
+          new_etag = check_etag(url)
+          assert old_etag != new_etag, "Old ETag {} is the same as {}".format(
+              old_etag, new_etag
+          )
 
-        with subtest("config is reloaded on nixos-rebuild switch"):
-            webserver.succeed(
-                "${justReloadSystem}/bin/switch-to-configuration test >&2"
-            )
-            webserver.wait_for_open_port("8080")
+      with subtest("config is reloaded on nixos-rebuild switch"):
+          webserver.succeed(
+              "${justReloadSystem}/bin/switch-to-configuration test >&2"
+          )
+          webserver.wait_for_open_port("8080")
 
-        with subtest("multiple configs are correctly merged"):
-            webserver.succeed(
-                "${multipleConfigs}/bin/switch-to-configuration test >&2"
-            )
-            webserver.wait_for_open_port("8080")
-            webserver.wait_for_open_port("8081")
-      '';
-  })
+      with subtest("multiple configs are correctly merged"):
+          webserver.succeed(
+              "${multipleConfigs}/bin/switch-to-configuration test >&2"
+          )
+          webserver.wait_for_open_port("8080")
+          webserver.wait_for_open_port("8081")
+    '';
+})