summary refs log tree commit diff
path: root/nixos/modules
diff options
context:
space:
mode:
Diffstat (limited to 'nixos/modules')
-rw-r--r--nixos/modules/installer/tools/nixos-rebuild.sh12
-rw-r--r--nixos/modules/misc/documentation.nix17
-rw-r--r--nixos/modules/module-list.nix2
-rw-r--r--nixos/modules/services/backup/duplicity.nix141
-rw-r--r--nixos/modules/services/desktops/gnome3/gnome-settings-daemon.nix45
-rw-r--r--nixos/modules/services/hardware/thinkfan.nix20
-rw-r--r--nixos/modules/services/mail/rmilter.nix4
-rw-r--r--nixos/modules/services/misc/home-assistant.nix20
-rw-r--r--nixos/modules/services/misc/redmine.nix72
-rw-r--r--nixos/modules/services/monitoring/datadog-agent.nix2
-rw-r--r--nixos/modules/services/networking/mosquitto.nix9
-rw-r--r--nixos/modules/services/web-apps/nextcloud.nix53
-rw-r--r--nixos/modules/services/web-servers/nginx/default.nix7
-rw-r--r--nixos/modules/services/web-servers/nginx/vhost-options.nix1
-rw-r--r--nixos/modules/services/x11/desktop-managers/gnome3.nix2
-rw-r--r--nixos/modules/services/x11/desktop-managers/mate.nix26
-rw-r--r--nixos/modules/services/x11/desktop-managers/pantheon.nix3
-rw-r--r--nixos/modules/services/x11/xserver.nix6
18 files changed, 339 insertions, 103 deletions
diff --git a/nixos/modules/installer/tools/nixos-rebuild.sh b/nixos/modules/installer/tools/nixos-rebuild.sh
index 27e5b5d8c70..6a08c9b4c6c 100644
--- a/nixos/modules/installer/tools/nixos-rebuild.sh
+++ b/nixos/modules/installer/tools/nixos-rebuild.sh
@@ -267,6 +267,14 @@ if [ -n "$rollback" -o "$action" = dry-build ]; then
     buildNix=
 fi
 
