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/config/krb5/default.nix2
-rw-r--r--nixos/modules/config/system-path.nix2
-rw-r--r--nixos/modules/config/xdg/mime.nix4
-rw-r--r--nixos/modules/misc/documentation.nix2
-rw-r--r--nixos/modules/module-list.nix2
-rw-r--r--nixos/modules/programs/fish.nix2
-rw-r--r--nixos/modules/services/continuous-integration/buildbot/master.nix67
-rw-r--r--nixos/modules/services/continuous-integration/buildbot/worker.nix77
-rw-r--r--nixos/modules/services/logging/journaldriver.nix2
-rw-r--r--nixos/modules/services/mail/rmilter.nix2
-rw-r--r--nixos/modules/services/mail/rspamd.nix2
-rw-r--r--nixos/modules/services/misc/nix-daemon.nix4
-rw-r--r--nixos/modules/services/misc/nix-optimise.nix2
-rw-r--r--nixos/modules/services/misc/redmine.nix168
-rw-r--r--nixos/modules/services/monitoring/prometheus/exporters.nix21
-rw-r--r--nixos/modules/services/monitoring/prometheus/exporters/varnish.nix1
-rw-r--r--nixos/modules/services/networking/pptpd.nix2
-rw-r--r--nixos/modules/services/networking/xl2tpd.nix2
-rw-r--r--nixos/modules/services/networking/xrdp.nix2
-rw-r--r--nixos/modules/services/printing/cupsd.nix2
-rw-r--r--nixos/modules/services/system/saslauthd.nix2
-rw-r--r--nixos/modules/services/web-apps/nextcloud.nix21
-rw-r--r--nixos/modules/services/x11/desktop-managers/gnome3.nix1
-rw-r--r--nixos/modules/services/x11/desktop-managers/plasma5.nix6
-rw-r--r--nixos/modules/services/x11/desktop-managers/xfce.nix3
-rw-r--r--nixos/modules/services/x11/display-managers/startx.nix44
-rw-r--r--nixos/modules/services/x11/gdk-pixbuf.nix45
-rw-r--r--nixos/modules/system/boot/luksroot.nix68
-rw-r--r--nixos/modules/system/boot/stage-1.nix4
-rw-r--r--nixos/modules/tasks/network-interfaces-scripted.nix3
-rw-r--r--nixos/modules/virtualisation/qemu-guest-agent.nix2
-rw-r--r--nixos/modules/virtualisation/virtualbox-image.nix2
-rw-r--r--nixos/modules/virtualisation/xe-guest-utilities.nix2
33 files changed, 436 insertions, 135 deletions
diff --git a/nixos/modules/config/krb5/default.nix b/nixos/modules/config/krb5/default.nix
index c22e99a0a2f1..87021a27d34f 100644
--- a/nixos/modules/config/krb5/default.nix
+++ b/nixos/modules/config/krb5/default.nix
@@ -79,7 +79,7 @@ in {
 
   options = {
     krb5 = {
-      enable = mkEnableOption "Whether to enable Kerberos V.";
+      enable = mkEnableOption "building krb5.conf, configuration file for Kerberos V";
 
       kerberos = mkOption {
         type = types.package;
diff --git a/nixos/modules/config/system-path.nix b/nixos/modules/config/system-path.nix
index 3c24dab85e4d..c07e19bd03c4 100644
--- a/nixos/modules/config/system-path.nix
+++ b/nixos/modules/config/system-path.nix
@@ -140,7 +140,7 @@ in
           if [ -x $out/bin/glib-compile-schemas -a -w $out/share/glib-2.0/schemas ]; then
               $out/bin/glib-compile-schemas $out/share/glib-2.0/schemas
           fi
-          
+
           ${config.environment.extraSetup}
         '';
     };
diff --git a/nixos/modules/config/xdg/mime.nix b/nixos/modules/config/xdg/mime.nix
index 4323a49ea1dd..cd1064630fbc 100644
--- a/nixos/modules/config/xdg/mime.nix
+++ b/nixos/modules/config/xdg/mime.nix
@@ -24,11 +24,11 @@ with lib;
 
     environment.extraSetup = ''
       if [ -w $out/share/mime ] && [ -d $out/share/mime/packages ]; then
-          XDG_DATA_DIRS=$out/share ${pkgs.shared-mime-info}/bin/update-mime-database -V $out/share/mime > /dev/null
+          XDG_DATA_DIRS=$out/share ${pkgs.buildPackages.shared-mime-info}/bin/update-mime-database -V $out/share/mime > /dev/null
       fi
 
       if [ -w $out/share/applications ]; then
-          ${pkgs.desktop-file-utils}/bin/update-desktop-database $out/share/applications
+          ${pkgs.buildPackages.desktop-file-utils}/bin/update-desktop-database $out/share/applications
       fi
     '';
   };
diff --git a/nixos/modules/misc/documentation.nix b/nixos/modules/misc/documentation.nix
index 6a7105e9cdaa..09d53c322fb3 100644
--- a/nixos/modules/misc/documentation.nix
+++ b/nixos/modules/misc/documentation.nix
@@ -166,7 +166,7 @@ in
         if [ -w $out/share/info ]; then
           shopt -s nullglob
           for i in $out/share/info/*.info $out/share/info/*.info.gz; do
-              ${pkgs.texinfo}/bin/install-info $i $out/share/info/dir
+              ${pkgs.buildPackages.texinfo}/bin/install-info $i $out/share/info/dir
           done
         fi
       '';
diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix
index b6849a4df574..f55c32fa511d 100644
--- a/nixos/modules/module-list.nix
+++ b/nixos/modules/module-list.nix
@@ -735,12 +735,14 @@
   ./services/x11/display-managers/lightdm.nix
   ./services/x11/display-managers/sddm.nix
   ./services/x11/display-managers/slim.nix
+  ./services/x11/display-managers/startx.nix
   ./services/x11/display-managers/xpra.nix
   ./services/x11/fractalart.nix
   ./services/x11/hardware/libinput.nix
   ./services/x11/hardware/multitouch.nix
   ./services/x11/hardware/synaptics.nix
   ./services/x11/hardware/wacom.nix
+  ./services/x11/gdk-pixbuf.nix
   ./services/x11/redshift.nix
   ./services/x11/urxvtd.nix
   ./services/x11/window-managers/awesome.nix
diff --git a/nixos/modules/programs/fish.nix b/nixos/modules/programs/fish.nix
index c3f742acde2e..5948fe11f92b 100644
--- a/nixos/modules/programs/fish.nix
+++ b/nixos/modules/programs/fish.nix
@@ -9,7 +9,7 @@ let
   cfg = config.programs.fish;
 
   fishAliases = concatStringsSep "\n" (
-    mapAttrsFlatten (k: v: "alias ${k} '${v}'") cfg.shellAliases
+    mapAttrsFlatten (k: v: "alias ${k} ${escapeShellArg v}") cfg.shellAliases
   );
 
 in
diff --git a/nixos/modules/services/continuous-integration/buildbot/master.nix b/nixos/modules/services/continuous-integration/buildbot/master.nix
index 8d767de37f00..0f07e6133bb5 100644
--- a/nixos/modules/services/continuous-integration/buildbot/master.nix
+++ b/nixos/modules/services/continuous-integration/buildbot/master.nix
@@ -6,8 +6,12 @@ with lib;
 
 let
   cfg = config.services.buildbot-master;
+
+  python = cfg.package.pythonModule;
+
   escapeStr = s: escape ["'"] s;
-  masterCfg = if cfg.masterCfg == null then pkgs.writeText "master.cfg" ''
+
+  defaultMasterCfg = pkgs.writeText "master.cfg" ''
     from buildbot.plugins import *
     factory = util.BuildFactory()
     c = BuildmasterConfig = dict(
@@ -27,8 +31,28 @@ let
       factory.addStep(step)
 
     ${cfg.extraConfig}
-  ''
-  else cfg.masterCfg;
+  '';
+
+  tacFile = pkgs.writeText "buildbot-master.tac" ''
+    import os
+
+    from twisted.application import service
+    from buildbot.master import BuildMaster
+
+    basedir = '${cfg.buildbotDir}'
+
+    configfile = '${cfg.masterCfg}'
+
+    # Default umask for server
+    umask = None
+
+    # note: this line is matched against to check that this is a buildmaster
+    # directory; do not edit it.
+    application = service.Application('buildmaster')
+
+    m = BuildMaster(basedir, configfile, umask)
+    m.setServiceParent(application)
+  '';
 
 in {
   options = {
@@ -66,9 +90,9 @@ in {
       };
 
       masterCfg = mkOption {
-        type = types.nullOr types.path;
+        type = types.path;
         description = "Optionally pass master.cfg path. Other options in this configuration will be ignored.";
-        default = null;
+        default = defaultMasterCfg;
         example = "/etc/nixos/buildbot/master.cfg";
       };
 
@@ -175,18 +199,25 @@ in {
 
       package = mkOption {
         type = types.package;
-        default = pkgs.buildbot-full;
-        defaultText = "pkgs.buildbot-full";
+        default = pkgs.pythonPackages.buildbot-full;
+        defaultText = "pkgs.pythonPackages.buildbot-full";
         description = "Package to use for buildbot.";
-        example = literalExample "pkgs.buildbot-full";
+        example = literalExample "pkgs.python3Packages.buildbot-full";
       };
 
       packages = mkOption {
-        default = with pkgs; [ python27Packages.twisted git ];
+        default = [ pkgs.git ];
         example = literalExample "[ pkgs.git ]";
         type = types.listOf types.package;
         description = "Packages to add to PATH for the buildbot process.";
       };
+
+      pythonPackages = mkOption {
+        default = pythonPackages: with pythonPackages; [ ];
+        defaultText = "pythonPackages: with pythonPackages; [ ]";
+        description = "Packages to add the to the PYTHONPATH of the buildbot process.";
+        example = literalExample "pythonPackages: with pythonPackages; [ requests ]";
+      };
     };
   };
 
@@ -210,14 +241,15 @@ in {
       description = "Buildbot Continuous Integration Server.";
       after = [ "network-online.target" ];
       wantedBy = [ "multi-user.target" ];
-      path = cfg.packages;
+      path = cfg.packages ++ cfg.pythonPackages python.pkgs;
+      environment.PYTHONPATH = "${python.withPackages (self: cfg.pythonPackages self ++ [ cfg.package ])}/${python.sitePackages}";
 
       preStart = ''
-        env > envvars
-        mkdir -vp ${cfg.buildbotDir}
-        ln -sfv ${masterCfg} ${cfg.buildbotDir}/master.cfg
-        rm -fv $cfg.buildbotDir}/buildbot.tac
-        ${cfg.package}/bin/buildbot create-master ${cfg.buildbotDir}
+        mkdir -vp "${cfg.buildbotDir}"
+        # Link the tac file so buildbot command line tools recognize the directory
+        ln -sf "${tacFile}" "${cfg.buildbotDir}/buildbot.tac"
+        ${cfg.package}/bin/buildbot create-master --db "${cfg.dbUrl}" "${cfg.buildbotDir}"
+        rm -f buildbot.tac.new master.cfg.sample
       '';
 
       serviceConfig = {
@@ -225,12 +257,11 @@ in {
         User = cfg.user;
         Group = cfg.group;
         WorkingDirectory = cfg.home;
-        ExecStart = "${cfg.package}/bin/buildbot start --nodaemon ${cfg.buildbotDir}";
+        # NOTE: call twistd directly with stdout logging for systemd
+        ExecStart = "${python.pkgs.twisted}/bin/twistd -o --nodaemon --pidfile= --logfile - --python ${tacFile}";
       };
-
     };
   };
 
   meta.maintainers = with lib.maintainers; [ nand0p mic92 ];
-
 }
diff --git a/nixos/modules/services/continuous-integration/buildbot/worker.nix b/nixos/modules/services/continuous-integration/buildbot/worker.nix
index 67c541570b97..4130ec918a70 100644
--- a/nixos/modules/services/continuous-integration/buildbot/worker.nix
+++ b/nixos/modules/services/continuous-integration/buildbot/worker.nix
@@ -7,6 +7,40 @@ with lib;
 let
   cfg = config.services.buildbot-worker;
 
+  python = cfg.package.pythonModule;
+
+  tacFile = pkgs.writeText "aur-buildbot-worker.tac" ''
+    import os
+    from io import open
+
+    from buildbot_worker.bot import Worker
+    from twisted.application import service
+
+    basedir = '${cfg.buildbotDir}'
+
+    # note: this line is matched against to check that this is a worker
+    # directory; do not edit it.
+    application = service.Application('buildbot-worker')
+
+    master_url_split = '${cfg.masterUrl}'.split(':')
+    buildmaster_host = master_url_split[0]
+    port = int(master_url_split[1])
+    workername = '${cfg.workerUser}'
+
+    with open('${cfg.workerPassFile}', 'r', encoding='utf-8') as passwd_file:
+        passwd = passwd_file.read().strip('\r\n')
+    keepalive = 600
+    umask = None
+    maxdelay = 300
+    numcpus = None
+    allow_shutdown = None
+
+    s = Worker(buildmaster_host, port, workername, passwd, basedir,
+               keepalive, umask=umask, maxdelay=maxdelay,
+               numcpus=numcpus, allow_shutdown=allow_shutdown)
+    s.setServiceParent(application)
+  '';
+
 in {
   options = {
     services.buildbot-worker = {
@@ -59,6 +93,23 @@ in {
         description = "Specifies the Buildbot Worker password.";
       };
 
+      workerPassFile = mkOption {
+        type = types.path;
+        description = "File used to store the Buildbot Worker password";
+      };
+
+      hostMessage = mkOption {
+        default = null;
+        type = types.nullOr types.str;
+        description = "Description of this worker";
+      };
+
+      adminMessage = mkOption {
+        default = null;
+        type = types.nullOr types.str;
+        description = "Name of the administrator of this worker";
+      };
+
       masterUrl = mkOption {
         default = "localhost:9989";
         type = types.str;
@@ -67,23 +118,24 @@ in {
 
       package = mkOption {
         type = types.package;
-        default = pkgs.buildbot-worker;
-        defaultText = "pkgs.buildbot-worker";
+        default = pkgs.pythonPackages.buildbot-worker;
+        defaultText = "pkgs.pythonPackages.buildbot-worker";
         description = "Package to use for buildbot worker.";
-        example = literalExample "pkgs.buildbot-worker";
+        example = literalExample "pkgs.python3Packages.buildbot-worker";
       };
 
       packages = mkOption {
-        default = with pkgs; [ python27Packages.twisted git ];
+        default = with pkgs; [ git ];
         example = literalExample "[ pkgs.git ]";
         type = types.listOf types.package;
         description = "Packages to add to PATH for the buildbot process.";
       };
-
     };
   };
 
   config = mkIf cfg.enable {
+    services.buildbot-worker.workerPassFile = mkDefault (pkgs.writeText "buildbot-worker-password" cfg.workerPass);
+
     users.groups = optional (cfg.group == "bbworker") {
       name = "bbworker";
     };
@@ -104,11 +156,16 @@ in {
       after = [ "network.target" "buildbot-master.service" ];
       wantedBy = [ "multi-user.target" ];
       path = cfg.packages;
+      environment.PYTHONPATH = "${python.withPackages (p: [ cfg.package ])}/${python.sitePackages}";
 
       preStart = ''
-        mkdir -vp ${cfg.buildbotDir}
-        rm -fv $cfg.buildbotDir}/buildbot.tac
-        ${cfg.package}/bin/buildbot-worker create-worker ${cfg.buildbotDir} ${cfg.masterUrl} ${cfg.workerUser} ${cfg.workerPass}
+        mkdir -vp "${cfg.buildbotDir}/info"
+        ${optionalString (cfg.hostMessage != null) ''
+          ln -sf "${pkgs.writeText "buildbot-worker-host" cfg.hostMessage}" "${cfg.buildbotDir}/info/host"
+        ''}
+        ${optionalString (cfg.adminMessage != null) ''
+          ln -sf "${pkgs.writeText "buildbot-worker-admin" cfg.adminMessage}" "${cfg.buildbotDir}/info/admin"
+        ''}
       '';
 
       serviceConfig = {
@@ -116,11 +173,9 @@ in {
         User = cfg.user;
         Group = cfg.group;
         WorkingDirectory = cfg.home;
-        Environment = "PYTHONPATH=${cfg.package}/lib/python2.7/site-packages:${pkgs.python27Packages.future}/lib/python2.7/site-packages";
 
         # NOTE: call twistd directly with stdout logging for systemd
-        #ExecStart = "${cfg.package}/bin/buildbot-worker start --nodaemon ${cfg.buildbotDir}";
-        ExecStart = "${pkgs.python27Packages.twisted}/bin/twistd -n -l - -y ${cfg.buildbotDir}/buildbot.tac";
+        ExecStart = "${python.pkgs.twisted}/bin/twistd --nodaemon --pidfile= --logfile - --python ${tacFile}";
       };
 
     };
diff --git a/nixos/modules/services/logging/journaldriver.nix b/nixos/modules/services/logging/journaldriver.nix
index 74ac3d4c2365..9bd581e9ec0e 100644
--- a/nixos/modules/services/logging/journaldriver.nix
+++ b/nixos/modules/services/logging/journaldriver.nix
@@ -7,7 +7,7 @@
 # to be set.
 #
 # For further information please consult the documentation in the
-# upstream repository at: https://github.com/aprilabank/journaldriver/
+# upstream repository at: https://github.com/tazjin/journaldriver/
 
 { config, lib, pkgs, ...}:
 
diff --git a/nixos/modules/services/mail/rmilter.nix b/nixos/modules/services/mail/rmilter.nix
index 0d91b247cd34..492c64583219 100644
--- a/nixos/modules/services/mail/rmilter.nix
+++ b/nixos/modules/services/mail/rmilter.nix
@@ -52,7 +52,7 @@ in
 
       enable = mkOption {
         type = types.bool;
-        default = cfg.rspamd.enable;
+        default = false;
         description = "Whether to run the rmilter daemon.";
       };
 
diff --git a/nixos/modules/services/mail/rspamd.nix b/nixos/modules/services/mail/rspamd.nix
index bba11796a3d3..ff01a5dee53d 100644
--- a/nixos/modules/services/mail/rspamd.nix
+++ b/nixos/modules/services/mail/rspamd.nix
@@ -159,7 +159,7 @@ in
 
     services.rspamd = {
 
-      enable = mkEnableOption "Whether to run the rspamd daemon.";
+      enable = mkEnableOption "rspamd, the Rapid spam filtering system";
 
       debug = mkOption {
         type = types.bool;
diff --git a/nixos/modules/services/misc/nix-daemon.nix b/nixos/modules/services/misc/nix-daemon.nix
index 24379ec27354..5e171c08d893 100644
--- a/nixos/modules/services/misc/nix-daemon.nix
+++ b/nixos/modules/services/misc/nix-daemon.nix
@@ -399,8 +399,8 @@ in
     systemd.sockets.nix-daemon.wantedBy = [ "sockets.target" ];
 
     systemd.services.nix-daemon =
-      { path = [ nix pkgs.utillinux ]
-          ++ optionals cfg.distributedBuilds [ config.programs.ssh.package pkgs.gzip ]
+      { path = [ nix pkgs.utillinux config.programs.ssh.package ]
+          ++ optionals cfg.distributedBuilds [ pkgs.gzip ]
           ++ optionals (!isNix20) [ pkgs.openssl.bin ];
 
         environment = cfg.envVars
diff --git a/nixos/modules/services/misc/nix-optimise.nix b/nixos/modules/services/misc/nix-optimise.nix
index 6f75e4dd03ea..416529f690e0 100644
--- a/nixos/modules/services/misc/nix-optimise.nix
+++ b/nixos/modules/services/misc/nix-optimise.nix
@@ -40,6 +40,8 @@ in
 
     systemd.services.nix-optimise =
       { description = "Nix Store Optimiser";
+        # No point running it inside a nixos-container. It should be on the host instead.
+        unitConfig.ConditionVirtualization = "!container";
         serviceConfig.ExecStart = "${config.nix.package}/bin/nix-store --optimise";
         startAt = optionals cfg.automatic cfg.dates;
       };
diff --git a/nixos/modules/services/misc/redmine.nix b/nixos/modules/services/misc/redmine.nix
index f763ba21d0b2..8d25ac5cb76f 100644
--- a/nixos/modules/services/misc/redmine.nix
+++ b/nixos/modules/services/misc/redmine.nix
@@ -5,7 +5,7 @@ with lib;
 let
   cfg = config.services.redmine;
 
-  bundle = "${pkgs.redmine}/share/redmine/bin/bundle";
+  bundle = "${cfg.package}/share/redmine/bin/bundle";
 
   databaseYml = pkgs.writeText "database.yml" ''
     production:
@@ -15,6 +15,7 @@ let
       port: ${toString cfg.database.port}
       username: ${cfg.database.user}
       password: #dbpass#
+      ${optionalString (cfg.database.socket != null) "socket: ${cfg.database.socket}"}
   '';
 
   configurationYml = pkgs.writeText "configuration.yml" ''
@@ -29,6 +30,19 @@ let
     ${cfg.extraConfig}
   '';
 
+  unpackTheme = unpack "theme";
+  unpackPlugin = unpack "plugin";
+  unpack = id: (name: source:
+    pkgs.stdenv.mkDerivation {
+      name = "redmine-${id}-${name}";
+      buildInputs = [ pkgs.unzip ];
+      buildCommand = ''
+        mkdir -p $out
+        cd $out
+        unpackFile ${source}
+      '';
+  });
+
 in
 
 {
@@ -40,6 +54,14 @@ in
         description = "Enable the Redmine service.";
       };
 
+      package = mkOption {
+        type = types.package;
+        default = pkgs.redmine;
+        defaultText = "pkgs.redmine";
+        description = "Which Redmine package to use.";
+        example = "pkgs.redmine.override { ruby = pkgs.ruby_2_3; }";
+      };
+
       user = mkOption {
         type = types.str;
         default = "redmine";
@@ -52,6 +74,12 @@ in
         description = "Group under which Redmine is ran.";
       };
 
+      port = mkOption {
+        type = types.int;
+        default = 3000;
+        description = "Port on which Redmine is ran.";
+      };
+
       stateDir = mkOption {
         type = types.str;
         default = "/var/lib/redmine";
@@ -66,6 +94,41 @@ in
 
           See https://guides.rubyonrails.org/action_mailer_basics.html#action-mailer-configuration
         '';
+        example = literalExample ''
+          email_delivery:
+            delivery_method: smtp
+            smtp_settings:
+              address: mail.example.com
+              port: 25
+        '';
+      };
+
+      themes = mkOption {
+        type = types.attrsOf types.path;
+        default = {};
+        description = "Set of themes.";
+        example = literalExample ''
+          {
+            dkuk-redmine_alex_skin = builtins.fetchurl {
+              url = https://bitbucket.org/dkuk/redmine_alex_skin/get/1842ef675ef3.zip;
+              sha256 = "0hrin9lzyi50k4w2bd2b30vrf1i4fi1c0gyas5801wn8i7kpm9yl";
+            };
+          }
+        '';
+      };
+
+      plugins = mkOption {
+        type = types.attrsOf types.path;
+        default = {};
+        description = "Set of plugins.";
+        example = literalExample ''
+          {
+            redmine_env_auth = builtins.fetchurl {
+              url = https://github.com/Intera/redmine_env_auth/archive/0.6.zip;
+              sha256 = "0yyr1yjd8gvvh832wdc8m3xfnhhxzk2pk3gm2psg5w9jdvd6skak";
+            };
+          }
+        '';
       };
 
       database = {
@@ -78,7 +141,7 @@ in
 
         host = mkOption {
           type = types.str;
-          default = "127.0.0.1";
+          default = (if cfg.database.socket != null then "localhost" else "127.0.0.1");
           description = "Database host address.";
         };
 
@@ -119,6 +182,13 @@ in
             <option>database.user</option>.
           '';
         };
+
+        socket = mkOption {
+          type = types.nullOr types.path;
+          default = null;
+          example = "/run/mysqld/mysqld.sock";
+          description = "Path to the unix socket file to use for authentication.";
+        };
       };
     };
   };
@@ -126,17 +196,20 @@ in
   config = mkIf cfg.enable {
 
     assertions = [
-      { assertion = cfg.database.passwordFile != null || cfg.database.password != "";
-        message = "either services.redmine.database.passwordFile or services.redmine.database.password must be set";
+      { assertion = cfg.database.passwordFile != null || cfg.database.password != "" || cfg.database.socket != null;
+        message = "one of services.redmine.database.socket, services.redmine.database.passwordFile, or services.redmine.database.password must be set";
+      }
+      { assertion = cfg.database.socket != null -> (cfg.database.type == "mysql2");
+        message = "Socket authentication is only available for the mysql2 database type";
       }
     ];
 
-    environment.systemPackages = [ pkgs.redmine ];
+    environment.systemPackages = [ cfg.package ];
 
     systemd.services.redmine = {
       after = [ "network.target" (if cfg.database.type == "mysql2" then "mysql.service" else "postgresql.service") ];
       wantedBy = [ "multi-user.target" ];
-      environment.HOME = "${pkgs.redmine}/share/redmine";
+      environment.HOME = "${cfg.package}/share/redmine";
       environment.RAILS_ENV = "production";
       environment.RAILS_CACHE = "${cfg.stateDir}/cache";
       environment.REDMINE_LANG = "en";
@@ -151,43 +224,80 @@ in
         subversion
       ];
       preStart = ''
-        # start with a fresh config directory every time
-        rm -rf ${cfg.stateDir}/config
-        cp -r ${pkgs.redmine}/share/redmine/config.dist ${cfg.stateDir}/config
+        # ensure cache directory exists for db:migrate command
+        mkdir -p "${cfg.stateDir}/cache"
 
-        # create the basic state directory layout pkgs.redmine expects
-        mkdir -p /run/redmine
+        # 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/$i
+          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
 
-        # ensure cache directory exists for db:migrate command
-        mkdir -p ${cfg.stateDir}/cache
+
+        # 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/"*
+        cp -r ${cfg.package}/share/redmine/config.dist/* "${cfg.stateDir}/config/"
 
         # link in the application configuration
-        ln -fs ${configurationYml} ${cfg.stateDir}/config/configuration.yml
+        ln -fs ${configurationYml} "${cfg.stateDir}/config/configuration.yml"
+
+
+        # 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
+
+        # link in redmine provided themes
+        ln -sf ${cfg.package}/share/redmine/public/themes.dist/* "${cfg.stateDir}/public/themes/"
+
 
-        chmod -R ug+rwX,o-rwx+x ${cfg.stateDir}/
+        # 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
+
+        # handle database.passwordFile & permissions
         DBPASS=$(head -n1 ${cfg.database.passwordFile})
-        cp -f ${databaseYml} ${cfg.stateDir}/config/database.yml
-        sed -e "s,#dbpass#,$DBPASS,g" -i ${cfg.stateDir}/config/database.yml
-        chmod 440 ${cfg.stateDir}/config/database.yml
+        cp -f ${databaseYml} "${cfg.stateDir}/config/database.yml"
+        sed -e "s,#dbpass#,$DBPASS,g" -i "${cfg.stateDir}/config/database.yml"
+        chmod 440 "${cfg.stateDir}/config/database.yml"
+
 
         # generate a secret token if required
         if ! test -e "${cfg.stateDir}/config/initializers/secret_token.rb"; then
           ${bundle} exec rake generate_secret_token
-          chmod 440 ${cfg.stateDir}/config/initializers/secret_token.rb
+          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}
+        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:load_default_data'
+
 
-        ${bundle} exec rake db:migrate
-        ${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"
       '';
 
       serviceConfig = {
@@ -196,13 +306,13 @@ in
         User = cfg.user;
         Group = cfg.group;
         TimeoutSec = "300";
-        WorkingDirectory = "${pkgs.redmine}/share/redmine";
-        ExecStart="${bundle} exec rails server webrick -e production -P ${cfg.stateDir}/redmine.pid";
+        WorkingDirectory = "${cfg.package}/share/redmine";
+        ExecStart="${bundle} exec rails server webrick -e production -p ${toString cfg.port} -P '${cfg.stateDir}/redmine.pid'";
       };
 
     };
 
-    users.extraUsers = optionalAttrs (cfg.user == "redmine") (singleton
+    users.users = optionalAttrs (cfg.user == "redmine") (singleton
       { name = "redmine";
         group = cfg.group;
         home = cfg.stateDir;
@@ -210,7 +320,7 @@ in
         uid = config.ids.uids.redmine;
       });
 
-    users.extraGroups = optionalAttrs (cfg.group == "redmine") (singleton
+    users.groups = optionalAttrs (cfg.group == "redmine") (singleton
       { name = "redmine";
         gid = config.ids.gids.redmine;
       });
diff --git a/nixos/modules/services/monitoring/prometheus/exporters.nix b/nixos/modules/services/monitoring/prometheus/exporters.nix
index 1d5f400250fd..ae8caac436da 100644
--- a/nixos/modules/services/monitoring/prometheus/exporters.nix
+++ b/nixos/modules/services/monitoring/prometheus/exporters.nix
@@ -123,15 +123,13 @@ let
       systemd.services."prometheus-${name}-exporter" = mkMerge ([{
         wantedBy = [ "multi-user.target" ];
         after = [ "network.target" ];
-        serviceConfig = {
-          Restart = mkDefault "always";
-          PrivateTmp = mkDefault true;
-          WorkingDirectory = mkDefault /tmp;
-        } // mkIf (!(serviceOpts.serviceConfig.DynamicUser or false)) {
-          User = conf.user;
-          Group = conf.group;
-        };
-      } serviceOpts ]);
+        serviceConfig.Restart = mkDefault "always";
+        serviceConfig.PrivateTmp = mkDefault true;
+        serviceConfig.WorkingDirectory = mkDefault /tmp;
+      } serviceOpts ] ++ optional (serviceOpts.serviceConfig.DynamicUser or false) {
+        serviceConfig.User = conf.user;
+        serviceConfig.Group = conf.group;
+      });
   };
 in
 {
@@ -172,5 +170,8 @@ in
     }) exporterOpts)
   );
 
-  meta.doc = ./exporters.xml;
+  meta = {
+    doc = ./exporters.xml;
+    maintainers = [ maintainers.willibutz ];
+  };
 }
diff --git a/nixos/modules/services/monitoring/prometheus/exporters/varnish.nix b/nixos/modules/services/monitoring/prometheus/exporters/varnish.nix
index 8dbf2d735ab9..aaed76175b84 100644
--- a/nixos/modules/services/monitoring/prometheus/exporters/varnish.nix
+++ b/nixos/modules/services/monitoring/prometheus/exporters/varnish.nix
@@ -69,6 +69,7 @@ in
     path = [ pkgs.varnish ];
     serviceConfig = {
       DynamicUser = true;
+      RestartSec = mkDefault 1;
       ExecStart = ''
         ${pkgs.prometheus-varnish-exporter}/bin/prometheus_varnish_exporter \
           --web.listen-address ${cfg.listenAddress}:${toString cfg.port} \
diff --git a/nixos/modules/services/networking/pptpd.nix b/nixos/modules/services/networking/pptpd.nix
index 56a612b91052..d8b9e8f8341a 100644
--- a/nixos/modules/services/networking/pptpd.nix
+++ b/nixos/modules/services/networking/pptpd.nix
@@ -5,7 +5,7 @@ with lib;
 {
   options = {
     services.pptpd = {
-      enable = mkEnableOption "Whether pptpd should be run on startup.";
+      enable = mkEnableOption "pptpd, the Point-to-Point Tunneling Protocol daemon";
 
       serverIp = mkOption {
         type        = types.string;
diff --git a/nixos/modules/services/networking/xl2tpd.nix b/nixos/modules/services/networking/xl2tpd.nix
index 46111a76af80..d0a3ed7bb5e0 100644
--- a/nixos/modules/services/networking/xl2tpd.nix
+++ b/nixos/modules/services/networking/xl2tpd.nix
@@ -5,7 +5,7 @@ with lib;
 {
   options = {
     services.xl2tpd = {
-      enable = mkEnableOption "Whether xl2tpd should be run on startup.";
+      enable = mkEnableOption "xl2tpd, the Layer 2 Tunnelling Protocol Daemon";
 
       serverIp = mkOption {
         type        = types.string;
diff --git a/nixos/modules/services/networking/xrdp.nix b/nixos/modules/services/networking/xrdp.nix
index 61f22a366a02..9ed3025e47d4 100644
--- a/nixos/modules/services/networking/xrdp.nix
+++ b/nixos/modules/services/networking/xrdp.nix
@@ -36,7 +36,7 @@ in
 
     services.xrdp = {
 
-      enable = mkEnableOption "Whether xrdp should be run on startup.";
+      enable = mkEnableOption "xrdp, the Remote Desktop Protocol server";
 
       package = mkOption {
         type = types.package;
diff --git a/nixos/modules/services/printing/cupsd.nix b/nixos/modules/services/printing/cupsd.nix
index dbf18ec1d114..1031d6f3d7e2 100644
--- a/nixos/modules/services/printing/cupsd.nix
+++ b/nixos/modules/services/printing/cupsd.nix
@@ -250,7 +250,7 @@ in
       drivers = mkOption {
         type = types.listOf types.path;
         default = [];
-        example = literalExample "[ pkgs.gutenprint pkgs.hplip pkgs.splix ]";
+        example = literalExample "with pkgs; [ gutenprint hplip splix cups-googlecloudprint ]";
         description = ''
           CUPS drivers to use. Drivers provided by CUPS, cups-filters,
           Ghostscript and Samba are added unconditionally. If this list contains
diff --git a/nixos/modules/services/system/saslauthd.nix b/nixos/modules/services/system/saslauthd.nix
index c8ddca9a0db6..8fcf4fb91fc4 100644
--- a/nixos/modules/services/system/saslauthd.nix
+++ b/nixos/modules/services/system/saslauthd.nix
@@ -16,7 +16,7 @@ in
 
     services.saslauthd = {
 
-      enable = mkEnableOption "Whether to enable the Cyrus SASL authentication daemon.";
+      enable = mkEnableOption "saslauthd, the Cyrus SASL authentication daemon";
 
       package = mkOption {
         default = pkgs.cyrus_sasl.bin;
diff --git a/nixos/modules/services/web-apps/nextcloud.nix b/nixos/modules/services/web-apps/nextcloud.nix
index 44c3df1d057b..db4c8e1a3d85 100644
--- a/nixos/modules/services/web-apps/nextcloud.nix
+++ b/nixos/modules/services/web-apps/nextcloud.nix
@@ -114,6 +114,21 @@ in {
       '';
     };
 
+    poolConfig = mkOption {
+      type = types.lines;
+      default = ''
+        pm = dynamic
+        pm.max_children = 32
+        pm.start_servers = 2
+        pm.min_spare_servers = 2
+        pm.max_spare_servers = 4
+        pm.max_requests = 500
+      '';
+      description = ''
+        Options for nextcloud's PHP pool. See the documentation on <literal>php-fpm.conf</literal> for details on configuration directives.
+      '';
+    };
+
     config = {
       dbtype = mkOption {
         type = types.enum [ "sqlite" "pgsql" "mysql" ];
@@ -339,11 +354,7 @@ in {
             listen.group = nginx
             user = nextcloud
             group = nginx
-            pm = dynamic
-            pm.max_children = 32
-            pm.start_servers = 2
-            pm.min_spare_servers = 2
-            pm.max_spare_servers = 4
+            ${cfg.poolConfig}
             env[NEXTCLOUD_CONFIG_DIR] = ${cfg.home}/config
             env[PATH] = /run/wrappers/bin:/nix/var/nix/profiles/default/bin:/run/current-system/sw/bin:/usr/bin:/bin
             ${phpAdminValues}
diff --git a/nixos/modules/services/x11/desktop-managers/gnome3.nix b/nixos/modules/services/x11/desktop-managers/gnome3.nix
index eb86f7b53bb6..0d5b860d4617 100644
--- a/nixos/modules/services/x11/desktop-managers/gnome3.nix
+++ b/nixos/modules/services/x11/desktop-managers/gnome3.nix
@@ -133,7 +133,6 @@ in {
 
     fonts.fonts = [ pkgs.dejavu_fonts pkgs.cantarell-fonts ];
 
-    services.xserver.displayManager.gdm.enable = mkDefault true;
     services.xserver.displayManager.extraSessionFilePackages = [ pkgs.gnome3.gnome-session ];
 
     services.xserver.displayManager.sessionCommands = ''
diff --git a/nixos/modules/services/x11/desktop-managers/plasma5.nix b/nixos/modules/services/x11/desktop-managers/plasma5.nix
index 11c1aa4315a8..704cc78c1528 100644
--- a/nixos/modules/services/x11/desktop-managers/plasma5.nix
+++ b/nixos/modules/services/x11/desktop-managers/plasma5.nix
@@ -185,10 +185,8 @@ in
         target = "X11/xkb";
       };
 
-      environment.variables = {
-        # Enable GTK applications to load SVG icons
-        GDK_PIXBUF_MODULE_FILE = "${pkgs.librsvg.out}/lib/gdk-pixbuf-2.0/2.10.0/loaders.cache";
-      };
+      # Enable GTK applications to load SVG icons
+      services.xserver.gdk-pixbuf.modulePackages = [ pkgs.librsvg ];
 
       fonts.fonts = with pkgs; [ noto-fonts hack-font ];
       fonts.fontconfig.defaultFonts = {
diff --git a/nixos/modules/services/x11/desktop-managers/xfce.nix b/nixos/modules/services/x11/desktop-managers/xfce.nix
index 75b9a76e1924..dabf09418da7 100644
--- a/nixos/modules/services/x11/desktop-managers/xfce.nix
+++ b/nixos/modules/services/x11/desktop-managers/xfce.nix
@@ -101,10 +101,11 @@ in
     ];
 
     environment.variables = {
-      GDK_PIXBUF_MODULE_FILE = "${pkgs.librsvg.out}/lib/gdk-pixbuf-2.0/2.10.0/loaders.cache";
       GIO_EXTRA_MODULES = [ "${pkgs.xfce.gvfs}/lib/gio/modules" ];
     };
 
+    services.xserver.gdk-pixbuf.modulePackages = [ pkgs.librsvg ];
+
     services.xserver.desktopManager.session = [{
       name = "xfce";
       bgSupport = true;
diff --git a/nixos/modules/services/x11/display-managers/startx.nix b/nixos/modules/services/x11/display-managers/startx.nix
new file mode 100644
index 000000000000..15609540a6e7
--- /dev/null
+++ b/nixos/modules/services/x11/display-managers/startx.nix
@@ -0,0 +1,44 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+  cfg = config.services.xserver.displayManager.startx;
+
+in
+
+{
+
+  ###### interface
+
+  options = {
+    services.xserver.displayManager.startx = {
+      enable = mkOption {
+        default = false;
+        description = ''
+          Whether to enable the dummy "startx" pseudo-display manager,
+          which allows users to start X manually via the "startx" command
+          from a vt shell. The X server runs under the user's id, not as root.
+          The user must provide a ~/.xinintrc file containing session startup
+          commands, see startx(1). This is not autmatically generated
+          from the desktopManager and windowManager settings.
+        '';
+      };
+    };
+  };
+
+
+  ###### implementation
+
+  config = mkIf cfg.enable {
+    services.xserver = {
+      exportConfiguration = true;
+      displayManager.job.execCmd = "";
+      displayManager.lightdm.enable = lib.mkForce false;
+    };
+    systemd.services.display-manager.enable = false;
+    environment.systemPackages =  with pkgs; [ xorg.xinit ];
+  };
+
+}
diff --git a/nixos/modules/services/x11/gdk-pixbuf.nix b/nixos/modules/services/x11/gdk-pixbuf.nix
new file mode 100644
index 000000000000..58faa8e2f9df
--- /dev/null
+++ b/nixos/modules/services/x11/gdk-pixbuf.nix
@@ -0,0 +1,45 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.services.xserver.gdk-pixbuf;
+
+  # Get packages to generate the cache for. We always include gdk_pixbuf.
+  effectivePackages = unique ([pkgs.gdk_pixbuf] ++ cfg.modulePackages);
+
+  # Generate the cache file by running gdk-pixbuf-query-loaders for each
+  # package and concatenating the results.
+  loadersCache = pkgs.runCommand "gdk-pixbuf-loaders.cache" {} ''
+    (
+      for package in ${concatStringsSep " " effectivePackages}; do
+        module_dir="$package/${pkgs.gdk_pixbuf.moduleDir}"
+        if [[ ! -d $module_dir ]]; then
+          echo "Warning (services.xserver.gdk-pixbuf): missing module directory $module_dir" 1>&2
+          continue
+        fi
+        GDK_PIXBUF_MODULEDIR="$module_dir" \
+          ${pkgs.gdk_pixbuf.dev}/bin/gdk-pixbuf-query-loaders
+      done
+    ) > "$out"
+  '';
+in
+
+{
+  options = {
+    services.xserver.gdk-pixbuf.modulePackages = mkOption {
+      type = types.listOf types.package;
+      default = [ ];
+      description = "Packages providing GDK-Pixbuf modules, for cache generation.";
+    };
+  };
+
+  # If there is any package configured in modulePackages, we generate the
+  # loaders.cache based on that and set the environment variable
+  # GDK_PIXBUF_MODULE_FILE to point to it.
+  config = mkIf (cfg.modulePackages != []) {
+    environment.variables = {
+      GDK_PIXBUF_MODULE_FILE = "${loadersCache}";
+    };
+  };
+}
diff --git a/nixos/modules/system/boot/luksroot.nix b/nixos/modules/system/boot/luksroot.nix
index 1079089bc5a8..018e7b2e7f89 100644
--- a/nixos/modules/system/boot/luksroot.nix
+++ b/nixos/modules/system/boot/luksroot.nix
@@ -7,19 +7,19 @@ let
 
   commonFunctions = ''
     die() {
-      echo "$@" >&2
-      exit 1
+        echo "$@" >&2
+        exit 1
     }
 
     dev_exist() {
-      local target="$1"
-      if [ -e $target ]; then
-        return 0
-      else
-        local uuid=$(echo -n $target | sed -e 's,UUID=\(.*\),\1,g')
-        local dev=$(blkid --uuid $uuid)
-        return $?
-      fi
+        local target="$1"
+        if [ -e $target ]; then
+            return 0
+        else
+            local uuid=$(echo -n $target | sed -e 's,UUID=\(.*\),\1,g')
+            blkid --uuid $uuid >/dev/null
+            return $?
+        fi
     }
 
     wait_target() {
@@ -51,30 +51,30 @@ let
     }
 
     wait_yubikey() {
-      local secs="''${1:-10}"
-
-      ykinfo -v 1>/dev/null 2>&1
-      if [ $? != 0 ]; then
-          echo -n "Waiting $secs seconds for Yubikey to appear..."
-          local success=false
-          for try in $(seq $secs); do
-              echo -n .
-              sleep 1
-              ykinfo -v 1>/dev/null 2>&1
-              if [ $? == 0 ]; then
-                  success=true
-                  break
-              fi
-          done
-          if [ $success == true ]; then
-              echo " - success";
-              return 0
-          else
-              echo " - failure";
-              return 1
-          fi
-      fi
-      return 0
+        local secs="''${1:-10}"
+
+        ykinfo -v 1>/dev/null 2>&1
+        if [ $? != 0 ]; then
+            echo -n "Waiting $secs seconds for Yubikey to appear..."
+            local success=false
+            for try in $(seq $secs); do
+                echo -n .
+                sleep 1
+                ykinfo -v 1>/dev/null 2>&1
+                if [ $? == 0 ]; then
+                    success=true
+                    break
+                fi
+            done
+            if [ $success == true ]; then
+                echo " - success";
+                return 0
+            else
+                echo " - failure";
+                return 1
+            fi
+        fi
+        return 0
     }
   '';
 
diff --git a/nixos/modules/system/boot/stage-1.nix b/nixos/modules/system/boot/stage-1.nix
index f58b68cb3353..f4cf9753c0a1 100644
--- a/nixos/modules/system/boot/stage-1.nix
+++ b/nixos/modules/system/boot/stage-1.nix
@@ -251,9 +251,9 @@ let
     postInstall = ''
       echo checking syntax
       # check both with bash
-      ${pkgs.bash}/bin/sh -n $target
+      ${pkgs.buildPackages.bash}/bin/sh -n $target
       # and with ash shell, just in case
-      ${extraUtils}/bin/ash -n $target
+      ${pkgs.buildPackages.busybox}/bin/ash -n $target
     '';
 
     inherit udevRules extraUtils modulesClosure;
diff --git a/nixos/modules/tasks/network-interfaces-scripted.nix b/nixos/modules/tasks/network-interfaces-scripted.nix
index af61c95da0af..93dfefdce902 100644
--- a/nixos/modules/tasks/network-interfaces-scripted.nix
+++ b/nixos/modules/tasks/network-interfaces-scripted.nix
@@ -85,7 +85,8 @@ let
             after = [ "network-pre.target" "systemd-udevd.service" "systemd-sysctl.service" ];
             before = [ "network.target" "shutdown.target" ];
             wants = [ "network.target" ];
-            partOf = map (i: "network-addresses-${i.name}.service") interfaces;
+            # exclude bridges from the partOf relationship to fix container networking bug #47210
+            partOf = map (i: "network-addresses-${i.name}.service") (filter (i: !(hasAttr i.name cfg.bridges)) interfaces);
             conflicts = [ "shutdown.target" ];
             wantedBy = [ "multi-user.target" ] ++ optional hasDefaultGatewaySet "network-online.target";
 
diff --git a/nixos/modules/virtualisation/qemu-guest-agent.nix b/nixos/modules/virtualisation/qemu-guest-agent.nix
index e0d2b3dc509d..665224e35d8c 100644
--- a/nixos/modules/virtualisation/qemu-guest-agent.nix
+++ b/nixos/modules/virtualisation/qemu-guest-agent.nix
@@ -25,7 +25,7 @@ in {
       systemd.services.qemu-guest-agent = {
         description = "Run the QEMU Guest Agent";
         serviceConfig = {
-          ExecStart = "${pkgs.kvm.ga}/bin/qemu-ga";
+          ExecStart = "${pkgs.qemu.ga}/bin/qemu-ga";
           Restart = "always";
           RestartSec = 0;
         };
diff --git a/nixos/modules/virtualisation/virtualbox-image.nix b/nixos/modules/virtualisation/virtualbox-image.nix
index 3d4c06f1f23f..60048911658c 100644
--- a/nixos/modules/virtualisation/virtualbox-image.nix
+++ b/nixos/modules/virtualisation/virtualbox-image.nix
@@ -12,7 +12,7 @@ in {
     virtualbox = {
       baseImageSize = mkOption {
         type = types.int;
-        default = 100 * 1024;
+        default = 10 * 1024;
         description = ''
           The size of the VirtualBox base image in MiB.
         '';
diff --git a/nixos/modules/virtualisation/xe-guest-utilities.nix b/nixos/modules/virtualisation/xe-guest-utilities.nix
index d703353858c0..675cf9297371 100644
--- a/nixos/modules/virtualisation/xe-guest-utilities.nix
+++ b/nixos/modules/virtualisation/xe-guest-utilities.nix
@@ -5,7 +5,7 @@ let
 in {
   options = {
     services.xe-guest-utilities = {
-      enable = mkEnableOption "Whether to enable the Xen guest utilities daemon.";
+      enable = mkEnableOption "the Xen guest utilities daemon";
     };
   };
   config = mkIf cfg.enable {