+nixSystem() {
+    machine="$(uname -m)"
+    if [[ "$machine" =~ i.86 ]]; then
+        machine=i686
+    fi
+    echo $machine-linux
+}
+
 prebuiltNix() {
     machine="$1"
     if [ "$machine" = x86_64 ]; then
@@ -286,7 +294,9 @@ if [ -n "$buildNix" ]; then
     nixDrv=
     if ! nixDrv="$(nix-instantiate '<nixpkgs/nixos>' --add-root $tmpDir/nix.drv --indirect -A config.nix.package.out "${extraBuildFlags[@]}")"; then
         if ! nixDrv="$(nix-instantiate '<nixpkgs>' --add-root $tmpDir/nix.drv --indirect -A nix "${extraBuildFlags[@]}")"; then
-            nixStorePath="$(prebuiltNix "$(uname -m)")"
+            if ! nixStorePath="$(nix-instantiate --eval '<nixpkgs/nixos/modules/installer/tools/nix-fallback-paths.nix>' -A $(nixSystem) | sed -e 's/^"//' -e 's/"$//')"; then
+                nixStorePath="$(prebuiltNix "$(uname -m)")"
+            fi
             if ! nix-store -r $nixStorePath --add-root $tmpDir/nix --indirect \
                 --option extra-binary-caches https://cache.nixos.org/; then
                 echo "warning: don't know how to get latest Nix" >&2
diff --git a/nixos/modules/misc/documentation.nix b/nixos/modules/misc/documentation.nix
index 9b2e1235b74..834ac0de912 100644
--- a/nixos/modules/misc/documentation.nix
+++ b/nixos/modules/misc/documentation.nix
@@ -1,4 +1,4 @@
-{ config, lib, pkgs, baseModules, ... }:
+{ config, lib, pkgs, baseModules, extraModules, modules, ... }:
 
 with lib;
 
@@ -6,6 +6,8 @@ let
 
   cfg = config.documentation;
 
+  manualModules = baseModules ++ optionals cfg.nixos.includeAllModules (extraModules ++ modules);
+
   /* For the purpose of generating docs, evaluate options with each derivation
     in `pkgs` (recursively) replaced by a fake with path "\${pkgs.attribute.path}".
     It isn't perfect, but it seems to cover a vast majority of use cases.
@@ -18,7 +20,7 @@ let
     options =
       let
         scrubbedEval = evalModules {
-          modules = [ { nixpkgs.localSystem = config.nixpkgs.localSystem; } ] ++ baseModules;
+          modules = [ { nixpkgs.localSystem = config.nixpkgs.localSystem; } ] ++ manualModules;
           args = (config._module.args) // { modules = [ ]; };
           specialArgs = { pkgs = scrubDerivations "pkgs" pkgs; };
         };
@@ -146,6 +148,17 @@ in
         '';
       };
 
+      nixos.includeAllModules = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Whether the generated NixOS's documentation should include documentation for all
+          the options from all the NixOS modules included in the current
+          <literal>configuration.nix</literal>. Disabling this will make the manual
+          generator to ignore options defined outside of <literal>baseModules</literal>.
+        '';
+      };
+
     };
 
   };
diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix
index 031a1d52e79..5b95fc8ecc3 100644
--- a/nixos/modules/module-list.nix
+++ b/nixos/modules/module-list.nix
@@ -189,6 +189,7 @@
   ./services/backup/duplicati.nix
   ./services/backup/crashplan.nix
   ./services/backup/crashplan-small-business.nix
+  ./services/backup/duplicity.nix
   ./services/backup/mysql-backup.nix
   ./services/backup/postgresql-backup.nix
   ./services/backup/restic.nix
@@ -268,6 +269,7 @@
   ./services/desktops/gnome3/gnome-online-accounts.nix
   ./services/desktops/gnome3/gnome-remote-desktop.nix
   ./services/desktops/gnome3/gnome-online-miners.nix
+  ./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
diff --git a/nixos/modules/services/backup/duplicity.nix b/nixos/modules/services/backup/duplicity.nix
new file mode 100644
index 00000000000..a8d56424862
--- /dev/null
+++ b/nixos/modules/services/backup/duplicity.nix
@@ -0,0 +1,141 @@
+{ config, lib, pkgs, ...}:
+
+with lib;
+
+let
+  cfg = config.services.duplicity;
+
+  stateDirectory = "/var/lib/duplicity";
+
+  localTarget = if hasPrefix "file://" cfg.targetUrl
+    then removePrefix "file://" cfg.targetUrl else null;
+
+in {
+  options.services.duplicity = {
+    enable = mkEnableOption "backups with duplicity";
+
+    root = mkOption {
+      type = types.path;
+      default = "/";
+      description = ''
+        Root directory to backup.
+      '';
+    };
+
+    include = mkOption {
+      type = types.listOf types.str;
+      default = [];
+      example = [ "/home" ];
+      description = ''
+        List of paths to include into the backups. See the FILE SELECTION
+        section in <citerefentry><refentrytitle>duplicity</refentrytitle>
+        <manvolnum>1</manvolnum></citerefentry> for details on the syntax.
+      '';
+    };
+
+    exclude = mkOption {
+      type = types.listOf types.str;
+      default = [];
+      description = ''
+        List of paths to exclude from backups. See the FILE SELECTION section in
+        <citerefentry><refentrytitle>duplicity</refentrytitle>
+        <manvolnum>1</manvolnum></citerefentry> for details on the syntax.
+      '';
+    };
+
+    targetUrl = mkOption {
+      type = types.str;
+      example = "s3://host:port/prefix";
+      description = ''
+        Target url to backup to. See the URL FORMAT section in
+        <citerefentry><refentrytitle>duplicity</refentrytitle>
+        <manvolnum>1</manvolnum></citerefentry> for supported urls.
+      '';
+    };
+
+    secretFile = mkOption {
+      type = types.nullOr types.path;
+      default = null;
+      description = ''
+        Path of a file containing secrets (gpg passphrase, access key...) in
+        the format of EnvironmentFile as described by
+        <citerefentry><refentrytitle>systemd.exec</refentrytitle>
+        <manvolnum>5</manvolnum></citerefentry>. For example:
+        <programlisting>
+        PASSPHRASE=<replaceable>...</replaceable>
+        AWS_ACCESS_KEY_ID=<replaceable>...</replaceable>
+        AWS_SECRET_ACCESS_KEY=<replaceable>...</replaceable>
+        </programlisting>
+      '';
+    };
+
+    frequency = mkOption {
+      type = types.nullOr types.str;
+      default = "daily";
+      description = ''
+        Run duplicity with the given frequency (see
+        <citerefentry><refentrytitle>systemd.time</refentrytitle>
+        <manvolnum>7</manvolnum></citerefentry> for the format).
+        If null, do not run automatically.
+      '';
+    };
+
+    extraFlags = mkOption {
+      type = types.listOf types.str;
+      default = [];
+      example = [ "--full-if-older-than" "1M" ];
+      description = ''
+        Extra command-line flags passed to duplicity. See
+        <citerefentry><refentrytitle>duplicity</refentrytitle>
+        <manvolnum>1</manvolnum></citerefentry>.
+      '';
+    };
+  };
+
+  config = mkIf cfg.enable {
+    systemd = {
+      services.duplicity = {
+        description = "backup files with duplicity";
+
+        environment.HOME = stateDirectory;
+
+        serviceConfig = {
+          ExecStart = ''
+            ${pkgs.duplicity}/bin/duplicity ${escapeShellArgs (
+              [
+                cfg.root
+                cfg.targetUrl
+                "--archive-dir" stateDirectory
+              ]
+              ++ concatMap (p: [ "--include" p ]) cfg.include
+              ++ concatMap (p: [ "--exclude" p ]) cfg.exclude
+              ++ cfg.extraFlags)}
+          '';
+          PrivateTmp = true;
+          ProtectSystem = "strict";
+          ProtectHome = "read-only";
+          StateDirectory = baseNameOf stateDirectory;
+        } // optionalAttrs (localTarget != null) {
+          ReadWritePaths = localTarget;
+        } // optionalAttrs (cfg.secretFile != null) {
+          EnvironmentFile = cfg.secretFile;
+        };
+      } // optionalAttrs (cfg.frequency != null) {
+        startAt = cfg.frequency;
+      };
+
+      tmpfiles.rules = optional (localTarget != null) "d ${localTarget} 0700 root root -";
+    };
+
+    assertions = singleton {
+      # Duplicity will fail if the last file selection option is an include. It
+      # is not always possible to detect but this simple case can be caught.
+      assertion = cfg.include != [] -> cfg.exclude != [] || cfg.extraFlags != [];
+      message = ''
+        Duplicity will fail if you only specify included paths ("Because the
+        default is to include all files, the expression is redundant. Exiting
+        because this probably isn't what you meant.")
+      '';
+    };
+  };
+}
diff --git a/nixos/modules/services/desktops/gnome3/gnome-settings-daemon.nix b/nixos/modules/services/desktops/gnome3/gnome-settings-daemon.nix
new file mode 100644
index 00000000000..dbf0f4e9b11
--- /dev/null
+++ b/nixos/modules/services/desktops/gnome3/gnome-settings-daemon.nix
@@ -0,0 +1,45 @@
+# GNOME Settings Daemon
+
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+  cfg = config.services.gnome3.gnome-settings-daemon;
+
+in
+
+{
+
+  ###### interface
+
+  options = {
+
+    services.gnome3.gnome-settings-daemon = {
+
+      enable = mkEnableOption "GNOME Settings Daemon.";
+
+      # There are many forks of gnome-settings-daemon
+      package = mkOption {
+        type = types.package;
+        default = pkgs.gnome3.gnome-settings-daemon;
+        description = "Which gnome-settings-daemon package to use.";
+      };
+
+    };
+
+  };
+
+
+  ###### implementation
+
+  config = mkIf cfg.enable {
+
+    environment.systemPackages = [ cfg.package ];
+
+    services.udev.packages = [ cfg.package ];
+
+  };
+
+}
diff --git a/nixos/modules/services/hardware/thinkfan.nix b/nixos/modules/services/hardware/thinkfan.nix
index d17121ca1c5..7c105e99ca5 100644
--- a/nixos/modules/services/hardware/thinkfan.nix
+++ b/nixos/modules/services/hardware/thinkfan.nix
@@ -47,6 +47,8 @@ let
     ${cfg.levels}
   '';
 
+  thinkfan = pkgs.thinkfan.override { smartSupport = cfg.smartSupport; };
+
 in {
 
   options = {
@@ -61,6 +63,15 @@ in {
         '';
       };
 
+      smartSupport = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Whether to build thinkfan with SMART support to read temperatures 
+          directly from hard disks.
+        '';
+      };
+
       sensors = mkOption {
         type = types.lines;
         default = ''
@@ -77,7 +88,7 @@ in {
               Which may be provided by any hwmon drivers (keyword
               hwmon)
 
-            S.M.A.R.T. (since 0.9 and requires the USE_ATASMART compilation flag)
+            S.M.A.R.T. (requires smartSupport to be enabled)
               Which reads the temperature directly from the hard
               disk using libatasmart (keyword atasmart)
 
@@ -125,18 +136,17 @@ in {
 
   config = mkIf cfg.enable {
 
-    environment.systemPackages = [ pkgs.thinkfan ];
+    environment.systemPackages = [ thinkfan ];
 
     systemd.services.thinkfan = {
       description = "Thinkfan";
       after = [ "basic.target" ];
       wantedBy = [ "multi-user.target" ];
-      path = [ pkgs.thinkfan ];
-      serviceConfig.ExecStart = "${pkgs.thinkfan}/bin/thinkfan -n -c ${configFile}";
+      path = [ thinkfan ];
+      serviceConfig.ExecStart = "${thinkfan}/bin/thinkfan -n -c ${configFile}";
     };
 
     boot.extraModprobeConfig = "options thinkpad_acpi experimental=1 fan_control=1";
 
   };
-
 }
diff --git a/nixos/modules/services/mail/rmilter.nix b/nixos/modules/services/mail/rmilter.nix
index 492c6458321..466365b6b30 100644
--- a/nixos/modules/services/mail/rmilter.nix
+++ b/nixos/modules/services/mail/rmilter.nix
@@ -8,7 +8,7 @@ let
   postfixCfg = config.services.postfix;
   cfg = config.services.rmilter;
 
-  inetSocket = addr: port: "inet:[${toString port}@${addr}]";
+  inetSocket = addr: port: "inet:${addr}:${toString port}";
   unixSocket = sock: "unix:${sock}";
 
   systemdSocket = if cfg.bindSocket.type == "unix" then cfg.bindSocket.path
@@ -97,7 +97,7 @@ in
 
       bindSocket.address = mkOption {
         type = types.str;
-        default = "::1";
+        default = "[::1]";
         example = "0.0.0.0";
         description = ''
           Inet address to listen on.
diff --git a/nixos/modules/services/misc/home-assistant.nix b/nixos/modules/services/misc/home-assistant.nix
index 95a7f2ea989..7f8d31bcf0b 100644
--- a/nixos/modules/services/misc/home-assistant.nix
+++ b/nixos/modules/services/misc/home-assistant.nix
@@ -9,13 +9,13 @@ let
   configJSON = pkgs.writeText "configuration.json"
     (builtins.toJSON (if cfg.applyDefaultConfig then
     (recursiveUpdate defaultConfig cfg.config) else cfg.config));
-  configFile = pkgs.runCommand "configuration.yaml" { } ''
+  configFile = pkgs.runCommand "configuration.yaml" { preferLocalBuild = true; } ''
     ${pkgs.remarshal}/bin/json2yaml -i ${configJSON} -o $out
   '';
 
   lovelaceConfigJSON = pkgs.writeText "ui-lovelace.json"
     (builtins.toJSON cfg.lovelaceConfig);
-  lovelaceConfigFile = pkgs.runCommand "ui-lovelace.yaml" { } ''
+  lovelaceConfigFile = pkgs.runCommand "ui-lovelace.yaml" { preferLocalBuild = true; } ''
     ${pkgs.remarshal}/bin/json2yaml -i ${lovelaceConfigJSON} -o $out
   '';
 
@@ -29,14 +29,24 @@ let
   #   platform = "luftdaten";
   #   ...
   # } ];
+  #
+  # Beginning with 0.87 Home Assistant is migrating their components to the
+  # scheme "platform.subComponent", e.g. "hue.light" instead of "light.hue".
+  # See https://developers.home-assistant.io/blog/2019/02/19/the-great-migration.html.
+  # Hence, we also check whether we find an entry in the config when interpreting
+  # the first part of the path as the component.
   useComponentPlatform = component:
     let
       path = splitString "." component;
+      # old: platform is the last part of path
       parentConfig = attrByPath (init path) null cfg.config;
       platform = last path;
-    in isList parentConfig && any
-      (item: item.platform or null == platform)
-      parentConfig;
+      # new: platform is the first part of the path
+      parentConfig' = attrByPath (tail path) null cfg.config;
+      platform' = head path;
+    in
+      (isList parentConfig && any (item: item.platform or null == platform) parentConfig)
+      || (isList parentConfig' && any (item: item.platform or null == platform') parentConfig');
 
   # Returns whether component is used in config
   useComponent = component:
diff --git a/nixos/modules/services/misc/redmine.nix b/nixos/modules/services/misc/redmine.nix
index 98e9c8953c8..c38138d7c97 100644
--- a/nixos/modules/services/misc/redmine.nix
+++ b/nixos/modules/services/misc/redmine.nix
@@ -234,10 +234,33 @@ in
 
     environment.systemPackages = [ cfg.package ];
 
+    # create symlinks for the basic directory layout the redmine package expects
+    systemd.tmpfiles.rules = [
+      "d '${cfg.stateDir}' 0750 ${cfg.user} ${cfg.group} - -"
+      "d '${cfg.stateDir}/cache' 0750 ${cfg.user} ${cfg.group} - -"
+      "d '${cfg.stateDir}/config' 0750 ${cfg.user} ${cfg.group} - -"
+      "d '${cfg.stateDir}/files' 0750 ${cfg.user} ${cfg.group} - -"
+      "d '${cfg.stateDir}/log' 0750 ${cfg.user} ${cfg.group} - -"
+      "d '${cfg.stateDir}/plugins' 0750 ${cfg.user} ${cfg.group} - -"
+      "d '${cfg.stateDir}/public' 0750 ${cfg.user} ${cfg.group} - -"
+      "d '${cfg.stateDir}/public/plugin_assets' 0750 ${cfg.user} ${cfg.group} - -"
+      "d '${cfg.stateDir}/public/themes' 0750 ${cfg.user} ${cfg.group} - -"
+      "d '${cfg.stateDir}/tmp' 0750 ${cfg.user} ${cfg.group} - -"
+
+      "d /run/redmine - - - - -"
+      "d /run/redmine/public - - - - -"
+      "L+ /run/redmine/config - - - - ${cfg.stateDir}/config"
+      "L+ /run/redmine/files - - - - ${cfg.stateDir}/files"
+      "L+ /run/redmine/log - - - - ${cfg.stateDir}/log"
+      "L+ /run/redmine/plugins - - - - ${cfg.stateDir}/plugins"
+      "L+ /run/redmine/public/plugin_assets - - - - ${cfg.stateDir}/public/plugin_assets"
+      "L+ /run/redmine/public/themes - - - - ${cfg.stateDir}/public/themes"
+      "L+ /run/redmine/tmp - - - - ${cfg.stateDir}/tmp"
+    ];
+
     systemd.services.redmine = {
       after = [ "network.target" (if cfg.database.type == "mysql2" then "mysql.service" else "postgresql.service") ];
       wantedBy = [ "multi-user.target" ];
-      environment.HOME = "${cfg.package}/share/redmine";
       environment.RAILS_ENV = "production";
       environment.RAILS_CACHE = "${cfg.stateDir}/cache";
       environment.REDMINE_LANG = "en";
@@ -252,28 +275,16 @@ in
         subversion
       ];
       preStart = ''
-        # ensure cache directory exists for db:migrate command
-        mkdir -p "${cfg.stateDir}/cache"
-
-        # create the basic directory layout the redmine package expects
-        mkdir -p /run/redmine/public
-
-        for i in config files log plugins tmp; do
-          mkdir -p "${cfg.stateDir}/$i"
-          ln -fs "${cfg.stateDir}/$i" /run/redmine/
-        done
-
-        for i in plugin_assets themes; do
-          mkdir -p "${cfg.stateDir}/public/$i"
-          ln -fs "${cfg.stateDir}/public/$i" /run/redmine/public/
-        done
-
+        rm -rf "${cfg.stateDir}/plugins/"*
+        rm -rf "${cfg.stateDir}/public/themes/"*
 
         # start with a fresh config directory
         # the config directory is copied instead of linked as some mutable data is stored in there
-        rm -rf "${cfg.stateDir}/config/"*
+        find "${cfg.stateDir}/config" ! -name "secret_token.rb" -type f -exec rm -f {} +
         cp -r ${cfg.package}/share/redmine/config.dist/* "${cfg.stateDir}/config/"
 
+        chmod -R u+w "${cfg.stateDir}/config"
+
         # link in the application configuration
         ln -fs ${configurationYml} "${cfg.stateDir}/config/configuration.yml"
 
@@ -282,7 +293,6 @@ in
 
 
         # link in all user specified themes
-        rm -rf "${cfg.stateDir}/public/themes/"*
         for theme in ${concatStringsSep " " (mapAttrsToList unpackTheme cfg.themes)}; do
           ln -fs $theme/* "${cfg.stateDir}/public/themes"
         done
@@ -292,16 +302,11 @@ in
 
 
         # link in all user specified plugins
-        rm -rf "${cfg.stateDir}/plugins/"*
         for plugin in ${concatStringsSep " " (mapAttrsToList unpackPlugin cfg.plugins)}; do
           ln -fs $plugin/* "${cfg.stateDir}/plugins/''${plugin##*-redmine-plugin-}"
         done
 
 
-        # ensure correct permissions for most files
-        chmod -R ug+rwX,o-rwx+x "${cfg.stateDir}/"
-
-
         # handle database.passwordFile & permissions
         DBPASS=$(head -n1 ${cfg.database.passwordFile})
         cp -f ${databaseYml} "${cfg.stateDir}/config/database.yml"
@@ -315,25 +320,13 @@ in
           chmod 440 "${cfg.stateDir}/config/initializers/secret_token.rb"
         fi
 
-
-        # ensure everything is owned by ${cfg.user}
-        chown -R ${cfg.user}:${cfg.group} "${cfg.stateDir}"
-
-
         # execute redmine required commands prior to starting the application
-        # NOTE: su required in case using mysql socket authentication
-        /run/wrappers/bin/su -s ${pkgs.bash}/bin/bash -m -l redmine -c '${bundle} exec rake db:migrate'
-        /run/wrappers/bin/su -s ${pkgs.bash}/bin/bash -m -l redmine -c '${bundle} exec rake redmine:plugins:migrate'
-        /run/wrappers/bin/su -s ${pkgs.bash}/bin/bash -m -l redmine -c '${bundle} exec rake redmine:load_default_data'
-
-
-        # log files don't exist until after first command has been executed
-        # correct ownership of files generated by calling exec rake ...
-        chown -R ${cfg.user}:${cfg.group} "${cfg.stateDir}/log"
+        ${bundle} exec rake db:migrate
+        ${bundle} exec rake redmine:plugins:migrate
+        ${bundle} exec rake redmine:load_default_data
       '';
 
       serviceConfig = {
-        PermissionsStartOnly = true; # preStart must be run as root
         Type = "simple";
         User = cfg.user;
         Group = cfg.group;
@@ -348,7 +341,6 @@ in
       { name = "redmine";
         group = cfg.group;
         home = cfg.stateDir;
-        createHome = true;
         uid = config.ids.uids.redmine;
       });
 
diff --git a/nixos/modules/services/monitoring/datadog-agent.nix b/nixos/modules/services/monitoring/datadog-agent.nix
index 11673bf8bc7..b4ac0ca184d 100644
--- a/nixos/modules/services/monitoring/datadog-agent.nix
+++ b/nixos/modules/services/monitoring/datadog-agent.nix
@@ -260,7 +260,7 @@ in {
         path = [ ];
         script = ''
           export DD_API_KEY=$(head -n 1 ${cfg.apiKeyFile})
-          ${pkgs.datadog-trace-agent}/bin/trace-agent -config /etc/datadog-agent/datadog.yaml
+          ${datadogPkg}/bin/trace-agent -config /etc/datadog-agent/datadog.yaml
         '';
       });
 
diff --git a/nixos/modules/services/networking/mosquitto.nix b/nixos/modules/services/networking/mosquitto.nix
index 332dc541345..9974cbd89d1 100644
--- a/nixos/modules/services/networking/mosquitto.nix
+++ b/nixos/modules/services/networking/mosquitto.nix
@@ -17,7 +17,6 @@ let
   '';
 
   mosquittoConf = pkgs.writeText "mosquitto.conf" ''
-    pid_file /run/mosquitto/pid
     acl_file ${aclFile}
     persistence true
     allow_anonymous ${boolToString cfg.allowAnonymous}
@@ -196,15 +195,15 @@ in
       wantedBy = [ "multi-user.target" ];
       after = [ "network.target" ];
       serviceConfig = {
-        Type = "forking";
+        Type = "notify";
+        NotifyAccess = "main";
         User = "mosquitto";
         Group = "mosquitto";
         RuntimeDirectory = "mosquitto";
         WorkingDirectory = cfg.dataDir;
         Restart = "on-failure";
-        ExecStart = "${pkgs.mosquitto}/bin/mosquitto -c ${mosquittoConf} -d";
+        ExecStart = "${pkgs.mosquitto}/bin/mosquitto -c ${mosquittoConf}";
         ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
-        PIDFile = "/run/mosquitto/pid";
       };
       preStart = ''
         rm -f ${cfg.dataDir}/passwd
@@ -214,7 +213,7 @@ in
           if c.hashedPassword != null then
             "echo '${n}:${c.hashedPassword}' >> ${cfg.dataDir}/passwd"
           else optionalString (c.password != null)
-            "${pkgs.mosquitto}/bin/mosquitto_passwd -b ${cfg.dataDir}/passwd ${n} ${c.password}"
+            "${pkgs.mosquitto}/bin/mosquitto_passwd -b ${cfg.dataDir}/passwd ${n} '${c.password}'"
         ) cfg.users);
     };
 
diff --git a/nixos/modules/services/web-apps/nextcloud.nix b/nixos/modules/services/web-apps/nextcloud.nix
index 49d8836b8ad..498e3fdb23a 100644
--- a/nixos/modules/services/web-apps/nextcloud.nix
+++ b/nixos/modules/services/web-apps/nextcloud.nix
@@ -5,14 +5,18 @@ with lib;
 let
   cfg = config.services.nextcloud;
 
+  phpPackage = pkgs.php73;
+  phpPackages = pkgs.php73Packages;
+
   toKeyValue = generators.toKeyValue {
     mkKeyValue = generators.mkKeyValueDefault {} " = ";
   };
 
   phpOptionsExtensions = ''
-    ${optionalString cfg.caching.apcu "extension=${cfg.phpPackages.apcu}/lib/php/extensions/apcu.so"}
-    ${optionalString cfg.caching.redis "extension=${cfg.phpPackages.redis}/lib/php/extensions/redis.so"}
-    ${optionalString cfg.caching.memcached "extension=${cfg.phpPackages.memcached}/lib/php/extensions/memcached.so"}
+    ${optionalString cfg.caching.apcu "extension=${phpPackages.apcu}/lib/php/extensions/apcu.so"}
+    ${optionalString cfg.caching.redis "extension=${phpPackages.redis}/lib/php/extensions/redis.so"}
+    ${optionalString cfg.caching.memcached "extension=${phpPackages.memcached}/lib/php/extensions/memcached.so"}
+    extension=${phpPackages.imagick}/lib/php/extensions/imagick.so
     zend_extension = opcache.so
     opcache.enable = 1
   '';
@@ -94,18 +98,6 @@ in {
       '';
     };
 
-    phpPackages = mkOption {
-      type = types.attrs;
-      default = pkgs.php71Packages;
-      defaultText = "pkgs.php71Packages";
-      description = ''
-        Overridable attribute of the PHP packages set to use.  If any caching
-        module is enabled, it will be taken from here.  Therefore it should
-        match the version of PHP given to
-        <literal>services.phpfpm.phpPackage</literal>.
-      '';
-    };
-
     phpOptions = mkOption {
       type = types.attrsOf types.str;
       default = {
@@ -223,6 +215,19 @@ in {
           <literal>services.nextcloud.hostname</literal> here.
         '';
       };
+
+      overwriteProtocol = mkOption {
+        type = types.nullOr (types.enum [ "http" "https" ]);
+        default = null;
+        example = "https";
+
+        description = ''
+          Force Nextcloud to always use HTTPS i.e. for link generation. Nextcloud
+          uses the currently used protocol by default, but when behind a reverse-proxy,
+          it may use <literal>http</literal> for everything although Nextcloud
+          may be served via HTTPS.
+        '';
+      };
     };
 
     caching = {
@@ -287,6 +292,7 @@ in {
               ${optionalString cfg.caching.apcu "'memcache.local' => '\\OC\\Memcache\\APCu',"}
               'log_type' => 'syslog',
               'log_level' => '${builtins.toString cfg.logLevel}',
+              ${optionalString (cfg.config.overwriteProtocol != null) "'overwriteprotocol' => '${cfg.config.overwriteProtocol}',"}
             ];
           '';
           occInstallCmd = let
@@ -359,14 +365,14 @@ in {
       };
 
       services.phpfpm = {
-        phpOptions = phpOptionsExtensions;
-        phpPackage = pkgs.php71;
         pools.nextcloud = let
           phpAdminValues = (toKeyValue
             (foldr (a: b: a // b) {}
               (mapAttrsToList (k: v: { "php_admin_value[${k}]" = v; })
                 phpOptions)));
         in {
+          phpOptions = phpOptionsExtensions;
+          phpPackage = phpPackage;
           listen = "/run/phpfpm/nextcloud";
           extraConfig = ''
             listen.owner = nginx
@@ -407,7 +413,7 @@ in {
               };
               "/" = {
                 priority = 200;
-                extraConfig = "rewrite ^ /index.php$uri;";
+                extraConfig = "rewrite ^ /index.php$request_uri;";
               };
               "~ ^/store-apps" = {
                 priority = 201;
@@ -444,22 +450,23 @@ in {
                   fastcgi_read_timeout 120s;
                 '';
               };
-              "~ ^/(?:updater|ocs-provider)(?:$|/)".extraConfig = ''
+              "~ ^/(?:updater|ocs-provider|ocm-provider)(?:$|\/)".extraConfig = ''
                 try_files $uri/ =404;
                 index index.php;
               '';
-              "~ \\.(?:css|js|woff|svg|gif)$".extraConfig = ''
-                try_files $uri /index.php$uri$is_args$args;
+              "~ \\.(?:css|js|woff2?|svg|gif)$".extraConfig = ''
+                try_files $uri /index.php$request_uri;
                 add_header Cache-Control "public, max-age=15778463";
                 add_header X-Content-Type-Options nosniff;
                 add_header X-XSS-Protection "1; mode=block";
                 add_header X-Robots-Tag none;
                 add_header X-Download-Options noopen;
                 add_header X-Permitted-Cross-Domain-Policies none;
+                add_header Referrer-Policy no-referrer;
                 access_log off;
               '';
               "~ \\.(?:png|html|ttf|ico|jpg|jpeg)$".extraConfig = ''
-                try_files $uri /index.php$uri$is_args$args;
+                try_files $uri /index.php$request_uri;
                 access_log off;
               '';
             };
@@ -469,10 +476,12 @@ in {
               add_header X-Robots-Tag none;
               add_header X-Download-Options noopen;
               add_header X-Permitted-Cross-Domain-Policies none;
+              add_header Referrer-Policy no-referrer;
               error_page 403 /core/templates/403.php;
               error_page 404 /core/templates/404.php;
               client_max_body_size ${cfg.maxUploadSize};
               fastcgi_buffers 64 4K;
+              fastcgi_hide_header X-Powered-By;
               gzip on;
               gzip_vary on;
               gzip_comp_level 4;
diff --git a/nixos/modules/services/web-servers/nginx/default.nix b/nixos/modules/services/web-servers/nginx/default.nix
index f688bec1426..1c9fbe048f8 100644
--- a/nixos/modules/services/web-servers/nginx/default.nix
+++ b/nixos/modules/services/web-servers/nginx/default.nix
@@ -194,11 +194,12 @@ let
             then filter (x: x.ssl) defaultListen
             else defaultListen;
 
-        listenString = { addr, port, ssl, ... }:
+        listenString = { addr, port, ssl, extraParameters ? [], ... }:
           "listen ${addr}:${toString port} "
           + optionalString ssl "ssl "
           + optionalString (ssl && vhost.http2) "http2 "
           + optionalString vhost.default "default_server "
+          + optionalString (extraParameters != []) (concatStringsSep " " extraParameters)
           + ";";
 
         redirectListen = filter (x: !x.ssl) defaultListen;
@@ -491,8 +492,8 @@ in
 
       sslProtocols = mkOption {
         type = types.str;
-        default = "TLSv1.2";
-        example = "TLSv1 TLSv1.1 TLSv1.2";
+        default = "TLSv1.2 TLSv1.3";
+        example = "TLSv1 TLSv1.1 TLSv1.2 TLSv1.3";
         description = "Allowed TLS protocol versions.";
       };
 
diff --git a/nixos/modules/services/web-servers/nginx/vhost-options.nix b/nixos/modules/services/web-servers/nginx/vhost-options.nix
index 6a50d8ed5cd..15b933c984a 100644
--- a/nixos/modules/services/web-servers/nginx/vhost-options.nix
+++ b/nixos/modules/services/web-servers/nginx/vhost-options.nix
@@ -31,6 +31,7 @@ with lib;
         addr = mkOption { type = str;  description = "IP address.";  };
         port = mkOption { type = int;  description = "Port number."; default = 80; };
         ssl  = mkOption { type = bool; description = "Enable SSL.";  default = false; };
+        extraParameters = mkOption { type = listOf str; description = "Extra parameters of this listen directive."; default = []; example = [ "reuseport" "deferred" ]; };
       }; });
       default = [];
       example = [
diff --git a/nixos/modules/services/x11/desktop-managers/gnome3.nix b/nixos/modules/services/x11/desktop-managers/gnome3.nix
index 6255dce8276..ea01749349d 100644
--- a/nixos/modules/services/x11/desktop-managers/gnome3.nix
+++ b/nixos/modules/services/x11/desktop-managers/gnome3.nix
@@ -133,6 +133,7 @@ in {
     services.gnome3.gnome-keyring.enable = true;
     services.gnome3.gnome-online-accounts.enable = mkDefault true;
     services.gnome3.gnome-remote-desktop.enable = mkDefault true;
+    services.gnome3.gnome-settings-daemon.enable = true;
     services.gnome3.gnome-terminal-server.enable = mkDefault true;
     services.gnome3.gnome-user-share.enable = mkDefault true;
     services.gnome3.gvfs.enable = true;
@@ -153,7 +154,6 @@ in {
     hardware.bluetooth.enable = mkDefault true;
     services.hardware.bolt.enable = mkDefault true;
     services.xserver.libinput.enable = mkDefault true; # for controlling touchpad settings via gnome control center
-    services.udev.packages = [ pkgs.gnome3.gnome-settings-daemon ];
     systemd.packages = [ pkgs.gnome3.vino ];
     services.flatpak.extraPortals = [ pkgs.xdg-desktop-portal-gtk ];
 
diff --git a/nixos/modules/services/x11/desktop-managers/mate.nix b/nixos/modules/services/x11/desktop-managers/mate.nix
index d06f478cf4d..bf6685ff7ea 100644
--- a/nixos/modules/services/x11/desktop-managers/mate.nix
+++ b/nixos/modules/services/x11/desktop-managers/mate.nix
@@ -56,9 +56,6 @@ in
 
         export XDG_MENU_PREFIX=mate-
 
-        # Find the mouse
-        export XCURSOR_PATH=~/.icons:${config.system.path}/share/icons
-
         # Let caja find extensions
         export CAJA_EXTENSION_DIRS=$CAJA_EXTENSION_DIRS''${CAJA_EXTENSION_DIRS:+:}${config.system.path}/lib/caja/extensions-2.0
 
@@ -78,9 +75,6 @@ in
         # Add mate-control-center paths to some XDG variables because its schemas are needed by mate-settings-daemon, and mate-settings-daemon is a dependency for mate-control-center (that is, they are mutually recursive)
         ${addToXDGDirs pkgs.mate.mate-control-center}
 
-        # Update user dirs as described in http://freedesktop.org/wiki/Software/xdg-user-dirs/
-        ${pkgs.xdg-user-dirs}/bin/xdg-user-dirs-update
-
         ${pkgs.mate.mate-session-manager}/bin/mate-session ${optionalString cfg.debug "--debug"} &
         waitPID=$!
       '';
@@ -90,14 +84,20 @@ in
       pkgs.mate.basePackages ++
       (pkgs.gnome3.removePackagesByName
         pkgs.mate.extraPackages
-        config.environment.mate.excludePackages);
-
-    services.dbus.packages = [
-      pkgs.gnome3.dconf
-      pkgs.at-spi2-core
-    ];
-
+        config.environment.mate.excludePackages) ++
+      [
+        pkgs.desktop-file-utils
+        pkgs.glib
+        pkgs.gtk3.out
+        pkgs.shared-mime-info
+        pkgs.xdg-user-dirs # Update user dirs as described in https://freedesktop.org/wiki/Software/xdg-user-dirs/
+      ];
+
+    programs.dconf.enable = true;
+    services.gnome3.at-spi2-core.enable = true;
     services.gnome3.gnome-keyring.enable = true;
+    services.gnome3.gnome-settings-daemon.enable = true;
+    services.gnome3.gnome-settings-daemon.package = pkgs.mate.mate-settings-daemon;
     services.gnome3.gvfs.enable = true;
     services.upower.enable = config.powerManagement.enable;
 
diff --git a/nixos/modules/services/x11/desktop-managers/pantheon.nix b/nixos/modules/services/x11/desktop-managers/pantheon.nix
index 0f49439bf7c..31bbbd55829 100644
--- a/nixos/modules/services/x11/desktop-managers/pantheon.nix
+++ b/nixos/modules/services/x11/desktop-managers/pantheon.nix
@@ -117,11 +117,12 @@ in
     services.gnome3.file-roller.enable = true;
     # TODO: gnome-keyring's xdg autostarts will still be in the environment (from elementary-session-settings) if disabled forcefully
     services.gnome3.gnome-keyring.enable = true;
+    services.gnome3.gnome-settings-daemon.enable = true;
+    services.gnome3.gnome-settings-daemon.package = pkgs.pantheon.elementary-settings-daemon;
     services.gnome3.gvfs.enable = true;
     services.gnome3.rygel.enable = true;
     services.gsignond.enable = true;
     services.gsignond.plugins = with pkgs.gsignondPlugins; [ lastfm mail oauth ];
-    services.udev.packages = [ pkgs.pantheon.elementary-settings-daemon ];
     services.udisks2.enable = true;
     services.upower.enable = config.powerManagement.enable;
     services.xserver.libinput.enable = mkDefault true;
diff --git a/nixos/modules/services/x11/xserver.nix b/nixos/modules/services/x11/xserver.nix
index d84ab3ced6f..c4d5b6a9cde 100644
--- a/nixos/modules/services/x11/xserver.nix
+++ b/nixos/modules/services/x11/xserver.nix
@@ -61,7 +61,9 @@ let
       '';
       description = ''
         Extra lines to append to the <literal>Monitor</literal> section
-        verbatim.
+        verbatim. Available options are documented in the MONITOR section in
+        <citerefentry><refentrytitle>xorg.conf</refentrytitle>
+        <manvolnum>5</manvolnum></citerefentry>.
       '';
     };
   };
@@ -633,7 +635,7 @@ in
 
     environment.pathsToLink = [ "/share/X11" ];
 
-    xdg = { 
+    xdg = {
       autostart.enable = true;
       menus.enable = true;
       mime.enable = true;