about summary refs log tree commit diff
path: root/nixpkgs/nixos/modules
diff options
context:
space:
mode:
authorAlyssa Ross <hi@alyssa.is>2021-01-26 18:06:19 +0000
committerAlyssa Ross <hi@alyssa.is>2021-01-26 18:21:18 +0000
commit7ac6743433dd45ceaead2ca96f6356dc0d064ce6 (patch)
treeb68ec89d7d2a8d2b6e6b1ff94ba26d6af4096350 /nixpkgs/nixos/modules
parentc5c7451dbef37b51f52792d6395a670ef5183d27 (diff)
parent891f607d5301d6730cb1f9dcf3618bcb1ab7f10e (diff)
downloadnixlib-7ac6743433dd45ceaead2ca96f6356dc0d064ce6.tar
nixlib-7ac6743433dd45ceaead2ca96f6356dc0d064ce6.tar.gz
nixlib-7ac6743433dd45ceaead2ca96f6356dc0d064ce6.tar.bz2
nixlib-7ac6743433dd45ceaead2ca96f6356dc0d064ce6.tar.lz
nixlib-7ac6743433dd45ceaead2ca96f6356dc0d064ce6.tar.xz
nixlib-7ac6743433dd45ceaead2ca96f6356dc0d064ce6.tar.zst
nixlib-7ac6743433dd45ceaead2ca96f6356dc0d064ce6.zip
Merge commit '891f607d5301d6730cb1f9dcf3618bcb1ab7f10e'
Diffstat (limited to 'nixpkgs/nixos/modules')
-rw-r--r--nixpkgs/nixos/modules/config/console.nix2
-rw-r--r--nixpkgs/nixos/modules/config/fonts/fontconfig.nix2
-rw-r--r--nixpkgs/nixos/modules/config/gnu.nix10
-rw-r--r--nixpkgs/nixos/modules/config/i18n.nix2
-rw-r--r--nixpkgs/nixos/modules/config/networking.nix4
-rw-r--r--nixpkgs/nixos/modules/config/pulseaudio.nix2
-rw-r--r--nixpkgs/nixos/modules/config/system-path.nix1
-rw-r--r--nixpkgs/nixos/modules/config/users-groups.nix4
-rw-r--r--nixpkgs/nixos/modules/config/xdg/portal.nix2
-rw-r--r--nixpkgs/nixos/modules/hardware/device-tree.nix8
-rw-r--r--nixpkgs/nixos/modules/hardware/nitrokey.nix16
-rw-r--r--nixpkgs/nixos/modules/hardware/opentabletdriver.nix17
-rw-r--r--nixpkgs/nixos/modules/hardware/video/bumblebee.nix2
-rw-r--r--nixpkgs/nixos/modules/i18n/input-method/default.nix3
-rw-r--r--nixpkgs/nixos/modules/i18n/input-method/fcitx5.nix33
-rw-r--r--nixpkgs/nixos/modules/i18n/input-method/ibus.nix2
-rw-r--r--nixpkgs/nixos/modules/installer/cd-dvd/iso-image.nix7
-rw-r--r--nixpkgs/nixos/modules/installer/cd-dvd/system-tarball-fuloong2f.nix2
-rw-r--r--nixpkgs/nixos/modules/installer/cd-dvd/system-tarball-sheevaplug.nix2
-rw-r--r--nixpkgs/nixos/modules/installer/netboot/netboot.nix2
-rw-r--r--nixpkgs/nixos/modules/installer/tools/nixos-option/default.nix10
-rw-r--r--nixpkgs/nixos/modules/installer/tools/nixos-rebuild.sh506
-rw-r--r--nixpkgs/nixos/modules/installer/tools/tools.nix12
-rw-r--r--nixpkgs/nixos/modules/misc/crashdump.nix1
-rw-r--r--nixpkgs/nixos/modules/misc/documentation.nix2
-rw-r--r--nixpkgs/nixos/modules/misc/ids.nix4
-rw-r--r--nixpkgs/nixos/modules/misc/locate.nix2
-rw-r--r--nixpkgs/nixos/modules/misc/nixpkgs.nix2
-rw-r--r--nixpkgs/nixos/modules/module-list.nix10
-rw-r--r--nixpkgs/nixos/modules/profiles/all-hardware.nix11
-rw-r--r--nixpkgs/nixos/modules/profiles/installation-device.nix4
-rw-r--r--nixpkgs/nixos/modules/programs/appgate-sdp.nix23
-rw-r--r--nixpkgs/nixos/modules/programs/captive-browser.nix14
-rw-r--r--nixpkgs/nixos/modules/programs/command-not-found/command-not-found.nix2
-rw-r--r--nixpkgs/nixos/modules/programs/fish.nix297
-rw-r--r--nixpkgs/nixos/modules/programs/ssh.nix2
-rw-r--r--nixpkgs/nixos/modules/programs/tilp2.nix28
-rw-r--r--nixpkgs/nixos/modules/programs/xss-lock.nix2
-rw-r--r--nixpkgs/nixos/modules/security/pam.nix8
-rw-r--r--nixpkgs/nixos/modules/services/amqp/activemq/default.nix1
-rw-r--r--nixpkgs/nixos/modules/services/audio/mpd.nix71
-rw-r--r--nixpkgs/nixos/modules/services/audio/mpdscribble.nix202
-rw-r--r--nixpkgs/nixos/modules/services/backup/bacula.nix3
-rw-r--r--nixpkgs/nixos/modules/services/backup/tarsnap.nix13
-rw-r--r--nixpkgs/nixos/modules/services/cluster/hadoop/default.nix3
-rw-r--r--nixpkgs/nixos/modules/services/computing/slurm/slurm.nix6
-rw-r--r--nixpkgs/nixos/modules/services/continuous-integration/buildbot/master.nix1
-rw-r--r--nixpkgs/nixos/modules/services/databases/couchdb.nix3
-rw-r--r--nixpkgs/nixos/modules/services/databases/firebird.nix5
-rw-r--r--nixpkgs/nixos/modules/services/databases/memcached.nix15
-rw-r--r--nixpkgs/nixos/modules/services/databases/mongodb.nix7
-rw-r--r--nixpkgs/nixos/modules/services/databases/neo4j.nix8
-rw-r--r--nixpkgs/nixos/modules/services/databases/openldap.nix2
-rw-r--r--nixpkgs/nixos/modules/services/databases/redis.nix99
-rw-r--r--nixpkgs/nixos/modules/services/databases/virtuoso.nix5
-rw-r--r--nixpkgs/nixos/modules/services/desktops/gnome3/evolution-data-server.nix54
-rw-r--r--nixpkgs/nixos/modules/services/desktops/pipewire.nix4
-rw-r--r--nixpkgs/nixos/modules/services/development/bloop.nix2
-rw-r--r--nixpkgs/nixos/modules/services/development/hoogle.nix7
-rw-r--r--nixpkgs/nixos/modules/services/editors/emacs.xml10
-rw-r--r--nixpkgs/nixos/modules/services/editors/infinoted.nix8
-rw-r--r--nixpkgs/nixos/modules/services/games/openarena.nix2
-rw-r--r--nixpkgs/nixos/modules/services/hardware/sane_extra_backends/brscan4_etc_files.nix14
-rw-r--r--nixpkgs/nixos/modules/services/logging/logstash.nix4
-rw-r--r--nixpkgs/nixos/modules/services/mail/mailman.nix2
-rw-r--r--nixpkgs/nixos/modules/services/mail/postfix.nix18
-rw-r--r--nixpkgs/nixos/modules/services/mail/postgrey.nix2
-rw-r--r--nixpkgs/nixos/modules/services/misc/autofs.nix1
-rw-r--r--nixpkgs/nixos/modules/services/misc/cgminer.nix2
-rw-r--r--nixpkgs/nixos/modules/services/misc/dictd.nix2
-rw-r--r--nixpkgs/nixos/modules/services/misc/exhibitor.nix2
-rw-r--r--nixpkgs/nixos/modules/services/misc/gitea.nix59
-rw-r--r--nixpkgs/nixos/modules/services/misc/gitlab.nix8
-rw-r--r--nixpkgs/nixos/modules/services/misc/gitolite.nix2
-rw-r--r--nixpkgs/nixos/modules/services/misc/matrix-synapse.nix3
-rw-r--r--nixpkgs/nixos/modules/services/misc/matrix-synapse.xml5
-rw-r--r--nixpkgs/nixos/modules/services/misc/nix-daemon.nix8
-rw-r--r--nixpkgs/nixos/modules/services/misc/nzbhydra2.nix78
-rw-r--r--nixpkgs/nixos/modules/services/misc/redmine.nix4
-rw-r--r--nixpkgs/nixos/modules/services/misc/snapper.nix2
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/apcupsd.nix2
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/grafana-image-renderer.nix2
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/graphite.nix6
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/incron.nix2
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/prometheus/default.nix54
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/collectd.nix2
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/nextcloud.nix10
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/telegraf.nix2
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/thanos.nix4
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/ups.nix2
-rw-r--r--nixpkgs/nixos/modules/services/network-filesystems/ceph.nix4
-rw-r--r--nixpkgs/nixos/modules/services/networking/amuled.nix4
-rw-r--r--nixpkgs/nixos/modules/services/networking/bitlbee.nix4
-rw-r--r--nixpkgs/nixos/modules/services/networking/cntlm.nix4
-rw-r--r--nixpkgs/nixos/modules/services/networking/connman.nix3
-rw-r--r--nixpkgs/nixos/modules/services/networking/dnscrypt-wrapper.nix4
-rw-r--r--nixpkgs/nixos/modules/services/networking/dnsdist.nix3
-rw-r--r--nixpkgs/nixos/modules/services/networking/gateone.nix4
-rw-r--r--nixpkgs/nixos/modules/services/networking/hostapd.nix4
-rw-r--r--nixpkgs/nixos/modules/services/networking/hylafax/modem-default.nix6
-rw-r--r--nixpkgs/nixos/modules/services/networking/hylafax/options.nix20
-rw-r--r--nixpkgs/nixos/modules/services/networking/hylafax/systemd.nix28
-rw-r--r--nixpkgs/nixos/modules/services/networking/iwd.nix5
-rw-r--r--nixpkgs/nixos/modules/services/networking/kippo.nix14
-rw-r--r--nixpkgs/nixos/modules/services/networking/murmur.nix9
-rw-r--r--nixpkgs/nixos/modules/services/networking/nomad.nix165
-rw-r--r--nixpkgs/nixos/modules/services/networking/ntp/chrony.nix52
-rw-r--r--nixpkgs/nixos/modules/services/networking/ntp/ntpd.nix1
-rw-r--r--nixpkgs/nixos/modules/services/networking/owamp.nix2
-rw-r--r--nixpkgs/nixos/modules/services/networking/privoxy.nix7
-rw-r--r--nixpkgs/nixos/modules/services/networking/quassel.nix2
-rw-r--r--nixpkgs/nixos/modules/services/networking/searx.nix214
-rw-r--r--nixpkgs/nixos/modules/services/networking/smokeping.nix2
-rw-r--r--nixpkgs/nixos/modules/services/networking/ssh/lshd.nix12
-rw-r--r--nixpkgs/nixos/modules/services/networking/strongswan-swanctl/swanctl-params.nix2
-rw-r--r--nixpkgs/nixos/modules/services/networking/supybot.nix2
-rw-r--r--nixpkgs/nixos/modules/services/networking/wpa_supplicant.nix4
-rw-r--r--nixpkgs/nixos/modules/services/security/fprintd.nix4
-rw-r--r--nixpkgs/nixos/modules/services/security/tor.nix1392
-rw-r--r--nixpkgs/nixos/modules/services/security/usbguard.nix2
-rw-r--r--nixpkgs/nixos/modules/services/security/vault.nix46
-rw-r--r--nixpkgs/nixos/modules/services/system/cloud-init.nix2
-rw-r--r--nixpkgs/nixos/modules/services/ttys/getty.nix (renamed from nixpkgs/nixos/modules/services/ttys/agetty.nix)20
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/dokuwiki.nix2
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/ihatemoney/default.nix9
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/keycloak.nix2
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/moodle.nix2
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/nextcloud.xml6
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/trilium.nix2
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/whitebophir.nix45
-rw-r--r--nixpkgs/nixos/modules/services/web-servers/jboss/default.nix6
-rw-r--r--nixpkgs/nixos/modules/services/web-servers/lighttpd/default.nix2
-rw-r--r--nixpkgs/nixos/modules/services/web-servers/nginx/default.nix21
-rw-r--r--nixpkgs/nixos/modules/services/web-servers/tomcat.nix1
-rw-r--r--nixpkgs/nixos/modules/services/web-servers/uwsgi.nix71
-rw-r--r--nixpkgs/nixos/modules/services/x11/desktop-managers/gnome3.nix6
-rw-r--r--nixpkgs/nixos/modules/services/x11/desktop-managers/plasma5.nix10
-rw-r--r--nixpkgs/nixos/modules/services/x11/hardware/libinput.nix97
-rw-r--r--nixpkgs/nixos/modules/services/x11/window-managers/clfswm.nix4
-rw-r--r--nixpkgs/nixos/modules/services/x11/window-managers/default.nix1
-rw-r--r--nixpkgs/nixos/modules/services/x11/window-managers/exwm.nix2
-rw-r--r--nixpkgs/nixos/modules/system/activation/top-level.nix2
-rw-r--r--nixpkgs/nixos/modules/system/boot/binfmt.nix10
-rw-r--r--nixpkgs/nixos/modules/system/boot/loader/generations-dir/generations-dir.nix2
-rw-r--r--nixpkgs/nixos/modules/system/boot/loader/grub/grub.nix22
-rw-r--r--nixpkgs/nixos/modules/system/boot/loader/raspberrypi/raspberrypi.nix7
-rw-r--r--nixpkgs/nixos/modules/system/boot/plymouth.nix2
-rw-r--r--nixpkgs/nixos/modules/system/boot/stage-1.nix9
-rw-r--r--nixpkgs/nixos/modules/system/boot/systemd.nix4
-rw-r--r--nixpkgs/nixos/modules/system/boot/timesyncd.nix1
-rw-r--r--nixpkgs/nixos/modules/system/boot/tmp.nix9
-rw-r--r--nixpkgs/nixos/modules/tasks/filesystems/zfs.nix4
-rw-r--r--nixpkgs/nixos/modules/virtualisation/azure-agent.nix2
-rw-r--r--nixpkgs/nixos/modules/virtualisation/docker.nix9
-rw-r--r--nixpkgs/nixos/modules/virtualisation/ec2-amis.nix36
-rw-r--r--nixpkgs/nixos/modules/virtualisation/google-compute-image.nix2
-rw-r--r--nixpkgs/nixos/modules/virtualisation/lxc-container.nix2
-rw-r--r--nixpkgs/nixos/modules/virtualisation/lxd.nix4
-rw-r--r--nixpkgs/nixos/modules/virtualisation/nixos-containers.nix4
-rw-r--r--nixpkgs/nixos/modules/virtualisation/podman.nix50
-rw-r--r--nixpkgs/nixos/modules/virtualisation/qemu-vm.nix9
-rw-r--r--nixpkgs/nixos/modules/virtualisation/railcar.nix2
162 files changed, 2707 insertions, 1717 deletions
diff --git a/nixpkgs/nixos/modules/config/console.nix b/nixpkgs/nixos/modules/config/console.nix
index ab1667605177..1339227f1e02 100644
--- a/nixpkgs/nixos/modules/config/console.nix
+++ b/nixpkgs/nixos/modules/config/console.nix
@@ -83,7 +83,7 @@ in
     packages = mkOption {
       type = types.listOf types.package;
       default = with pkgs.kbdKeymaps; [ dvp neo ];
-      defaultText = ''with pkgs.kbdKeymaps; [ dvp neo ]'';
+      defaultText = "with pkgs.kbdKeymaps; [ dvp neo ]";
       description = ''
         List of additional packages that provide console fonts, keymaps and
         other resources for virtual consoles use.
diff --git a/nixpkgs/nixos/modules/config/fonts/fontconfig.nix b/nixpkgs/nixos/modules/config/fonts/fontconfig.nix
index 5b681ca59464..6e7b8c4b88a2 100644
--- a/nixpkgs/nixos/modules/config/fonts/fontconfig.nix
+++ b/nixpkgs/nixos/modules/config/fonts/fontconfig.nix
@@ -436,7 +436,7 @@ in
         useEmbeddedBitmaps = mkOption {
           type = types.bool;
           default = false;
-          description = ''Use embedded bitmaps in fonts like Calibri.'';
+          description = "Use embedded bitmaps in fonts like Calibri.";
         };
 
       };
diff --git a/nixpkgs/nixos/modules/config/gnu.nix b/nixpkgs/nixos/modules/config/gnu.nix
index 93d130970190..255d9741ba71 100644
--- a/nixpkgs/nixos/modules/config/gnu.nix
+++ b/nixpkgs/nixos/modules/config/gnu.nix
@@ -1,11 +1,9 @@
 { config, lib, pkgs, ... }:
 
-with lib;
-
 {
   options = {
-    gnu = mkOption {
-      type = types.bool;
+    gnu = lib.mkOption {
+      type = lib.types.bool;
       default = false;
       description = ''
         When enabled, GNU software is chosen by default whenever a there is
@@ -15,7 +13,7 @@ with lib;
     };
   };
 
-  config = mkIf config.gnu {
+  config = lib.mkIf config.gnu {
 
     environment.systemPackages = with pkgs;
       # TODO: Adjust `requiredPackages' from `system-path.nix'.
@@ -26,7 +24,7 @@ with lib;
         nano zile
         texinfo # for the stand-alone Info reader
       ]
-      ++ stdenv.lib.optional (!stdenv.isAarch32) grub2;
+      ++ lib.optional (!stdenv.isAarch32) grub2;
 
 
     # GNU GRUB, where available.
diff --git a/nixpkgs/nixos/modules/config/i18n.nix b/nixpkgs/nixos/modules/config/i18n.nix
index feb76581a720..991b449d80b5 100644
--- a/nixpkgs/nixos/modules/config/i18n.nix
+++ b/nixpkgs/nixos/modules/config/i18n.nix
@@ -84,7 +84,7 @@ with lib;
     environment.etc."locale.conf".source = pkgs.writeText "locale.conf"
       ''
         LANG=${config.i18n.defaultLocale}
-        ${concatStringsSep "\n" (mapAttrsToList (n: v: ''${n}=${v}'') config.i18n.extraLocaleSettings)}
+        ${concatStringsSep "\n" (mapAttrsToList (n: v: "${n}=${v}") config.i18n.extraLocaleSettings)}
       '';
 
   };
diff --git a/nixpkgs/nixos/modules/config/networking.nix b/nixpkgs/nixos/modules/config/networking.nix
index 4cb7d81c9972..dba8977e482c 100644
--- a/nixpkgs/nixos/modules/config/networking.nix
+++ b/nixpkgs/nixos/modules/config/networking.nix
@@ -58,6 +58,7 @@ in
         "2.nixos.pool.ntp.org"
         "3.nixos.pool.ntp.org"
       ];
+      type = types.listOf types.str;
       description = ''
         The set of NTP servers from which to synchronise.
       '';
@@ -193,6 +194,9 @@ in
           cat ${escapeShellArgs cfg.hostFiles} > $out
         '';
 
+        # /etc/netgroup: Network-wide groups.
+        netgroup.text = mkDefault "";
+
         # /etc/host.conf: resolver configuration file
         "host.conf".text = ''
           multi on
diff --git a/nixpkgs/nixos/modules/config/pulseaudio.nix b/nixpkgs/nixos/modules/config/pulseaudio.nix
index a77524d75d8d..c0e90a8c26e6 100644
--- a/nixpkgs/nixos/modules/config/pulseaudio.nix
+++ b/nixpkgs/nixos/modules/config/pulseaudio.nix
@@ -183,7 +183,7 @@ in {
         config = mkOption {
           type = types.attrsOf types.unspecified;
           default = {};
-          description = ''Config of the pulse daemon. See <literal>man pulse-daemon.conf</literal>.'';
+          description = "Config of the pulse daemon. See <literal>man pulse-daemon.conf</literal>.";
           example = literalExample ''{ realtime-scheduling = "yes"; }'';
         };
       };
diff --git a/nixpkgs/nixos/modules/config/system-path.nix b/nixpkgs/nixos/modules/config/system-path.nix
index 27d1cef849bc..aee7a041d043 100644
--- a/nixpkgs/nixos/modules/config/system-path.nix
+++ b/nixpkgs/nixos/modules/config/system-path.nix
@@ -144,6 +144,7 @@ in
         "/share/kservicetypes5"
         "/share/kxmlgui5"
         "/share/systemd"
+        "/share/thumbnailers"
       ];
 
     system.path = pkgs.buildEnv {
diff --git a/nixpkgs/nixos/modules/config/users-groups.nix b/nixpkgs/nixos/modules/config/users-groups.nix
index e90a7d567d42..5b3e9a8ceb7f 100644
--- a/nixpkgs/nixos/modules/config/users-groups.nix
+++ b/nixpkgs/nixos/modules/config/users-groups.nix
@@ -364,7 +364,7 @@ let
       count = mkOption {
         type = types.int;
         default = 1;
-        description = ''Count of subordinate user ids'';
+        description = "Count of subordinate user ids";
       };
     };
   };
@@ -381,7 +381,7 @@ let
       count = mkOption {
         type = types.int;
         default = 1;
-        description = ''Count of subordinate group ids'';
+        description = "Count of subordinate group ids";
       };
     };
   };
diff --git a/nixpkgs/nixos/modules/config/xdg/portal.nix b/nixpkgs/nixos/modules/config/xdg/portal.nix
index 3c7cd729c60a..80ec3126ca54 100644
--- a/nixpkgs/nixos/modules/config/xdg/portal.nix
+++ b/nixpkgs/nixos/modules/config/xdg/portal.nix
@@ -62,7 +62,7 @@ with lib;
       services.dbus.packages  = packages;
       systemd.packages = packages;
 
-      environment.variables = {
+      environment.sessionVariables = {
         GTK_USE_PORTAL = mkIf cfg.gtkUsePortal "1";
         XDG_DESKTOP_PORTAL_DIR = "${joinedPortals}/share/xdg-desktop-portal/portals";
       };
diff --git a/nixpkgs/nixos/modules/hardware/device-tree.nix b/nixpkgs/nixos/modules/hardware/device-tree.nix
index e0ab37bca63a..4aa1d6369d1b 100644
--- a/nixpkgs/nixos/modules/hardware/device-tree.nix
+++ b/nixpkgs/nixos/modules/hardware/device-tree.nix
@@ -68,11 +68,11 @@ let
       patchShebangs scripts/*
       substituteInPlace scripts/Makefile.lib \
         --replace 'DTC_FLAGS += $(DTC_FLAGS_$(basetarget))' 'DTC_FLAGS += $(DTC_FLAGS_$(basetarget)) -@'
-      make ${pkgs.stdenv.hostPlatform.platform.kernelBaseConfig} ARCH="${pkgs.stdenv.hostPlatform.platform.kernelArch}"
-      make dtbs ARCH="${pkgs.stdenv.hostPlatform.platform.kernelArch}"
+      make ${pkgs.stdenv.hostPlatform.linux-kernel.baseConfig} ARCH="${pkgs.stdenv.hostPlatform.linuxArch}"
+      make dtbs ARCH="${pkgs.stdenv.hostPlatform.linuxArch}"
     '';
     installPhase = ''
-      make dtbs_install INSTALL_DTBS_PATH=$out/dtbs  ARCH="${pkgs.stdenv.hostPlatform.platform.kernelArch}"
+      make dtbs_install INSTALL_DTBS_PATH=$out/dtbs  ARCH="${pkgs.stdenv.hostPlatform.linuxArch}"
     '';
   };
 
@@ -115,7 +115,7 @@ in
   options = {
       hardware.deviceTree = {
         enable = mkOption {
-          default = pkgs.stdenv.hostPlatform.platform.kernelDTB or false;
+          default = pkgs.stdenv.hostPlatform.linux-kernel.DTB or false;
           type = types.bool;
           description = ''
             Build device tree files. These are used to describe the
diff --git a/nixpkgs/nixos/modules/hardware/nitrokey.nix b/nixpkgs/nixos/modules/hardware/nitrokey.nix
index 02e4c3f46f8d..baa07203118c 100644
--- a/nixpkgs/nixos/modules/hardware/nitrokey.nix
+++ b/nixpkgs/nixos/modules/hardware/nitrokey.nix
@@ -19,23 +19,9 @@ in
         nitrokey-app package, depending on your device and needs.
       '';
     };
-
-    group = mkOption {
-      type = types.str;
-      default = "nitrokey";
-      example = "wheel";
-      description = ''
-        Grant access to Nitrokey devices to users in this group.
-      '';
-    };
   };
 
   config = mkIf cfg.enable {
-    services.udev.packages = [
-      (pkgs.nitrokey-udev-rules.override (attrs:
-        { inherit (cfg) group; }
-      ))
-    ];
-    users.groups.${cfg.group} = {};
+    services.udev.packages = [ pkgs.nitrokey-udev-rules ];
   };
 }
diff --git a/nixpkgs/nixos/modules/hardware/opentabletdriver.nix b/nixpkgs/nixos/modules/hardware/opentabletdriver.nix
index b759bcf034ee..295e23e6164f 100644
--- a/nixpkgs/nixos/modules/hardware/opentabletdriver.nix
+++ b/nixpkgs/nixos/modules/hardware/opentabletdriver.nix
@@ -5,6 +5,8 @@ let
   cfg = config.hardware.opentabletdriver;
 in
 {
+  meta.maintainers = with lib.maintainers; [ thiagokokada ];
+
   options = {
     hardware.opentabletdriver = {
       enable = mkOption {
@@ -24,6 +26,15 @@ in
         '';
       };
 
+      package = mkOption {
+        type = types.package;
+        default = pkgs.opentabletdriver;
+        defaultText = "pkgs.opentabletdriver";
+        description = ''
+          OpenTabletDriver derivation to use.
+        '';
+      };
+
       daemon = {
         enable = mkOption {
           default = true;
@@ -37,9 +48,9 @@ in
   };
 
   config = mkIf cfg.enable {
-    environment.systemPackages = with pkgs; [ opentabletdriver ];
+    environment.systemPackages = [ cfg.package ];
 
-    services.udev.packages = with pkgs; [ opentabletdriver ];
+    services.udev.packages = [ cfg.package ];
 
     boot.blacklistedKernelModules = cfg.blacklistedKernelModules;
 
@@ -50,7 +61,7 @@ in
 
       serviceConfig = {
         Type = "simple";
-        ExecStart = "${opentabletdriver}/bin/otd-daemon -c ${opentabletdriver}/lib/OpenTabletDriver/Configurations";
+        ExecStart = "${cfg.package}/bin/otd-daemon -c ${cfg.package}/lib/OpenTabletDriver/Configurations";
         Restart = "on-failure";
       };
     };
diff --git a/nixpkgs/nixos/modules/hardware/video/bumblebee.nix b/nixpkgs/nixos/modules/hardware/video/bumblebee.nix
index 2278c7b40611..b6af4f80445a 100644
--- a/nixpkgs/nixos/modules/hardware/video/bumblebee.nix
+++ b/nixpkgs/nixos/modules/hardware/video/bumblebee.nix
@@ -40,7 +40,7 @@ in
         default = "wheel";
         example = "video";
         type = types.str;
-        description = ''Group for bumblebee socket'';
+        description = "Group for bumblebee socket";
       };
 
       connectDisplay = mkOption {
diff --git a/nixpkgs/nixos/modules/i18n/input-method/default.nix b/nixpkgs/nixos/modules/i18n/input-method/default.nix
index 0d6dd3399bfc..4649f9b862a5 100644
--- a/nixpkgs/nixos/modules/i18n/input-method/default.nix
+++ b/nixpkgs/nixos/modules/i18n/input-method/default.nix
@@ -29,7 +29,7 @@ in
   options.i18n = {
     inputMethod = {
       enabled = mkOption {
-        type    = types.nullOr (types.enum [ "ibus" "fcitx" "nabi" "uim" "hime" ]);
+        type    = types.nullOr (types.enum [ "ibus" "fcitx" "fcitx5" "nabi" "uim" "hime" ]);
         default = null;
         example = "fcitx";
         description = ''
@@ -42,6 +42,7 @@ in
           <itemizedlist>
           <listitem><para>ibus: The intelligent input bus, extra input engines can be added using <literal>i18n.inputMethod.ibus.engines</literal>.</para></listitem>
           <listitem><para>fcitx: A customizable lightweight input method, extra input engines can be added using <literal>i18n.inputMethod.fcitx.engines</literal>.</para></listitem>
+          <listitem><para>fcitx5: The next generation of fcitx, addons (including engines, dictionaries, skins) can be added using <literal>i18n.inputMethod.fcitx5.addons</literal>.</para></listitem>
           <listitem><para>nabi: A Korean input method based on XIM. Nabi doesn't support Qt 5.</para></listitem>
           <listitem><para>uim: The universal input method, is a library with a XIM bridge. uim mainly support Chinese, Japanese and Korean.</para></listitem>
           <listitem><para>hime: An extremely easy-to-use input method framework.</para></listitem>
diff --git a/nixpkgs/nixos/modules/i18n/input-method/fcitx5.nix b/nixpkgs/nixos/modules/i18n/input-method/fcitx5.nix
new file mode 100644
index 000000000000..44962d202fe1
--- /dev/null
+++ b/nixpkgs/nixos/modules/i18n/input-method/fcitx5.nix
@@ -0,0 +1,33 @@
+{ config, pkgs, lib, ... }:
+
+with lib;
+
+let
+  im = config.i18n.inputMethod;
+  cfg = im.fcitx5;
+  fcitx5Package = pkgs.fcitx5-with-addons.override { inherit (cfg) addons; };
+in
+  {
+    options = {
+      i18n.inputMethod.fcitx5 = {
+        addons = mkOption {
+          type = with types; listOf package;
+          default = [];
+          example = with pkgs; [ fcitx5-rime ];
+          description = ''
+            Enabled Fcitx5 addons.
+          '';
+        };
+      };
+    };
+
+    config = mkIf (im.enabled == "fcitx5") {
+      i18n.inputMethod.package = fcitx5Package;
+
+      environment.variables = {
+        GTK_IM_MODULE = "fcitx";
+        QT_IM_MODULE = "fcitx";
+        XMODIFIERS = "@im=fcitx";
+      };
+    };
+  }
diff --git a/nixpkgs/nixos/modules/i18n/input-method/ibus.nix b/nixpkgs/nixos/modules/i18n/input-method/ibus.nix
index cf24ecf58631..1aaa5a952bea 100644
--- a/nixpkgs/nixos/modules/i18n/input-method/ibus.nix
+++ b/nixpkgs/nixos/modules/i18n/input-method/ibus.nix
@@ -48,7 +48,7 @@ in
       panel = mkOption {
         type = with types; nullOr path;
         default = null;
-        example = literalExample "''${pkgs.plasma5.plasma-desktop}/lib/libexec/kimpanel-ibus-panel";
+        example = literalExample "''${pkgs.plasma5Packages.plasma-desktop}/lib/libexec/kimpanel-ibus-panel";
         description = "Replace the IBus panel with another panel.";
       };
     };
diff --git a/nixpkgs/nixos/modules/installer/cd-dvd/iso-image.nix b/nixpkgs/nixos/modules/installer/cd-dvd/iso-image.nix
index 43d20a556f8d..1418420afcd9 100644
--- a/nixpkgs/nixos/modules/installer/cd-dvd/iso-image.nix
+++ b/nixpkgs/nixos/modules/installer/cd-dvd/iso-image.nix
@@ -425,7 +425,12 @@ in
     };
 
     isoImage.squashfsCompression = mkOption {
-      default = "xz -Xdict-size 100%";
+      default = with pkgs.stdenv.targetPlatform; "xz -Xdict-size 100% "
+                + lib.optionalString (isx86_32 || isx86_64) "-Xbcj x86"
+                # Untested but should also reduce size for these platforms
+                + lib.optionalString (isAarch32 || isAarch64) "-Xbcj arm"
+                + lib.optionalString (isPowerPC) "-Xbcj powerpc"
+                + lib.optionalString (isSparc) "-Xbcj sparc";
       description = ''
         Compression settings to use for the squashfs nix store.
       '';
diff --git a/nixpkgs/nixos/modules/installer/cd-dvd/system-tarball-fuloong2f.nix b/nixpkgs/nixos/modules/installer/cd-dvd/system-tarball-fuloong2f.nix
index 6d4ba96dba0c..8159576a62ac 100644
--- a/nixpkgs/nixos/modules/installer/cd-dvd/system-tarball-fuloong2f.nix
+++ b/nixpkgs/nixos/modules/installer/cd-dvd/system-tarball-fuloong2f.nix
@@ -104,7 +104,7 @@ in
     '';
 
   # Some more help text.
-  services.mingetty.helpLine =
+  services.getty.helpLine =
     ''
 
       Log in as "root" with an empty password.  ${
diff --git a/nixpkgs/nixos/modules/installer/cd-dvd/system-tarball-sheevaplug.nix b/nixpkgs/nixos/modules/installer/cd-dvd/system-tarball-sheevaplug.nix
index 0e67ae7de698..95579f3ca06d 100644
--- a/nixpkgs/nixos/modules/installer/cd-dvd/system-tarball-sheevaplug.nix
+++ b/nixpkgs/nixos/modules/installer/cd-dvd/system-tarball-sheevaplug.nix
@@ -122,7 +122,7 @@ in
       device = "/dev/something";
     };
 
-  services.mingetty = {
+  services.getty = {
     # Some more help text.
     helpLine = ''
       Log in as "root" with an empty password.  ${
diff --git a/nixpkgs/nixos/modules/installer/netboot/netboot.nix b/nixpkgs/nixos/modules/installer/netboot/netboot.nix
index 95eba86bcb65..fa074fdfcc6e 100644
--- a/nixpkgs/nixos/modules/installer/netboot/netboot.nix
+++ b/nixpkgs/nixos/modules/installer/netboot/netboot.nix
@@ -88,7 +88,7 @@ with lib;
 
     system.build.netbootIpxeScript = pkgs.writeTextDir "netboot.ipxe" ''
       #!ipxe
-      kernel ${pkgs.stdenv.hostPlatform.platform.kernelTarget} init=${config.system.build.toplevel}/init initrd=initrd ${toString config.boot.kernelParams}
+      kernel ${pkgs.stdenv.hostPlatform.linux-kernel.target} init=${config.system.build.toplevel}/init initrd=initrd ${toString config.boot.kernelParams}
       initrd initrd
       boot
     '';
diff --git a/nixpkgs/nixos/modules/installer/tools/nixos-option/default.nix b/nixpkgs/nixos/modules/installer/tools/nixos-option/default.nix
index 753fd92c7bbf..72eec3a38363 100644
--- a/nixpkgs/nixos/modules/installer/tools/nixos-option/default.nix
+++ b/nixpkgs/nixos/modules/installer/tools/nixos-option/default.nix
@@ -1,11 +1,11 @@
-{lib, stdenv, boost, cmake, pkgconfig, nix, ... }:
+{lib, stdenv, boost, cmake, pkg-config, nix, ... }:
 stdenv.mkDerivation rec {
   name = "nixos-option";
   src = ./.;
-  nativeBuildInputs = [ cmake pkgconfig ];
+  nativeBuildInputs = [ cmake pkg-config ];
   buildInputs = [ boost nix ];
-  meta = {
-    license = stdenv.lib.licenses.lgpl2Plus;
-    maintainers = with lib.maintainers; [ chkno ];
+  meta = with lib; {
+    license = licenses.lgpl2Plus;
+    maintainers = with maintainers; [ chkno ];
   };
 }
diff --git a/nixpkgs/nixos/modules/installer/tools/nixos-rebuild.sh b/nixpkgs/nixos/modules/installer/tools/nixos-rebuild.sh
deleted file mode 100644
index e452e24d263d..000000000000
--- a/nixpkgs/nixos/modules/installer/tools/nixos-rebuild.sh
+++ /dev/null
@@ -1,506 +0,0 @@
-#! @runtimeShell@
-
-if [ -x "@runtimeShell@" ]; then export SHELL="@runtimeShell@"; fi;
-
-set -e
-set -o pipefail
-
-export PATH=@path@:$PATH
-
-showSyntax() {
-    exec man nixos-rebuild
-    exit 1
-}
-
-
-# Parse the command line.
-origArgs=("$@")
-extraBuildFlags=()
-lockFlags=()
-flakeFlags=()
-action=
-buildNix=1
-fast=
-rollback=
-upgrade=
-upgrade_all=
-repair=
-profile=/nix/var/nix/profiles/system
-buildHost=
-targetHost=
-maybeSudo=()
-
-while [ "$#" -gt 0 ]; do
-    i="$1"; shift 1
-    case "$i" in
-      --help)
-        showSyntax
-        ;;
-      switch|boot|test|build|edit|dry-build|dry-run|dry-activate|build-vm|build-vm-with-bootloader)
-        if [ "$i" = dry-run ]; then i=dry-build; fi
-        action="$i"
-        ;;
-      --install-grub)
-        echo "$0: --install-grub deprecated, use --install-bootloader instead" >&2
-        export NIXOS_INSTALL_BOOTLOADER=1
-        ;;
-      --install-bootloader)
-        export NIXOS_INSTALL_BOOTLOADER=1
-        ;;
-      --no-build-nix)
-        buildNix=
-        ;;
-      --rollback)
-        rollback=1
-        ;;
-      --upgrade)
-        upgrade=1
-        ;;
-      --upgrade-all)
-        upgrade=1
-        upgrade_all=1
-        ;;
-      --repair)
-        repair=1
-        extraBuildFlags+=("$i")
-        ;;
-      --max-jobs|-j|--cores|-I|--builders)
-        j="$1"; shift 1
-        extraBuildFlags+=("$i" "$j")
-        ;;
-      --show-trace|--keep-failed|-K|--keep-going|-k|--verbose|-v|-vv|-vvv|-vvvv|-vvvvv|--fallback|--repair|--no-build-output|-Q|-j*|-L|--refresh|--no-net|--impure)
-        extraBuildFlags+=("$i")
-        ;;
-      --option)
-        j="$1"; shift 1
-        k="$1"; shift 1
-        extraBuildFlags+=("$i" "$j" "$k")
-        ;;
-      --fast)
-        buildNix=
-        fast=1
-        extraBuildFlags+=(--show-trace)
-        ;;
-      --profile-name|-p)
-        if [ -z "$1" ]; then
-            echo "$0: ‘--profile-name’ requires an argument"
-            exit 1
-        fi
-        if [ "$1" != system ]; then
-            profile="/nix/var/nix/profiles/system-profiles/$1"
-            mkdir -p -m 0755 "$(dirname "$profile")"
-        fi
-        shift 1
-        ;;
-      --build-host|h)
-        buildHost="$1"
-        shift 1
-        ;;
-      --target-host|t)
-        targetHost="$1"
-        shift 1
-        ;;
-      --use-remote-sudo)
-        maybeSudo=(sudo --)
-        ;;
-      --flake)
-        flake="$1"
-        flakeFlags=(--experimental-features 'nix-command flakes')
-        shift 1
-        ;;
-      --recreate-lock-file|--no-update-lock-file|--no-write-lock-file|--no-registries|--commit-lock-file)
-        lockFlags+=("$i")
-        ;;
-      --update-input)
-        j="$1"; shift 1
-        lockFlags+=("$i" "$j")
-        ;;
-      --override-input)
-        j="$1"; shift 1
-        k="$1"; shift 1
-        lockFlags+=("$i" "$j" "$k")
-        ;;
-      *)
-        echo "$0: unknown option \`$i'"
-        exit 1
-        ;;
-    esac
-done
-
-if [ -n "$SUDO_USER" ]; then
-    maybeSudo=(sudo --)
-fi
-
-if [ -z "$buildHost" -a -n "$targetHost" ]; then
-    buildHost="$targetHost"
-fi
-if [ "$targetHost" = localhost ]; then
-    targetHost=
-fi
-if [ "$buildHost" = localhost ]; then
-    buildHost=
-fi
-
-buildHostCmd() {
-    if [ -z "$buildHost" ]; then
-        "$@"
-    elif [ -n "$remoteNix" ]; then
-        ssh $SSHOPTS "$buildHost" env PATH="$remoteNix:$PATH" "${maybeSudo[@]}" "$@"
-    else
-        ssh $SSHOPTS "$buildHost" "${maybeSudo[@]}" "$@"
-    fi
-}
-
-targetHostCmd() {
-    if [ -z "$targetHost" ]; then
-        "${maybeSudo[@]}" "$@"
-    else
-        ssh $SSHOPTS "$targetHost" "${maybeSudo[@]}" "$@"
-    fi
-}
-
-copyToTarget() {
-    if ! [ "$targetHost" = "$buildHost" ]; then
-        if [ -z "$targetHost" ]; then
-            NIX_SSHOPTS=$SSHOPTS nix-copy-closure --from "$buildHost" "$1"
-        elif [ -z "$buildHost" ]; then
-            NIX_SSHOPTS=$SSHOPTS nix-copy-closure --to "$targetHost" "$1"
-        else
-            buildHostCmd nix-copy-closure --to "$targetHost" "$1"
-        fi
-    fi
-}
-
-nixBuild() {
-    if [ -z "$buildHost" ]; then
-        nix-build "$@"
-    else
-        local instArgs=()
-        local buildArgs=()
-
-        while [ "$#" -gt 0 ]; do
-            local i="$1"; shift 1
-            case "$i" in
-              -o)
-                local out="$1"; shift 1
-                buildArgs+=("--add-root" "$out" "--indirect")
-                ;;
-              -A)
-                local j="$1"; shift 1
-                instArgs+=("$i" "$j")
-                ;;
-              -I) # We don't want this in buildArgs
-                shift 1
-                ;;
-              --no-out-link) # We don't want this in buildArgs
-                ;;
-              "<"*) # nix paths
-                instArgs+=("$i")
-                ;;
-              *)
-                buildArgs+=("$i")
-                ;;
-            esac
-        done
-
-        local drv="$(nix-instantiate "${instArgs[@]}" "${extraBuildFlags[@]}")"
-        if [ -a "$drv" ]; then
-            NIX_SSHOPTS=$SSHOPTS nix-copy-closure --to "$buildHost" "$drv"
-            buildHostCmd nix-store -r "$drv" "${buildArgs[@]}"
-        else
-            echo "nix-instantiate failed"
-            exit 1
-        fi
-  fi
-}
-
-
-if [ -z "$action" ]; then showSyntax; fi
-
-# Only run shell scripts from the Nixpkgs tree if the action is
-# "switch", "boot", or "test". With other actions (such as "build"),
-# the user may reasonably expect that no code from the Nixpkgs tree is
-# executed, so it's safe to run nixos-rebuild against a potentially
-# untrusted tree.
-canRun=
-if [ "$action" = switch -o "$action" = boot -o "$action" = test ]; then
-    canRun=1
-fi
-
-
-# If ‘--upgrade’ or `--upgrade-all` is given,
-# run ‘nix-channel --update nixos’.
-if [[ -n $upgrade && -z $_NIXOS_REBUILD_REEXEC && -z $flake ]]; then
-    # If --upgrade-all is passed, or there are other channels that
-    # contain a file called ".update-on-nixos-rebuild", update them as
-    # well. Also upgrade the nixos channel.
-
-    for channelpath in /nix/var/nix/profiles/per-user/root/channels/*; do
-        channel_name=$(basename "$channelpath")
-
-        if [[ "$channel_name" == "nixos" ]]; then
-            nix-channel --update "$channel_name"
-        elif [ -e "$channelpath/.update-on-nixos-rebuild" ]; then
-            nix-channel --update "$channel_name"
-        elif [[ -n $upgrade_all ]] ; then
-            nix-channel --update "$channel_name"
-        fi
-    done
-fi
-
-# Make sure that we use the Nix package we depend on, not something
-# else from the PATH for nix-{env,instantiate,build}.  This is
-# important, because NixOS defaults the architecture of the rebuilt
-# system to the architecture of the nix-* binaries used.  So if on an
-# amd64 system the user has an i686 Nix package in her PATH, then we
-# would silently downgrade the whole system to be i686 NixOS on the
-# next reboot.
-if [ -z "$_NIXOS_REBUILD_REEXEC" ]; then
-    export PATH=@nix@/bin:$PATH
-fi
-
-# Use /etc/nixos/flake.nix if it exists. It can be a symlink to the
-# actual flake.
-if [[ -z $flake && -e /etc/nixos/flake.nix ]]; then
-    flake="$(dirname "$(readlink -f /etc/nixos/flake.nix)")"
-fi
-
-# Re-execute nixos-rebuild from the Nixpkgs tree.
-# FIXME: get nixos-rebuild from $flake.
-if [[ -z $_NIXOS_REBUILD_REEXEC && -n $canRun && -z $fast && -z $flake ]]; then
-    if p=$(nix-build --no-out-link --expr 'with import <nixpkgs/nixos> {}; config.system.build.nixos-rebuild' "${extraBuildFlags[@]}"); then
-        export _NIXOS_REBUILD_REEXEC=1
-        exec $p/bin/nixos-rebuild "${origArgs[@]}"
-        exit 1
-    fi
-fi
-
-# For convenience, use the hostname as the default configuration to
-# build from the flake.
-if [[ -n $flake ]]; then
-    if [[ $flake =~ ^(.*)\#([^\#\"]*)$ ]]; then
-       flake="${BASH_REMATCH[1]}"
-       flakeAttr="${BASH_REMATCH[2]}"
-    fi
-    if [[ -z $flakeAttr ]]; then
-        read -r hostname < /proc/sys/kernel/hostname
-        if [[ -z $hostname ]]; then
-            hostname=default
-        fi
-        flakeAttr="nixosConfigurations.\"$hostname\""
-    else
-        flakeAttr="nixosConfigurations.\"$flakeAttr\""
-    fi
-fi
-
-# Resolve the flake.
-if [[ -n $flake ]]; then
-    flake=$(nix "${flakeFlags[@]}" flake info --json "${extraBuildFlags[@]}" "${lockFlags[@]}" -- "$flake" | jq -r .url)
-fi
-
-# Find configuration.nix and open editor instead of building.
-if [ "$action" = edit ]; then
-    if [[ -z $flake ]]; then
-        NIXOS_CONFIG=${NIXOS_CONFIG:-$(nix-instantiate --find-file nixos-config)}
-        if [[ -d $NIXOS_CONFIG ]]; then
-            NIXOS_CONFIG=$NIXOS_CONFIG/default.nix
-        fi
-        exec ${EDITOR:-nano} "$NIXOS_CONFIG"
-    else
-        exec nix "${flakeFlags[@]}" edit "${lockFlags[@]}" -- "$flake#$flakeAttr"
-    fi
-    exit 1
-fi
-
-
-tmpDir=$(mktemp -t -d nixos-rebuild.XXXXXX)
-SSHOPTS="$NIX_SSHOPTS -o ControlMaster=auto -o ControlPath=$tmpDir/ssh-%n -o ControlPersist=60"
-
-cleanup() {
-    for ctrl in "$tmpDir"/ssh-*; do
-        ssh -o ControlPath="$ctrl" -O exit dummyhost 2>/dev/null || true
-    done
-    rm -rf "$tmpDir"
-}
-trap cleanup EXIT
-
-
-
-# If the Nix daemon is running, then use it.  This allows us to use
-# the latest Nix from Nixpkgs (below) for expression evaluation, while
-# still using the old Nix (via the daemon) for actual store access.
-# This matters if the new Nix in Nixpkgs has a schema change.  It
-# would upgrade the schema, which should only happen once we actually
-# switch to the new configuration.
-# If --repair is given, don't try to use the Nix daemon, because the
-# flag can only be used directly.
-if [ -z "$repair" ] && systemctl show nix-daemon.socket nix-daemon.service | grep -q ActiveState=active; then
-    export NIX_REMOTE=${NIX_REMOTE-daemon}
-fi
-
-
-# First build Nix, since NixOS may require a newer version than the
-# current one.
-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
-        echo @nix_x86_64_linux@
-    elif [[ "$machine" =~ i.86 ]]; then
-        echo @nix_i686_linux@
-    else
-        echo "$0: unsupported platform"
-        exit 1
-    fi
-}
-
-remotePATH=
-
-if [[ -n $buildNix && -z $flake ]]; then
-    echo "building Nix..." >&2
-    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
-            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
-            fi
-            # Older version of nix-store -r don't support --add-root.
-            [ -e $tmpDir/nix ] || ln -sf $nixStorePath $tmpDir/nix
-            if [ -n "$buildHost" ]; then
-                remoteNixStorePath="$(prebuiltNix "$(buildHostCmd uname -m)")"
-                remoteNix="$remoteNixStorePath/bin"
-                if ! buildHostCmd nix-store -r $remoteNixStorePath \
-                  --option extra-binary-caches https://cache.nixos.org/ >/dev/null; then
-                    remoteNix=
-                    echo "warning: don't know how to get latest Nix" >&2
-                fi
-            fi
-        fi
-    fi
-    if [ -a "$nixDrv" ]; then
-        nix-store -r "$nixDrv"'!'"out" --add-root $tmpDir/nix --indirect >/dev/null
-        if [ -n "$buildHost" ]; then
-            nix-copy-closure --to "$buildHost" "$nixDrv"
-            # The nix build produces multiple outputs, we add them all to the remote path
-            for p in $(buildHostCmd nix-store -r "$(readlink "$nixDrv")" "${buildArgs[@]}"); do
-                remoteNix="$remoteNix${remoteNix:+:}$p/bin"
-            done
-        fi
-    fi
-    PATH="$tmpDir/nix/bin:$PATH"
-fi
-
-
-# Update the version suffix if we're building from Git (so that
-# nixos-version shows something useful).
-if [[ -n $canRun && -z $flake ]]; then
-    if nixpkgs=$(nix-instantiate --find-file nixpkgs "${extraBuildFlags[@]}"); then
-        suffix=$($SHELL $nixpkgs/nixos/modules/installer/tools/get-version-suffix "${extraBuildFlags[@]}" || true)
-        if [ -n "$suffix" ]; then
-            echo -n "$suffix" > "$nixpkgs/.version-suffix" || true
-        fi
-    fi
-fi
-
-
-if [ "$action" = dry-build ]; then
-    extraBuildFlags+=(--dry-run)
-fi
-
-
-# Either upgrade the configuration in the system profile (for "switch"
-# or "boot"), or just build it and create a symlink "result" in the
-# current directory (for "build" and "test").
-if [ -z "$rollback" ]; then
-    echo "building the system configuration..." >&2
-    if [ "$action" = switch -o "$action" = boot ]; then
-        if [[ -z $flake ]]; then
-            pathToConfig="$(nixBuild '<nixpkgs/nixos>' --no-out-link -A system "${extraBuildFlags[@]}")"
-        else
-            outLink=$tmpDir/result
-            nix "${flakeFlags[@]}" build "$flake#$flakeAttr.config.system.build.toplevel" \
-              "${extraBuildFlags[@]}" "${lockFlags[@]}" --out-link $outLink
-            pathToConfig="$(readlink -f $outLink)"
-        fi
-        copyToTarget "$pathToConfig"
-        targetHostCmd nix-env -p "$profile" --set "$pathToConfig"
-    elif [ "$action" = test -o "$action" = build -o "$action" = dry-build -o "$action" = dry-activate ]; then
-        if [[ -z $flake ]]; then
-            pathToConfig="$(nixBuild '<nixpkgs/nixos>' -A system -k "${extraBuildFlags[@]}")"
-        else
-            nix "${flakeFlags[@]}" build "$flake#$flakeAttr.config.system.build.toplevel" "${extraBuildFlags[@]}" "${lockFlags[@]}"
-            pathToConfig="$(readlink -f ./result)"
-        fi
-    elif [ "$action" = build-vm ]; then
-        if [[ -z $flake ]]; then
-            pathToConfig="$(nixBuild '<nixpkgs/nixos>' -A vm -k "${extraBuildFlags[@]}")"
-        else
-            nix "${flakeFlags[@]}" build "$flake#$flakeAttr.config.system.build.vm" \
-              "${extraBuildFlags[@]}" "${lockFlags[@]}"
-            pathToConfig="$(readlink -f ./result)"
-        fi
-    elif [ "$action" = build-vm-with-bootloader ]; then
-        if [[ -z $flake ]]; then
-            pathToConfig="$(nixBuild '<nixpkgs/nixos>' -A vmWithBootLoader -k "${extraBuildFlags[@]}")"
-        else
-            nix "${flakeFlags[@]}" build "$flake#$flakeAttr.config.system.build.vmWithBootLoader" \
-              "${extraBuildFlags[@]}" "${lockFlags[@]}"
-            pathToConfig="$(readlink -f ./result)"
-        fi
-    else
-        showSyntax
-    fi
-    # Copy build to target host if we haven't already done it
-    if ! [ "$action" = switch -o "$action" = boot ]; then
-        copyToTarget "$pathToConfig"
-    fi
-else # [ -n "$rollback" ]
-    if [ "$action" = switch -o "$action" = boot ]; then
-        targetHostCmd nix-env --rollback -p "$profile"
-        pathToConfig="$profile"
-    elif [ "$action" = test -o "$action" = build ]; then
-        systemNumber=$(
-            targetHostCmd nix-env -p "$profile" --list-generations |
-            sed -n '/current/ {g; p;}; s/ *\([0-9]*\).*/\1/; h'
-        )
-        pathToConfig="$profile"-${systemNumber}-link
-        if [ -z "$targetHost" ]; then
-            ln -sT "$pathToConfig" ./result
-        fi
-    else
-        showSyntax
-    fi
-fi
-
-
-# If we're not just building, then make the new configuration the boot
-# default and/or activate it now.
-if [ "$action" = switch -o "$action" = boot -o "$action" = test -o "$action" = dry-activate ]; then
-    if ! targetHostCmd $pathToConfig/bin/switch-to-configuration "$action"; then
-        echo "warning: error(s) occurred while switching to the new configuration" >&2
-        exit 1
-    fi
-fi
-
-
-if [ "$action" = build-vm ]; then
-    cat >&2 <<EOF
-
-Done.  The virtual machine can be started by running $(echo $pathToConfig/bin/run-*-vm)
-EOF
-fi
diff --git a/nixpkgs/nixos/modules/installer/tools/tools.nix b/nixpkgs/nixos/modules/installer/tools/tools.nix
index 0582812f92d2..ada5f5748561 100644
--- a/nixpkgs/nixos/modules/installer/tools/tools.nix
+++ b/nixpkgs/nixos/modules/installer/tools/tools.nix
@@ -28,17 +28,7 @@ let
     ];
   };
 
-  nixos-rebuild =
-    let fallback = import ./nix-fallback-paths.nix; in
-    makeProg {
-      name = "nixos-rebuild";
-      src = ./nixos-rebuild.sh;
-      inherit (pkgs) runtimeShell;
-      nix = config.nix.package.out;
-      nix_x86_64_linux = fallback.x86_64-linux;
-      nix_i686_linux = fallback.i686-linux;
-      path = makeBinPath [ pkgs.jq ];
-    };
+  nixos-rebuild = pkgs.nixos-rebuild.override { nix = config.nix.package.out; };
 
   nixos-generate-config = makeProg {
     name = "nixos-generate-config";
diff --git a/nixpkgs/nixos/modules/misc/crashdump.nix b/nixpkgs/nixos/modules/misc/crashdump.nix
index 3c47e79d0512..11dec37b3fae 100644
--- a/nixpkgs/nixos/modules/misc/crashdump.nix
+++ b/nixpkgs/nixos/modules/misc/crashdump.nix
@@ -26,6 +26,7 @@ in
         };
         reservedMemory = mkOption {
           default = "128M";
+          type = types.str;
           description = ''
             The amount of memory reserved for the crashdump kernel.
             If you choose a too high value, dmesg will mention
diff --git a/nixpkgs/nixos/modules/misc/documentation.nix b/nixpkgs/nixos/modules/misc/documentation.nix
index fe0263f158f4..d81d6c6cb9b8 100644
--- a/nixpkgs/nixos/modules/misc/documentation.nix
+++ b/nixpkgs/nixos/modules/misc/documentation.nix
@@ -261,7 +261,7 @@ in
         ++ optionals cfg.doc.enable ([ manual.manualHTML nixos-help ]
            ++ optionals config.services.xserver.enable [ pkgs.nixos-icons ]);
 
-      services.mingetty.helpLine = mkIf cfg.doc.enable (
+      services.getty.helpLine = mkIf cfg.doc.enable (
           "\nRun 'nixos-help' for the NixOS manual."
       );
     })
diff --git a/nixpkgs/nixos/modules/misc/ids.nix b/nixpkgs/nixos/modules/misc/ids.nix
index fd9541062969..43779ef53fc9 100644
--- a/nixpkgs/nixos/modules/misc/ids.nix
+++ b/nixpkgs/nixos/modules/misc/ids.nix
@@ -143,7 +143,7 @@ in
       nix-ssh = 104;
       dictd = 105;
       couchdb = 106;
-      searx = 107;
+      #searx = 107; # dynamically allocated as of 2020-10-27
       kippo = 108;
       jenkins = 109;
       systemd-journal-gateway = 110;
@@ -457,7 +457,7 @@ in
       #nix-ssh = 104; # unused
       dictd = 105;
       couchdb = 106;
-      searx = 107;
+      #searx = 107; # dynamically allocated as of 2020-10-27
       kippo = 108;
       jenkins = 109;
       systemd-journal-gateway = 110;
diff --git a/nixpkgs/nixos/modules/misc/locate.nix b/nixpkgs/nixos/modules/misc/locate.nix
index 426281c94129..1d2bc8c72813 100644
--- a/nixpkgs/nixos/modules/misc/locate.nix
+++ b/nixpkgs/nixos/modules/misc/locate.nix
@@ -215,7 +215,7 @@ in {
           ''
           else ''
             exec ${cfg.locate}/bin/updatedb \
-              ${optionalString (cfg.localuser != null && ! isMLocate) ''--localuser=${cfg.localuser}''} \
+              ${optionalString (cfg.localuser != null && ! isMLocate) "--localuser=${cfg.localuser}"} \
               --output=${toString cfg.output} ${concatStringsSep " " cfg.extraFlags}
           '';
         environment = optionalAttrs (!isMLocate) {
diff --git a/nixpkgs/nixos/modules/misc/nixpkgs.nix b/nixpkgs/nixos/modules/misc/nixpkgs.nix
index 25ac94b8e0f6..8160bfef4a3c 100644
--- a/nixpkgs/nixos/modules/misc/nixpkgs.nix
+++ b/nixpkgs/nixos/modules/misc/nixpkgs.nix
@@ -73,7 +73,7 @@ in
           }
         '';
       type = pkgsType;
-      example = literalExample ''import <nixpkgs> {}'';
+      example = literalExample "import <nixpkgs> {}";
       description = ''
         If set, the pkgs argument to all NixOS modules is the value of
         this option, extended with <code>nixpkgs.overlays</code>, if
diff --git a/nixpkgs/nixos/modules/module-list.nix b/nixpkgs/nixos/modules/module-list.nix
index 5e9ee2b91ab2..cb06c0c027a2 100644
--- a/nixpkgs/nixos/modules/module-list.nix
+++ b/nixpkgs/nixos/modules/module-list.nix
@@ -82,6 +82,7 @@
   ./hardware/xpadneo.nix
   ./i18n/input-method/default.nix
   ./i18n/input-method/fcitx.nix
+  ./i18n/input-method/fcitx5.nix
   ./i18n/input-method/hime.nix
   ./i18n/input-method/ibus.nix
   ./i18n/input-method/nabi.nix
@@ -101,6 +102,7 @@
   ./misc/version.nix
   ./misc/nixops-autoluks.nix
   ./programs/adb.nix
+  ./programs/appgate-sdp.nix
   ./programs/atop.nix
   ./programs/autojump.nix
   ./programs/bandwhich.nix
@@ -167,6 +169,7 @@
   ./programs/sway.nix
   ./programs/system-config-printer.nix
   ./programs/thefuck.nix
+  ./programs/tilp2.nix
   ./programs/tmux.nix
   ./programs/traceroute.nix
   ./programs/tsm-client.nix
@@ -226,6 +229,7 @@
   ./services/audio/icecast.nix
   ./services/audio/liquidsoap.nix
   ./services/audio/mpd.nix
+  ./services/audio/mpdscribble.nix
   ./services/audio/mopidy.nix
   ./services/audio/roon-server.nix
   ./services/audio/slimserver.nix
@@ -494,6 +498,7 @@
   ./services/misc/nix-ssh-serve.nix
   ./services/misc/novacomd.nix
   ./services/misc/nzbget.nix
+  ./services/misc/nzbhydra2.nix
   ./services/misc/octoprint.nix
   ./services/misc/osrm.nix
   ./services/misc/packagekit.nix
@@ -631,6 +636,7 @@
   ./services/networking/dnsdist.nix
   ./services/networking/dnsmasq.nix
   ./services/networking/ncdns.nix
+  ./services/networking/nomad.nix
   ./services/networking/ejabberd.nix
   ./services/networking/epmd.nix
   ./services/networking/ergo.nix
@@ -854,7 +860,7 @@
   ./services/torrent/peerflix.nix
   ./services/torrent/rtorrent.nix
   ./services/torrent/transmission.nix
-  ./services/ttys/agetty.nix
+  ./services/ttys/getty.nix
   ./services/ttys/gpm.nix
   ./services/ttys/kmscon.nix
   ./services/wayland/cage.nix
@@ -898,6 +904,7 @@
   ./services/web-apps/selfoss.nix
   ./services/web-apps/shiori.nix
   ./services/web-apps/virtlyst.nix
+  ./services/web-apps/whitebophir.nix
   ./services/web-apps/wordpress.nix
   ./services/web-apps/youtrack.nix
   ./services/web-apps/zabbix.nix
@@ -953,6 +960,7 @@
   ./services/x11/urxvtd.nix
   ./services/x11/window-managers/awesome.nix
   ./services/x11/window-managers/default.nix
+  ./services/x11/window-managers/clfswm.nix
   ./services/x11/window-managers/fluxbox.nix
   ./services/x11/window-managers/icewm.nix
   ./services/x11/window-managers/bspwm.nix
diff --git a/nixpkgs/nixos/modules/profiles/all-hardware.nix b/nixpkgs/nixos/modules/profiles/all-hardware.nix
index 19f821ae17f3..d460c52dbefd 100644
--- a/nixpkgs/nixos/modules/profiles/all-hardware.nix
+++ b/nixpkgs/nixos/modules/profiles/all-hardware.nix
@@ -3,8 +3,10 @@
 # enabled in the initrd.  Its primary use is in the NixOS installation
 # CDs.
 
-{ ... }:
-
+{ pkgs, lib,... }:
+let
+  platform = pkgs.stdenv.hostPlatform;
+in
 {
 
   # The initrd has to contain any module that might be necessary for
@@ -42,7 +44,10 @@
       "virtio_net" "virtio_pci" "virtio_blk" "virtio_scsi" "virtio_balloon" "virtio_console"
 
       # VMware support.
-      "mptspi" "vmw_balloon" "vmwgfx" "vmw_vmci" "vmw_vsock_vmci_transport" "vmxnet3" "vsock"
+      "mptspi" "vmxnet3" "vsock"
+    ] ++ lib.optional platform.isx86 "vmw_balloon"
+    ++ lib.optionals (!platform.isAarch64) [ # not sure where else they're missing
+      "vmw_vmci" "vmwgfx" "vmw_vsock_vmci_transport"
 
       # Hyper-V support.
       "hv_storvsc"
diff --git a/nixpkgs/nixos/modules/profiles/installation-device.nix b/nixpkgs/nixos/modules/profiles/installation-device.nix
index e68ea1b08776..7dc493fb495d 100644
--- a/nixpkgs/nixos/modules/profiles/installation-device.nix
+++ b/nixpkgs/nixos/modules/profiles/installation-device.nix
@@ -45,10 +45,10 @@ with lib;
     };
 
     # Automatically log in at the virtual consoles.
-    services.mingetty.autologinUser = "nixos";
+    services.getty.autologinUser = "nixos";
 
     # Some more help text.
-    services.mingetty.helpLine = ''
+    services.getty.helpLine = ''
       The "nixos" and "root" accounts have empty passwords.
 
       An ssh daemon is running. You then must set a password
diff --git a/nixpkgs/nixos/modules/programs/appgate-sdp.nix b/nixpkgs/nixos/modules/programs/appgate-sdp.nix
new file mode 100644
index 000000000000..1dec4ecf9ecc
--- /dev/null
+++ b/nixpkgs/nixos/modules/programs/appgate-sdp.nix
@@ -0,0 +1,23 @@
+{ config, pkgs, lib, ... }:
+
+with lib;
+
+{
+  options = {
+    programs.appgate-sdp = {
+      enable = mkEnableOption
+        "AppGate SDP VPN client";
+    };
+  };
+
+  config = mkIf config.programs.appgate-sdp.enable {
+    boot.kernelModules = [ "tun" ];
+    environment.systemPackages = [ pkgs.appgate-sdp ];
+    services.dbus.packages = [ pkgs.appgate-sdp ];
+    systemd = {
+      packages = [ pkgs.appgate-sdp ];
+      # https://github.com/NixOS/nixpkgs/issues/81138
+      services.appgatedriver.wantedBy =  [ "multi-user.target" ];
+    };
+  };
+}
diff --git a/nixpkgs/nixos/modules/programs/captive-browser.nix b/nixpkgs/nixos/modules/programs/captive-browser.nix
index 26db16750727..4d59ea8d0fd8 100644
--- a/nixpkgs/nixos/modules/programs/captive-browser.nix
+++ b/nixpkgs/nixos/modules/programs/captive-browser.nix
@@ -27,14 +27,14 @@ in
       # the options below are the same as in "captive-browser.toml"
       browser = mkOption {
         type = types.str;
-        default = concatStringsSep " " [ ''${pkgs.chromium}/bin/chromium''
-                                         ''--user-data-dir=''${XDG_DATA_HOME:-$HOME/.local/share}/chromium-captive''
+        default = concatStringsSep " " [ "${pkgs.chromium}/bin/chromium"
+                                         "--user-data-dir=\${XDG_DATA_HOME:-$HOME/.local/share}/chromium-captive"
                                          ''--proxy-server="socks5://$PROXY"''
                                          ''--host-resolver-rules="MAP * ~NOTFOUND , EXCLUDE localhost"''
-                                         ''--no-first-run''
-                                         ''--new-window''
-                                         ''--incognito''
-                                         ''http://cache.nixos.org/''
+                                         "--no-first-run"
+                                         "--new-window"
+                                         "--incognito"
+                                         "http://cache.nixos.org/"
                                        ];
         description = ''
           The shell (/bin/sh) command executed once the proxy starts.
@@ -62,7 +62,7 @@ in
       socks5-addr = mkOption {
         type = types.str;
         default = "localhost:1666";
-        description = ''the listen address for the SOCKS5 proxy server'';
+        description = "the listen address for the SOCKS5 proxy server";
       };
 
       bindInterface = mkOption {
diff --git a/nixpkgs/nixos/modules/programs/command-not-found/command-not-found.nix b/nixpkgs/nixos/modules/programs/command-not-found/command-not-found.nix
index 656c255fcb18..d8394bf73a2e 100644
--- a/nixpkgs/nixos/modules/programs/command-not-found/command-not-found.nix
+++ b/nixpkgs/nixos/modules/programs/command-not-found/command-not-found.nix
@@ -80,6 +80,8 @@ in
             # Retry the command if we just installed it.
             if [ $? = 126 ]; then
               "$@"
+            else
+              return 127
             fi
           else
             # Indicate than there was an error so ZSH falls back to its default handler
diff --git a/nixpkgs/nixos/modules/programs/fish.nix b/nixpkgs/nixos/modules/programs/fish.nix
index 50d1077dd410..392f06eb9332 100644
--- a/nixpkgs/nixos/modules/programs/fish.nix
+++ b/nixpkgs/nixos/modules/programs/fish.nix
@@ -13,6 +13,27 @@ let
       (filterAttrs (k: v: v != null) cfg.shellAliases)
   );
 
+  envShellInit = pkgs.writeText "shellInit" cfge.shellInit;
+
+  envLoginShellInit = pkgs.writeText "loginShellInit" cfge.loginShellInit;
+
+  envInteractiveShellInit = pkgs.writeText "interactiveShellInit" cfge.interactiveShellInit;
+
+  sourceEnv = file:
+  if cfg.useBabelfish then
+    "source /etc/fish/${file}.fish"
+  else
+    ''
+      set fish_function_path ${pkgs.fishPlugins.foreign-env}/share/fish/vendor_functions.d $fish_function_path
+      fenv source /etc/fish/foreign-env/${file} > /dev/null
+      set -e fish_function_path[1]
+    '';
+
+  babelfishTranslate = path: name:
+    pkgs.runCommand "${name}.fish" {
+      nativeBuildInputs = [ pkgs.babelfish ];
+    } "${pkgs.babelfish}/bin/babelfish < ${path} > $out;";
+
 in
 
 {
@@ -29,6 +50,15 @@ in
         type = types.bool;
       };
 
+      useBabelfish = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          If enabled, the configured environment will be translated to native fish using <link xlink:href="https://github.com/bouk/babelfish">babelfish</link>.
+          Otherwise, <link xlink:href="https://github.com/oh-my-fish/plugin-foreign-env">foreign-env</link> will be used.
+        '';
+      };
+
       vendor.config.enable = mkOption {
         type = types.bool;
         default = true;
@@ -105,72 +135,152 @@ in
     # Required for man completions
     documentation.man.generateCaches = lib.mkDefault true;
 
-    environment.etc."fish/foreign-env/shellInit".text = cfge.shellInit;
-    environment.etc."fish/foreign-env/loginShellInit".text = cfge.loginShellInit;
-    environment.etc."fish/foreign-env/interactiveShellInit".text = cfge.interactiveShellInit;
-
-    environment.etc."fish/nixos-env-preinit.fish".text = ''
-      # This happens before $__fish_datadir/config.fish sets fish_function_path, so it is currently
-      # unset. We set it and then completely erase it, leaving its configuration to $__fish_datadir/config.fish
-      set fish_function_path ${pkgs.fish-foreign-env}/share/fish-foreign-env/functions $__fish_datadir/functions
-
-      # source the NixOS environment config
-      if [ -z "$__NIXOS_SET_ENVIRONMENT_DONE" ]
-          fenv source ${config.system.build.setEnvironment}
-      end
-
-      # clear fish_function_path so that it will be correctly set when we return to $__fish_datadir/config.fish
-      set -e fish_function_path
-    '';
-
-    environment.etc."fish/config.fish".text = ''
-      # /etc/fish/config.fish: DO NOT EDIT -- this file has been generated automatically.
-
-      # if we haven't sourced the general config, do it
-      if not set -q __fish_nixos_general_config_sourced
-        set fish_function_path ${pkgs.fish-foreign-env}/share/fish-foreign-env/functions $fish_function_path
-        fenv source /etc/fish/foreign-env/shellInit > /dev/null
-        set -e fish_function_path[1]
-
-        ${cfg.shellInit}
-
-        # and leave a note so we don't source this config section again from
-        # this very shell (children will source the general config anew)
-        set -g __fish_nixos_general_config_sourced 1
-      end
-
-      # if we haven't sourced the login config, do it
-      status --is-login; and not set -q __fish_nixos_login_config_sourced
-      and begin
-        set fish_function_path ${pkgs.fish-foreign-env}/share/fish-foreign-env/functions $fish_function_path
-        fenv source /etc/fish/foreign-env/loginShellInit > /dev/null
-        set -e fish_function_path[1]
-
-        ${cfg.loginShellInit}
-
-        # and leave a note so we don't source this config section again from
-        # this very shell (children will source the general config anew)
-        set -g __fish_nixos_login_config_sourced 1
-      end
-
-      # if we haven't sourced the interactive config, do it
-      status --is-interactive; and not set -q __fish_nixos_interactive_config_sourced
-      and begin
-        ${fishAliases}
-
-        set fish_function_path ${pkgs.fish-foreign-env}/share/fish-foreign-env/functions $fish_function_path
-        fenv source /etc/fish/foreign-env/interactiveShellInit > /dev/null
-        set -e fish_function_path[1]
-
-        ${cfg.promptInit}
-        ${cfg.interactiveShellInit}
-
-        # and leave a note so we don't source this config section again from
-        # this very shell (children will source the general config anew,
-        # allowing configuration changes in, e.g, aliases, to propagate)
-        set -g __fish_nixos_interactive_config_sourced 1
-      end
-    '';
+    environment = mkMerge [
+      (mkIf cfg.useBabelfish
+      {
+        etc."fish/setEnvironment.fish".source = babelfishTranslate config.system.build.setEnvironment "setEnvironment";
+        etc."fish/shellInit.fish".source = babelfishTranslate envShellInit "shellInit";
+        etc."fish/loginShellInit.fish".source = babelfishTranslate envLoginShellInit "loginShellInit";
+        etc."fish/interactiveShellInit.fish".source = babelfishTranslate envInteractiveShellInit "interactiveShellInit";
+     })
+
+      (mkIf (!cfg.useBabelfish)
+      {
+        etc."fish/foreign-env/shellInit".source = envShellInit;
+        etc."fish/foreign-env/loginShellInit".source = envLoginShellInit;
+        etc."fish/foreign-env/interactiveShellInit".source = envInteractiveShellInit;
+      })
+
+      {
+        etc."fish/nixos-env-preinit.fish".text =
+        if cfg.useBabelfish
+        then ''
+          # source the NixOS environment config
+          if [ -z "$__NIXOS_SET_ENVIRONMENT_DONE" ]
+            source /etc/fish/setEnvironment.fish
+          end
+        ''
+        else ''
+          # This happens before $__fish_datadir/config.fish sets fish_function_path, so it is currently
+          # unset. We set it and then completely erase it, leaving its configuration to $__fish_datadir/config.fish
+          set fish_function_path ${pkgs.fishPlugins.foreign-env}/share/fish/vendor_functions.d $__fish_datadir/functions
+
+          # source the NixOS environment config
+          if [ -z "$__NIXOS_SET_ENVIRONMENT_DONE" ]
+            fenv source ${config.system.build.setEnvironment}
+          end
+
+          # clear fish_function_path so that it will be correctly set when we return to $__fish_datadir/config.fish
+          set -e fish_function_path
+        '';
+      }
+
+      {
+        etc."fish/config.fish".text = ''
+        # /etc/fish/config.fish: DO NOT EDIT -- this file has been generated automatically.
+
+        # if we haven't sourced the general config, do it
+        if not set -q __fish_nixos_general_config_sourced
+          ${sourceEnv "shellInit"}
+
+          ${cfg.shellInit}
+
+          # and leave a note so we don't source this config section again from
+          # this very shell (children will source the general config anew)
+          set -g __fish_nixos_general_config_sourced 1
+        end
+
+        # if we haven't sourced the login config, do it
+        status --is-login; and not set -q __fish_nixos_login_config_sourced
+        and begin
+          ${sourceEnv "loginShellInit"}
+
+          ${cfg.loginShellInit}
+
+          # and leave a note so we don't source this config section again from
+          # this very shell (children will source the general config anew)
+          set -g __fish_nixos_login_config_sourced 1
+        end
+
+        # if we haven't sourced the interactive config, do it
+        status --is-interactive; and not set -q __fish_nixos_interactive_config_sourced
+        and begin
+          ${fishAliases}
+
+          ${sourceEnv "interactiveShellInit"}
+
+          ${cfg.promptInit}
+          ${cfg.interactiveShellInit}
+
+          # and leave a note so we don't source this config section again from
+          # this very shell (children will source the general config anew,
+          # allowing configuration changes in, e.g, aliases, to propagate)
+          set -g __fish_nixos_interactive_config_sourced 1
+        end
+      '';
+      }
+
+      {
+        etc."fish/generated_completions".source =
+        let
+          patchedGenerator = pkgs.stdenv.mkDerivation {
+            name = "fish_patched-completion-generator";
+            srcs = [
+              "${pkgs.fish}/share/fish/tools/create_manpage_completions.py"
+              "${pkgs.fish}/share/fish/tools/deroff.py"
+            ];
+            unpackCmd = "cp $curSrc $(basename $curSrc)";
+            sourceRoot = ".";
+            patches = [ ./fish_completion-generator.patch ]; # to prevent collisions of identical completion files
+            dontBuild = true;
+            installPhase = ''
+              mkdir -p $out
+              cp * $out/
+            '';
+            preferLocalBuild = true;
+            allowSubstitutes = false;
+          };
+          generateCompletions = package: pkgs.runCommand
+            "${package.name}_fish-completions"
+            (
+              {
+                inherit package;
+                preferLocalBuild = true;
+                allowSubstitutes = false;
+              }
+              // optionalAttrs (package ? meta.priority) { meta.priority = package.meta.priority; }
+            )
+            ''
+              mkdir -p $out
+              if [ -d $package/share/man ]; then
+                find $package/share/man -type f | xargs ${pkgs.python3.interpreter} ${patchedGenerator}/create_manpage_completions.py --directory $out >/dev/null
+              fi
+            '';
+        in
+          pkgs.buildEnv {
+            name = "system_fish-completions";
+            ignoreCollisions = true;
+            paths = map generateCompletions config.environment.systemPackages;
+          };
+      }
+
+      # include programs that bring their own completions
+      {
+        pathsToLink = []
+        ++ optional cfg.vendor.config.enable "/share/fish/vendor_conf.d"
+        ++ optional cfg.vendor.completions.enable "/share/fish/vendor_completions.d"
+        ++ optional cfg.vendor.functions.enable "/share/fish/vendor_functions.d";
+      }
+
+      { systemPackages = [ pkgs.fish ]; }
+
+      {
+        shells = [
+          "/run/current-system/sw/bin/fish"
+          "${pkgs.fish}/bin/fish"
+        ];
+      }
+    ];
 
     programs.fish.interactiveShellInit = ''
       # add completions generated by NixOS to $fish_complete_path
@@ -187,61 +297,6 @@ in
       end
     '';
 
-    environment.etc."fish/generated_completions".source =
-      let
-        patchedGenerator = pkgs.stdenv.mkDerivation {
-          name = "fish_patched-completion-generator";
-          srcs = [
-            "${pkgs.fish}/share/fish/tools/create_manpage_completions.py"
-            "${pkgs.fish}/share/fish/tools/deroff.py"
-          ];
-          unpackCmd = "cp $curSrc $(basename $curSrc)";
-          sourceRoot = ".";
-          patches = [ ./fish_completion-generator.patch ]; # to prevent collisions of identical completion files
-          dontBuild = true;
-          installPhase = ''
-            mkdir -p $out
-            cp * $out/
-          '';
-          preferLocalBuild = true;
-          allowSubstitutes = false;
-        };
-        generateCompletions = package: pkgs.runCommand
-          "${package.name}_fish-completions"
-          (
-            {
-              inherit package;
-              preferLocalBuild = true;
-              allowSubstitutes = false;
-            }
-            // optionalAttrs (package ? meta.priority) { meta.priority = package.meta.priority; }
-          )
-          ''
-            mkdir -p $out
-            if [ -d $package/share/man ]; then
-              find $package/share/man -type f | xargs ${pkgs.python3.interpreter} ${patchedGenerator}/create_manpage_completions.py --directory $out >/dev/null
-            fi
-          '';
-      in
-        pkgs.buildEnv {
-          name = "system_fish-completions";
-          ignoreCollisions = true;
-          paths = map generateCompletions config.environment.systemPackages;
-        };
-
-    # include programs that bring their own completions
-    environment.pathsToLink = []
-      ++ optional cfg.vendor.config.enable "/share/fish/vendor_conf.d"
-      ++ optional cfg.vendor.completions.enable "/share/fish/vendor_completions.d"
-      ++ optional cfg.vendor.functions.enable "/share/fish/vendor_functions.d";
-
-    environment.systemPackages = [ pkgs.fish ];
-
-    environment.shells = [
-      "/run/current-system/sw/bin/fish"
-      "${pkgs.fish}/bin/fish"
-    ];
-
   };
 
 }
diff --git a/nixpkgs/nixos/modules/programs/ssh.nix b/nixpkgs/nixos/modules/programs/ssh.nix
index 40af4d0ff5ae..d4a7769bbd6d 100644
--- a/nixpkgs/nixos/modules/programs/ssh.nix
+++ b/nixpkgs/nixos/modules/programs/ssh.nix
@@ -36,7 +36,7 @@ in
       askPassword = mkOption {
         type = types.str;
         default = "${pkgs.x11_ssh_askpass}/libexec/x11-ssh-askpass";
-        description = ''Program used by SSH to ask for passwords.'';
+        description = "Program used by SSH to ask for passwords.";
       };
 
       forwardX11 = mkOption {
diff --git a/nixpkgs/nixos/modules/programs/tilp2.nix b/nixpkgs/nixos/modules/programs/tilp2.nix
new file mode 100644
index 000000000000..da9e32e3e6c6
--- /dev/null
+++ b/nixpkgs/nixos/modules/programs/tilp2.nix
@@ -0,0 +1,28 @@
+{ config, pkgs, lib, ... }:
+
+with lib;
+
+let
+  cfg = config.programs.tilp2;
+
+in {
+  options.programs.tilp2 = {
+    enable = mkOption {
+      type = types.bool;
+      default = false;
+      description = ''
+        Enable tilp2 and udev rules for supported calculators.
+      '';
+    };
+  };
+
+  config = mkIf cfg.enable {
+    services.udev.packages = [
+      pkgs.libticables2
+    ];
+
+    environment.systemPackages = [
+      pkgs.tilp2
+    ];
+  };
+}
diff --git a/nixpkgs/nixos/modules/programs/xss-lock.nix b/nixpkgs/nixos/modules/programs/xss-lock.nix
index 83ed71386407..ceb7259b3d77 100644
--- a/nixpkgs/nixos/modules/programs/xss-lock.nix
+++ b/nixpkgs/nixos/modules/programs/xss-lock.nix
@@ -11,7 +11,7 @@ in
 
     lockerCommand = mkOption {
       default = "${pkgs.i3lock}/bin/i3lock";
-      example = literalExample ''''${pkgs.i3lock-fancy}/bin/i3lock-fancy'';
+      example = literalExample "\${pkgs.i3lock-fancy}/bin/i3lock-fancy";
       type = types.separatedString " ";
       description = "Locker to be used with xsslock";
     };
diff --git a/nixpkgs/nixos/modules/security/pam.nix b/nixpkgs/nixos/modules/security/pam.nix
index 1522111dbddf..103cf2050123 100644
--- a/nixpkgs/nixos/modules/security/pam.nix
+++ b/nixpkgs/nixos/modules/security/pam.nix
@@ -430,8 +430,8 @@ let
               ${optionalString cfg.pamMount
                 "auth optional ${pkgs.pam_mount}/lib/security/pam_mount.so"}
               ${optionalString cfg.enableKwallet
-                ("auth optional ${pkgs.plasma5.kwallet-pam}/lib/security/pam_kwallet5.so" +
-                 " kwalletd=${pkgs.kdeFrameworks.kwallet.bin}/bin/kwalletd5")}
+                ("auth optional ${pkgs.plasma5Packages.kwallet-pam}/lib/security/pam_kwallet5.so" +
+                 " kwalletd=${pkgs.plasma5Packages.kwallet.bin}/bin/kwalletd5")}
               ${optionalString cfg.enableGnomeKeyring
                 "auth optional ${pkgs.gnome3.gnome-keyring}/lib/security/pam_gnome_keyring.so"}
               ${optionalString cfg.gnupg.enable
@@ -509,8 +509,8 @@ let
           ${optionalString (cfg.enableAppArmor && config.security.apparmor.enable)
               "session optional ${pkgs.apparmor-pam}/lib/security/pam_apparmor.so order=user,group,default debug"}
           ${optionalString (cfg.enableKwallet)
-              ("session optional ${pkgs.plasma5.kwallet-pam}/lib/security/pam_kwallet5.so" +
-               " kwalletd=${pkgs.kdeFrameworks.kwallet.bin}/bin/kwalletd5")}
+              ("session optional ${pkgs.plasma5Packages.kwallet-pam}/lib/security/pam_kwallet5.so" +
+               " kwalletd=${pkgs.plasma5Packages.kwallet.bin}/bin/kwalletd5")}
           ${optionalString (cfg.enableGnomeKeyring)
               "session optional ${pkgs.gnome3.gnome-keyring}/lib/security/pam_gnome_keyring.so auto_start"}
           ${optionalString cfg.gnupg.enable
diff --git a/nixpkgs/nixos/modules/services/amqp/activemq/default.nix b/nixpkgs/nixos/modules/services/amqp/activemq/default.nix
index 160dbddcd487..178b2f6e144b 100644
--- a/nixpkgs/nixos/modules/services/amqp/activemq/default.nix
+++ b/nixpkgs/nixos/modules/services/amqp/activemq/default.nix
@@ -33,6 +33,7 @@ in {
       };
       configurationDir = mkOption {
         default = "${activemq}/conf";
+        type = types.str;
         description = ''
           The base directory for ActiveMQ's configuration.
           By default, this directory is searched for a file named activemq.xml,
diff --git a/nixpkgs/nixos/modules/services/audio/mpd.nix b/nixpkgs/nixos/modules/services/audio/mpd.nix
index e09e4861646c..9f01e29dd0e9 100644
--- a/nixpkgs/nixos/modules/services/audio/mpd.nix
+++ b/nixpkgs/nixos/modules/services/audio/mpd.nix
@@ -10,6 +10,14 @@ let
   gid = config.ids.gids.mpd;
   cfg = config.services.mpd;
 
+  credentialsPlaceholder = (creds:
+    let
+      placeholders = (imap0
+        (i: c: ''password "{{password-${toString i}}}@${concatStringsSep "," c.permissions}"'')
+        creds);
+    in
+      concatStringsSep "\n" placeholders);
+
   mpdConf = pkgs.writeText "mpd.conf" ''
     # This file was automatically generated by NixOS. Edit mpd's configuration
     # via NixOS' configuration.nix, as this file will be rewritten upon mpd's
@@ -32,6 +40,8 @@ let
       }
     ''}
 
+    ${optionalString (cfg.credentials != []) (credentialsPlaceholder cfg.credentials)}
+
     ${cfg.extraConfig}
   '';
 
@@ -64,7 +74,7 @@ in {
       musicDirectory = mkOption {
         type = with types; either path (strMatching "(http|https|nfs|smb)://.+");
         default = "${cfg.dataDir}/music";
-        defaultText = ''''${dataDir}/music'';
+        defaultText = "\${dataDir}/music";
         description = ''
           The directory or NFS/SMB network share where MPD reads music from. If left
           as the default value this directory will automatically be created before
@@ -76,7 +86,7 @@ in {
       playlistDirectory = mkOption {
         type = types.path;
         default = "${cfg.dataDir}/playlists";
-        defaultText = ''''${dataDir}/playlists'';
+        defaultText = "\${dataDir}/playlists";
         description = ''
           The directory where MPD stores playlists. If left as the default value
           this directory will automatically be created before the MPD server starts,
@@ -145,23 +155,42 @@ in {
       dbFile = mkOption {
         type = types.nullOr types.str;
         default = "${cfg.dataDir}/tag_cache";
-        defaultText = ''''${dataDir}/tag_cache'';
+        defaultText = "\${dataDir}/tag_cache";
         description = ''
           The path to MPD's database. If set to <literal>null</literal> the
           parameter is omitted from the configuration.
         '';
       };
 
-      credentialsFile = mkOption {
-        type = types.path;
+      credentials = mkOption {
+        type = types.listOf (types.submodule {
+          options = {
+            passwordFile = mkOption {
+              type = types.path;
+              description = ''
+                Path to file containing the password.
+              '';
+            };
+            permissions = let
+              perms = ["read" "add" "control" "admin"];
+            in mkOption {
+              type = types.listOf (types.enum perms);
+              default = [ "read" ];
+              description = ''
+                List of permissions that are granted with this password.
+                Permissions can be "${concatStringsSep "\", \"" perms}".
+              '';
+            };
+          };
+        });
         description = ''
-          Path to a file to be merged with the settings during the service startup.
-          Useful to merge a file which is better kept out of the Nix store
-          because it contains sensible data like MPD's password. Example may look like this:
-          <literal>password "myMpdPassword@read,add,control,admin"</literal>
+          Credentials and permissions for accessing the mpd server.
         '';
-        default = "/dev/null";
-        example = "/var/lib/secrets/mpd.conf";
+        default = [];
+        example = [
+          {passwordFile = "/var/lib/secrets/mpd_readonly_password"; permissions = [ "read" ];}
+          {passwordFile = "/var/lib/secrets/mpd_admin_password"; permissions = ["read" "add" "control" "admin"];}
+        ];
       };
 
       fluidsynth = mkOption {
@@ -201,12 +230,16 @@ in {
       serviceConfig = mkMerge [
         {
           User = "${cfg.user}";
-          ExecStart = "${pkgs.mpd}/bin/mpd --no-daemon /etc/mpd.conf";
-          ExecStartPre = pkgs.writeScript "mpd-start-pre" ''
-            #!${pkgs.runtimeShell}
+          ExecStart = "${pkgs.mpd}/bin/mpd --no-daemon /run/mpd/mpd.conf";
+          ExecStartPre = pkgs.writeShellScript "mpd-start-pre" ''
             set -euo pipefail
-            cat ${mpdConf} ${cfg.credentialsFile} > /etc/mpd.conf
+            install -m 600 ${mpdConf} /run/mpd/mpd.conf
+            ${optionalString (cfg.credentials != [])
+            "${pkgs.replace}/bin/replace-literal -fe ${
+              concatStringsSep " -a " (imap0 (i: c: "\"{{password-${toString i}}}\" \"$(cat ${c.passwordFile})\"") cfg.credentials)
+            } /run/mpd/mpd.conf"}
           '';
+          RuntimeDirectory = "mpd";
           Type = "notify";
           LimitRTPRIO = 50;
           LimitRTTIME = "infinity";
@@ -230,14 +263,6 @@ in {
         })
       ];
     };
-    environment.etc."mpd.conf" = {
-      mode = "0640";
-      group = cfg.group;
-      user = cfg.user;
-      # To be modified by the service' ExecStartPre
-      text = ''
-      '';
-    };
 
     users.users = optionalAttrs (cfg.user == name) {
       ${name} = {
diff --git a/nixpkgs/nixos/modules/services/audio/mpdscribble.nix b/nixpkgs/nixos/modules/services/audio/mpdscribble.nix
new file mode 100644
index 000000000000..642d8743935f
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/audio/mpdscribble.nix
@@ -0,0 +1,202 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.services.mpdscribble;
+  mpdCfg = config.services.mpd;
+
+  endpointUrls = {
+    "last.fm" = "http://post.audioscrobbler.com";
+    "libre.fm" = "http://turtle.libre.fm";
+    "jamendo" = "http://postaudioscrobbler.jamendo.com";
+    "listenbrainz" = "http://proxy.listenbrainz.org";
+  };
+
+  mkSection = secname: secCfg: ''
+    [${secname}]
+    url      = ${secCfg.url}
+    username = ${secCfg.username}
+    password = {{${secname}_PASSWORD}}
+    journal  = /var/lib/mpdscribble/${secname}.journal
+  '';
+
+  endpoints = concatStringsSep "\n" (mapAttrsToList mkSection cfg.endpoints);
+  cfgTemplate = pkgs.writeText "mpdscribble.conf" ''
+    ## This file was automatically genenrated by NixOS and will be overwritten.
+    ## Do not edit. Edit your NixOS configuration instead.
+
+    ## mpdscribble - an audioscrobbler for the Music Player Daemon.
+    ## http://mpd.wikia.com/wiki/Client:mpdscribble
+
+    # HTTP proxy URL.
+    ${optionalString (cfg.proxy != null) "proxy = ${cfg.proxy}"}
+
+    # The location of the mpdscribble log file.  The special value
+    # "syslog" makes mpdscribble use the local syslog daemon.  On most
+    # systems, log messages will appear in /var/log/daemon.log then.
+    # "-" means log to stderr (the current terminal).
+    log = -
+
+    # How verbose mpdscribble's logging should be.  Default is 1.
+    verbose = ${toString cfg.verbose}
+
+    # How often should mpdscribble save the journal file? [seconds]
+    journal_interval = ${toString cfg.journalInterval}
+
+    # The host running MPD, possibly protected by a password
+    # ([PASSWORD@]HOSTNAME).
+    host = ${(optionalString (cfg.passwordFile != null) "{{MPD_PASSWORD}}@") + cfg.host}
+
+    # The port that the MPD listens on and mpdscribble should try to
+    # connect to.
+    port = ${toString cfg.port}
+
+    ${endpoints}
+  '';
+
+  cfgFile = "/run/mpdscribble/mpdscribble.conf";
+
+  replaceSecret = secretFile: placeholder: targetFile:
+    optionalString (secretFile != null) ''
+      ${pkgs.replace}/bin/replace-literal -ef ${placeholder} "$(cat ${secretFile})" ${targetFile}'';
+
+  preStart = pkgs.writeShellScript "mpdscribble-pre-start" ''
+    cp -f "${cfgTemplate}" "${cfgFile}"
+    ${replaceSecret cfg.passwordFile "{{MPD_PASSWORD}}" cfgFile}
+    ${concatStringsSep "\n" (mapAttrsToList (secname: cfg:
+      replaceSecret cfg.passwordFile "{{${secname}_PASSWORD}}" cfgFile)
+      cfg.endpoints)}
+  '';
+
+  localMpd = (cfg.host == "localhost" || cfg.host == "127.0.0.1");
+
+in {
+  ###### interface
+
+  options.services.mpdscribble = {
+
+    enable = mkEnableOption "mpdscribble";
+
+    proxy = mkOption {
+      default = null;
+      type = types.nullOr types.str;
+      description = ''
+        HTTP proxy URL.
+      '';
+    };
+
+    verbose = mkOption {
+      default = 1;
+      type = types.int;
+      description = ''
+        Log level for the mpdscribble daemon.
+      '';
+    };
+
+    journalInterval = mkOption {
+      default = 600;
+      example = 60;
+      type = types.int;
+      description = ''
+        How often should mpdscribble save the journal file? [seconds]
+      '';
+    };
+
+    host = mkOption {
+      default = (if mpdCfg.network.listenAddress != "any" then
+        mpdCfg.network.listenAddress
+      else
+        "localhost");
+      type = types.str;
+      description = ''
+        Host for the mpdscribble daemon to search for a mpd daemon on.
+      '';
+    };
+
+    passwordFile = mkOption {
+      default = if localMpd then
+        (findFirst
+          (c: any (x: x == "read") c.permissions)
+          { passwordFile = null; }
+          mpdCfg.credentials).passwordFile
+      else
+        null;
+      type = types.nullOr types.str;
+      description = ''
+        File containing the password for the mpd daemon.
+        If there is a local mpd configured using <option>services.mpd.credentials</option>
+        the default is automatically set to a matching passwordFile of the local mpd.
+      '';
+    };
+
+    port = mkOption {
+      default = mpdCfg.network.port;
+      type = types.port;
+      description = ''
+        Port for the mpdscribble daemon to search for a mpd daemon on.
+      '';
+    };
+
+    endpoints = mkOption {
+      type = (let
+        endpoint = { name, ... }: {
+          options = {
+            url = mkOption {
+              type = types.str;
+              default = endpointUrls.${name} or "";
+              description =
+                "The url endpoint where the scrobble API is listening.";
+            };
+            username = mkOption {
+              type = types.str;
+              description = ''
+                Username for the scrobble service.
+              '';
+            };
+            passwordFile = mkOption {
+              type = types.nullOr types.str;
+              description =
+                "File containing the password, either as MD5SUM or cleartext.";
+            };
+          };
+        };
+      in types.attrsOf (types.submodule endpoint));
+      default = { };
+      example = {
+        "last.fm" = {
+          username = "foo";
+          passwordFile = "/run/secrets/lastfm_password";
+        };
+      };
+      description = ''
+        Endpoints to scrobble to.
+        If the endpoint is one of "${
+          concatStringsSep "\", \"" (attrNames endpointUrls)
+        }" the url is set automatically.
+      '';
+    };
+
+  };
+
+  ###### implementation
+
+  config = mkIf cfg.enable {
+    systemd.services.mpdscribble = {
+      after = [ "network.target" ] ++ (optional localMpd "mpd.service");
+      description = "mpdscribble mpd scrobble client";
+      wantedBy = [ "multi-user.target" ];
+      serviceConfig = {
+        DynamicUser = true;
+        StateDirectory = "mpdscribble";
+        RuntimeDirectory = "mpdscribble";
+        RuntimeDirectoryMode = "700";
+        # TODO use LoadCredential= instead of running preStart with full privileges?
+        ExecStartPre = "+${preStart}";
+        ExecStart =
+          "${pkgs.mpdscribble}/bin/mpdscribble --no-daemon --conf ${cfgFile}";
+      };
+    };
+  };
+
+}
diff --git a/nixpkgs/nixos/modules/services/backup/bacula.nix b/nixpkgs/nixos/modules/services/backup/bacula.nix
index 3d69a69038a3..b485602aab8c 100644
--- a/nixpkgs/nixos/modules/services/backup/bacula.nix
+++ b/nixpkgs/nixos/modules/services/backup/bacula.nix
@@ -190,8 +190,7 @@ let
       };
 
       devices = mkOption {
-        description = ''
-        '';
+        description = "";
       };
 
       extraAutochangerConfig = mkOption {
diff --git a/nixpkgs/nixos/modules/services/backup/tarsnap.nix b/nixpkgs/nixos/modules/services/backup/tarsnap.nix
index e1200731c2ca..8187042b4b80 100644
--- a/nixpkgs/nixos/modules/services/backup/tarsnap.nix
+++ b/nixpkgs/nixos/modules/services/backup/tarsnap.nix
@@ -29,13 +29,7 @@ in
 
   options = {
     services.tarsnap = {
-      enable = mkOption {
-        type = types.bool;
-        default = false;
-        description = ''
-          Enable periodic tarsnap backups.
-        '';
-      };
+      enable = mkEnableOption "periodic tarsnap backups";
 
       keyfile = mkOption {
         type = types.str;
@@ -279,7 +273,8 @@ in
           Tarsnap archive configurations. Each attribute names an archive
           to be created at a given time interval, according to the options
           associated with it. When uploading to the tarsnap server,
-          archive names are suffixed by a 1 second resolution timestamp.
+          archive names are suffixed by a 1 second resolution timestamp,
+          with the format <literal>%Y%m%d%H%M%S</literal>.
 
           For each member of the set is created a timer which triggers the
           instanced <literal>tarsnap-archive-name</literal> service unit. You may use
@@ -359,7 +354,7 @@ in
 
         script = let
           tarsnap = ''tarsnap --configfile "/etc/tarsnap/${name}.conf"'';
-          lastArchive = ''$(${tarsnap} --list-archives | sort | tail -1)'';
+          lastArchive = "$(${tarsnap} --list-archives | sort | tail -1)";
           run = ''${tarsnap} -x -f "${lastArchive}" ${optionalString cfg.verbose "-v"}'';
 
         in if (cfg.cachedir != null) then ''
diff --git a/nixpkgs/nixos/modules/services/cluster/hadoop/default.nix b/nixpkgs/nixos/modules/services/cluster/hadoop/default.nix
index bfb73f683715..171d4aced651 100644
--- a/nixpkgs/nixos/modules/services/cluster/hadoop/default.nix
+++ b/nixpkgs/nixos/modules/services/cluster/hadoop/default.nix
@@ -50,8 +50,7 @@ with lib;
       default = pkgs.hadoop;
       defaultText = "pkgs.hadoop";
       example = literalExample "pkgs.hadoop";
-      description = ''
-      '';
+      description = "";
     };
   };
 
diff --git a/nixpkgs/nixos/modules/services/computing/slurm/slurm.nix b/nixpkgs/nixos/modules/services/computing/slurm/slurm.nix
index 302f058926c8..7363441e5387 100644
--- a/nixpkgs/nixos/modules/services/computing/slurm/slurm.nix
+++ b/nixpkgs/nixos/modules/services/computing/slurm/slurm.nix
@@ -14,8 +14,8 @@ let
       ClusterName=${cfg.clusterName}
       StateSaveLocation=${cfg.stateSaveLocation}
       SlurmUser=${cfg.user}
-      ${optionalString (cfg.controlMachine != null) ''controlMachine=${cfg.controlMachine}''}
-      ${optionalString (cfg.controlAddr != null) ''controlAddr=${cfg.controlAddr}''}
+      ${optionalString (cfg.controlMachine != null) "controlMachine=${cfg.controlMachine}"}
+      ${optionalString (cfg.controlAddr != null) "controlAddr=${cfg.controlAddr}"}
       ${toString (map (x: "NodeName=${x}\n") cfg.nodeName)}
       ${toString (map (x: "PartitionName=${x}\n") cfg.partitionName)}
       PlugStackConfig=${plugStackConfig}/plugstack.conf
@@ -25,7 +25,7 @@ let
 
   plugStackConfig = pkgs.writeTextDir "plugstack.conf"
     ''
-      ${optionalString cfg.enableSrunX11 ''optional ${pkgs.slurm-spank-x11}/lib/x11.so''}
+      ${optionalString cfg.enableSrunX11 "optional ${pkgs.slurm-spank-x11}/lib/x11.so"}
       ${cfg.extraPlugstackConfig}
     '';
 
diff --git a/nixpkgs/nixos/modules/services/continuous-integration/buildbot/master.nix b/nixpkgs/nixos/modules/services/continuous-integration/buildbot/master.nix
index e1950b91382b..d30d94c53cc3 100644
--- a/nixpkgs/nixos/modules/services/continuous-integration/buildbot/master.nix
+++ b/nixpkgs/nixos/modules/services/continuous-integration/buildbot/master.nix
@@ -223,6 +223,7 @@ in {
       };
 
       pythonPackages = mkOption {
+        type = types.listOf types.package;
         default = pythonPackages: with pythonPackages; [ ];
         defaultText = "pythonPackages: with pythonPackages; [ ]";
         description = "Packages to add the to the PYTHONPATH of the buildbot process.";
diff --git a/nixpkgs/nixos/modules/services/databases/couchdb.nix b/nixpkgs/nixos/modules/services/databases/couchdb.nix
index f385331e8782..c99a7529213d 100644
--- a/nixpkgs/nixos/modules/services/databases/couchdb.nix
+++ b/nixpkgs/nixos/modules/services/databases/couchdb.nix
@@ -16,8 +16,7 @@ let
       [admins]
       ${cfg.adminUser} = ${cfg.adminPass}
     '' else
-    ''
-    '') + (if useVersion2 then
+    "") + (if useVersion2 then
     ''
       [chttpd]
     '' else
diff --git a/nixpkgs/nixos/modules/services/databases/firebird.nix b/nixpkgs/nixos/modules/services/databases/firebird.nix
index 95837aa1cea6..ed47f647edd3 100644
--- a/nixpkgs/nixos/modules/services/databases/firebird.nix
+++ b/nixpkgs/nixos/modules/services/databases/firebird.nix
@@ -59,6 +59,7 @@ in
 
       port = mkOption {
         default = "3050";
+        type = types.port;
         description = ''
           Port Firebird uses.
         '';
@@ -66,6 +67,7 @@ in
 
       user = mkOption {
         default = "firebird";
+        type = types.str;
         description = ''
           User account under which firebird runs.
         '';
@@ -73,6 +75,7 @@ in
 
       baseDir = mkOption {
         default = "/var/db/firebird"; # ubuntu is using /var/lib/firebird/2.1/data/.. ?
+        type = types.str;
         description = ''
           Location containing data/ and system/ directories.
           data/ stores the databases, system/ stores the password database security2.fdb.
@@ -114,7 +117,7 @@ in
         serviceConfig.User = cfg.user;
         serviceConfig.LogsDirectory = "firebird";
         serviceConfig.LogsDirectoryMode = "0700";
-        serviceConfig.ExecStart = ''${firebird}/bin/fbserver -d'';
+        serviceConfig.ExecStart = "${firebird}/bin/fbserver -d";
 
         # TODO think about shutdown
       };
diff --git a/nixpkgs/nixos/modules/services/databases/memcached.nix b/nixpkgs/nixos/modules/services/databases/memcached.nix
index f54bb6cc9b18..ca7b20eb049a 100644
--- a/nixpkgs/nixos/modules/services/databases/memcached.nix
+++ b/nixpkgs/nixos/modules/services/databases/memcached.nix
@@ -17,39 +17,44 @@ in
   options = {
 
     services.memcached = {
-
       enable = mkEnableOption "Memcached";
 
       user = mkOption {
+        type = types.str;
         default = "memcached";
         description = "The user to run Memcached as";
       };
 
       listen = mkOption {
+        type = types.str;
         default = "127.0.0.1";
-        description = "The IP address to bind to";
+        description = "The IP address to bind to.";
       };
 
       port = mkOption {
+        type = types.port;
         default = 11211;
-        description = "The port to bind to";
+        description = "The port to bind to.";
       };
 
       enableUnixSocket = mkEnableOption "unix socket at /run/memcached/memcached.sock";
 
       maxMemory = mkOption {
+        type = types.ints.unsigned;
         default = 64;
         description = "The maximum amount of memory to use for storage, in megabytes.";
       };
 
       maxConnections = mkOption {
+        type = types.ints.unsigned;
         default = 1024;
-        description = "The maximum number of simultaneous connections";
+        description = "The maximum number of simultaneous connections.";
       };
 
       extraOptions = mkOption {
+        type = types.listOf types.str;
         default = [];
-        description = "A list of extra options that will be added as a suffix when running memcached";
+        description = "A list of extra options that will be added as a suffix when running memcached.";
       };
     };
 
diff --git a/nixpkgs/nixos/modules/services/databases/mongodb.nix b/nixpkgs/nixos/modules/services/databases/mongodb.nix
index 4af0b9d44e13..db1e5fedf50d 100644
--- a/nixpkgs/nixos/modules/services/databases/mongodb.nix
+++ b/nixpkgs/nixos/modules/services/databases/mongodb.nix
@@ -41,16 +41,19 @@ in
       };
 
       user = mkOption {
+        type = types.str;
         default = "mongodb";
         description = "User account under which MongoDB runs";
       };
 
       bind_ip = mkOption {
+        type = types.str;
         default = "127.0.0.1";
         description = "IP to bind to";
       };
 
       quiet = mkOption {
+        type = types.bool;
         default = false;
         description = "quieter output";
       };
@@ -68,16 +71,19 @@ in
       };
 
       dbpath = mkOption {
+        type = types.str;
         default = "/var/db/mongodb";
         description = "Location where MongoDB stores its files";
       };
 
       pidFile = mkOption {
+        type = types.str;
         default = "/run/mongodb.pid";
         description = "Location of MongoDB pid file";
       };
 
       replSetName = mkOption {
+        type = types.str;
         default = "";
         description = ''
           If this instance is part of a replica set, set its name here.
@@ -86,6 +92,7 @@ in
       };
 
       extraConfig = mkOption {
+        type = types.lines;
         default = "";
         example = ''
           storage.journal.enabled: false
diff --git a/nixpkgs/nixos/modules/services/databases/neo4j.nix b/nixpkgs/nixos/modules/services/databases/neo4j.nix
index 09b453e75845..53760bb24c4a 100644
--- a/nixpkgs/nixos/modules/services/databases/neo4j.nix
+++ b/nixpkgs/nixos/modules/services/databases/neo4j.nix
@@ -16,14 +16,14 @@ let
       ''}
       dbms.ssl.policy.${name}.client_auth=${conf.clientAuth}
       ${if length (splitString "/" conf.privateKey) > 1 then
-        ''dbms.ssl.policy.${name}.private_key=${conf.privateKey}''
+        "dbms.ssl.policy.${name}.private_key=${conf.privateKey}"
       else
-        ''dbms.ssl.policy.${name}.private_key=${conf.baseDirectory}/${conf.privateKey}''
+        "dbms.ssl.policy.${name}.private_key=${conf.baseDirectory}/${conf.privateKey}"
       }
       ${if length (splitString "/" conf.privateKey) > 1 then
-        ''dbms.ssl.policy.${name}.public_certificate=${conf.publicCertificate}''
+        "dbms.ssl.policy.${name}.public_certificate=${conf.publicCertificate}"
       else
-        ''dbms.ssl.policy.${name}.public_certificate=${conf.baseDirectory}/${conf.publicCertificate}''
+        "dbms.ssl.policy.${name}.public_certificate=${conf.baseDirectory}/${conf.publicCertificate}"
       }
       dbms.ssl.policy.${name}.revoked_dir=${conf.revokedDir}
       dbms.ssl.policy.${name}.tls_versions=${concatStringsSep "," conf.tlsVersions}
diff --git a/nixpkgs/nixos/modules/services/databases/openldap.nix b/nixpkgs/nixos/modules/services/databases/openldap.nix
index 94a5c573768b..f0efc659cff7 100644
--- a/nixpkgs/nixos/modules/services/databases/openldap.nix
+++ b/nixpkgs/nixos/modules/services/databases/openldap.nix
@@ -244,7 +244,7 @@ in {
     };
   };
 
-  meta.maintainers = with lib.maintainters; [ mic92 kwohlfahrt ];
+  meta.maintainers = with lib.maintainers; [ mic92 kwohlfahrt ];
 
   config = mkIf cfg.enable {
     assertions = map (opt: {
diff --git a/nixpkgs/nixos/modules/services/databases/redis.nix b/nixpkgs/nixos/modules/services/databases/redis.nix
index 6b8853ae390b..117e63662258 100644
--- a/nixpkgs/nixos/modules/services/databases/redis.nix
+++ b/nixpkgs/nixos/modules/services/databases/redis.nix
@@ -4,31 +4,16 @@ with lib;
 
 let
   cfg = config.services.redis;
-  redisBool = b: if b then "yes" else "no";
-  condOption = name: value: if value != null then "${name} ${toString value}" else "";
-
-  redisConfig = pkgs.writeText "redis.conf" ''
-    port ${toString cfg.port}
-    ${condOption "bind" cfg.bind}
-    ${condOption "unixsocket" cfg.unixSocket}
-    daemonize no
-    supervised systemd
-    loglevel ${cfg.logLevel}
-    logfile ${cfg.logfile}
-    syslog-enabled ${redisBool cfg.syslog}
-    databases ${toString cfg.databases}
-    ${concatMapStrings (d: "save ${toString (builtins.elemAt d 0)} ${toString (builtins.elemAt d 1)}\n") cfg.save}
-    dbfilename dump.rdb
-    dir /var/lib/redis
-    ${if cfg.slaveOf != null then "slaveof ${cfg.slaveOf.ip} ${toString cfg.slaveOf.port}" else ""}
-    ${condOption "masterauth" cfg.masterAuth}
-    ${condOption "requirepass" cfg.requirePass}
-    appendOnly ${redisBool cfg.appendOnly}
-    appendfsync ${cfg.appendFsync}
-    slowlog-log-slower-than ${toString cfg.slowLogLogSlowerThan}
-    slowlog-max-len ${toString cfg.slowLogMaxLen}
-    ${cfg.extraConfig}
-  '';
+
+  mkValueString = value:
+    if value == true then "yes"
+    else if value == false then "no"
+    else generators.mkValueStringDefault { } value;
+
+  redisConfig = pkgs.writeText "redis.conf" (generators.toKeyValue {
+    listsAsDuplicateKeys = true;
+    mkKeyValue = generators.mkKeyValueDefault { inherit mkValueString; } " ";
+  } cfg.settings);
 in
 {
   imports = [
@@ -37,6 +22,7 @@ in
     (mkRemovedOptionModule [ "services" "redis" "dbFilename" ] "The redis module now uses /var/lib/redis/dump.rdb as database dump location.")
     (mkRemovedOptionModule [ "services" "redis" "appendOnlyFilename" ] "This option was never used.")
     (mkRemovedOptionModule [ "services" "redis" "pidFile" ] "This option was removed.")
+    (mkRemovedOptionModule [ "services" "redis" "extraConfig" ] "Use services.redis.settings instead.")
   ];
 
   ###### interface
@@ -136,12 +122,29 @@ in
       };
 
       slaveOf = mkOption {
-        default = null; # { ip, port }
-        description = "An attribute set with two attributes: ip and port to which this redis instance acts as a slave.";
+        type = with types; nullOr (submodule ({ ... }: {
+          options = {
+            ip = mkOption {
+              type = str;
+              description = "IP of the Redis master";
+              example = "192.168.1.100";
+            };
+
+            port = mkOption {
+              type = port;
+              description = "port of the Redis master";
+              default = 6379;
+            };
+          };
+        }));
+
+        default = null;
+        description = "IP and port to which this redis instance acts as a slave.";
         example = { ip = "192.168.1.100"; port = 6379; };
       };
 
       masterAuth = mkOption {
+        type = with types; nullOr str;
         default = null;
         description = ''If the master is password protected (using the requirePass configuration)
         it is possible to tell the slave to authenticate before starting the replication synchronization
@@ -191,10 +194,20 @@ in
         description = "Maximum number of items to keep in slow log.";
       };
 
-      extraConfig = mkOption {
-        type = types.lines;
-        default = "";
-        description = "Extra configuration options for redis.conf.";
+      settings = mkOption {
+        type = with types; attrsOf (oneOf [ bool int str (listOf str) ]);
+        default = {};
+        description = ''
+          Redis configuration. Refer to
+          <link xlink:href="https://redis.io/topics/config"/>
+          for details on supported values.
+        '';
+        example = literalExample ''
+          {
+            unixsocketperm = "700";
+            loadmodule = [ "/path/to/my_module.so" "/path/to/other_module.so" ];
+          }
+        '';
       };
     };
 
@@ -225,6 +238,30 @@ in
 
     environment.systemPackages = [ cfg.package ];
 
+    services.redis.settings = mkMerge [
+      {
+        port = cfg.port;
+        daemonize = false;
+        supervised = "systemd";
+        loglevel = cfg.logLevel;
+        logfile = cfg.logfile;
+        syslog-enabled = cfg.syslog;
+        databases = cfg.databases;
+        save = map (d: "${toString (builtins.elemAt d 0)} ${toString (builtins.elemAt d 1)}") cfg.save;
+        dbfilename = "dump.rdb";
+        dir = "/var/lib/redis";
+        appendOnly = cfg.appendOnly;
+        appendfsync = cfg.appendFsync;
+        slowlog-log-slower-than = cfg.slowLogLogSlowerThan;
+        slowlog-max-len = cfg.slowLogMaxLen;
+      }
+      (mkIf (cfg.bind != null) { bind = cfg.bind; })
+      (mkIf (cfg.unixSocket != null) { unixsocket = cfg.unixSocket; })
+      (mkIf (cfg.slaveOf != null) { slaveof = "${cfg.slaveOf.ip} ${cfg.slaveOf.port}"; })
+      (mkIf (cfg.masterAuth != null) { masterauth = cfg.masterAuth; })
+      (mkIf (cfg.requirePass != null) { requirepass = cfg.requirePass; })
+    ];
+
     systemd.services.redis = {
       description = "Redis Server";
 
diff --git a/nixpkgs/nixos/modules/services/databases/virtuoso.nix b/nixpkgs/nixos/modules/services/databases/virtuoso.nix
index 6eb09e0a58fc..8b01622ecb03 100644
--- a/nixpkgs/nixos/modules/services/databases/virtuoso.nix
+++ b/nixpkgs/nixos/modules/services/databases/virtuoso.nix
@@ -16,28 +16,33 @@ with lib;
       enable = mkEnableOption "Virtuoso Opensource database server";
 
       config = mkOption {
+        type = types.lines;
         default = "";
         description = "Extra options to put into Virtuoso configuration file.";
       };
 
       parameters = mkOption {
+        type = types.lines;
         default = "";
         description = "Extra options to put into [Parameters] section of Virtuoso configuration file.";
       };
 
       listenAddress = mkOption {
+        type = types.str;
         default = "1111";
         example = "myserver:1323";
         description = "ip:port or port to listen on.";
       };
 
       httpListenAddress = mkOption {
+        type = types.nullOr types.str;
         default = null;
         example = "myserver:8080";
         description = "ip:port or port for Virtuoso HTTP server to listen on.";
       };
 
       dirsAllowed = mkOption {
+        type = types.nullOr types.str; # XXX Maybe use a list in the future?
         default = null;
         example = "/www, /home/";
         description = "A list of directories Virtuoso is allowed to access";
diff --git a/nixpkgs/nixos/modules/services/desktops/gnome3/evolution-data-server.nix b/nixpkgs/nixos/modules/services/desktops/gnome3/evolution-data-server.nix
index bd62d16f61ce..749f12b86bc8 100644
--- a/nixpkgs/nixos/modules/services/desktops/gnome3/evolution-data-server.nix
+++ b/nixpkgs/nixos/modules/services/desktops/gnome3/evolution-data-server.nix
@@ -15,31 +15,45 @@ with lib;
   options = {
 
     services.gnome3.evolution-data-server = {
-
-      enable = mkOption {
-        type = types.bool;
-        default = false;
-        description = ''
-          Whether to enable Evolution Data Server, a collection of services for
-          storing addressbooks and calendars.
-        '';
+      enable = mkEnableOption "Evolution Data Server, a collection of services for storing addressbooks and calendars.";
+      plugins = mkOption {
+        type = types.listOf types.package;
+        default = [ ];
+        description = "Plugins for Evolution Data Server.";
       };
-
     };
+    programs.evolution = {
+      enable = mkEnableOption "Evolution, a Personal information management application that provides integrated mail, calendaring and address book functionality.";
+      plugins = mkOption {
+        type = types.listOf types.package;
+        default = [ ];
+        example = literalExample "[ pkgs.evolution-ews ]";
+        description = "Plugins for Evolution.";
+      };
 
+    };
   };
 
-
   ###### implementation
 
-  config = mkIf config.services.gnome3.evolution-data-server.enable {
-
-    environment.systemPackages = [ pkgs.gnome3.evolution-data-server ];
-
-    services.dbus.packages = [ pkgs.gnome3.evolution-data-server ];
-
-    systemd.packages = [ pkgs.gnome3.evolution-data-server ];
-
-  };
-
+  config =
+    let
+      bundle = pkgs.evolutionWithPlugins.override { inherit (config.services.gnome3.evolution-data-server) plugins; };
+    in
+    mkMerge [
+      (mkIf config.services.gnome3.evolution-data-server.enable {
+        environment.systemPackages = [ bundle ];
+
+        services.dbus.packages = [ bundle ];
+
+        systemd.packages = [ bundle ];
+      })
+      (mkIf config.programs.evolution.enable {
+        services.gnome3.evolution-data-server = {
+          enable = true;
+          plugins = [ pkgs.evolution ] ++ config.programs.evolution.plugins;
+        };
+        services.gnome3.gnome-keyring.enable = true;
+      })
+    ];
 }
diff --git a/nixpkgs/nixos/modules/services/desktops/pipewire.nix b/nixpkgs/nixos/modules/services/desktops/pipewire.nix
index 0ef988d9e69f..134becf6b0c4 100644
--- a/nixpkgs/nixos/modules/services/desktops/pipewire.nix
+++ b/nixpkgs/nixos/modules/services/desktops/pipewire.nix
@@ -93,11 +93,11 @@ in {
     assertions = [
       {
         assertion = cfg.pulse.enable -> !config.hardware.pulseaudio.enable;
-        message = "PipeWire based PulseAudio server emulation replaces PulseAudio";
+        message = "PipeWire based PulseAudio server emulation replaces PulseAudio. This option requires `hardware.pulseaudio.enable` to be set to false";
       }
       {
         assertion = cfg.jack.enable -> !config.services.jack.jackd.enable;
-        message = "PipeWire based JACK emulation doesn't use the JACK service";
+        message = "PipeWire based JACK emulation doesn't use the JACK service. This option requires `services.jack.jackd.enable` to be set to false";
       }
     ];
 
diff --git a/nixpkgs/nixos/modules/services/development/bloop.nix b/nixpkgs/nixos/modules/services/development/bloop.nix
index 226718a9e80a..c1180a8bbdd4 100644
--- a/nixpkgs/nixos/modules/services/development/bloop.nix
+++ b/nixpkgs/nixos/modules/services/development/bloop.nix
@@ -44,7 +44,7 @@ in {
       };
       serviceConfig = {
         Type        = "simple";
-        ExecStart   = ''${pkgs.bloop}/bin/bloop server'';
+        ExecStart   = "${pkgs.bloop}/bin/bloop server";
         Restart     = "always";
       };
     };
diff --git a/nixpkgs/nixos/modules/services/development/hoogle.nix b/nixpkgs/nixos/modules/services/development/hoogle.nix
index cbf13f027de2..a661e3acae3e 100644
--- a/nixpkgs/nixos/modules/services/development/hoogle.nix
+++ b/nixpkgs/nixos/modules/services/development/hoogle.nix
@@ -49,6 +49,11 @@ in {
       default = "https://hoogle.haskell.org";
     };
 
+    host = mkOption {
+      type = types.str;
+      description = "Set the host to bind on.";
+      default = "127.0.0.1";
+    };
   };
 
   config = mkIf cfg.enable {
@@ -59,7 +64,7 @@ in {
 
       serviceConfig = {
         Restart = "always";
-        ExecStart = ''${hoogleEnv}/bin/hoogle server --local --port ${toString cfg.port} --home ${cfg.home}'';
+        ExecStart = ''${hoogleEnv}/bin/hoogle server --local --port ${toString cfg.port} --home ${cfg.home} --host ${cfg.host}'';
 
         DynamicUser = true;
 
diff --git a/nixpkgs/nixos/modules/services/editors/emacs.xml b/nixpkgs/nixos/modules/services/editors/emacs.xml
index 302aa1ed7c48..fd99ee9442c9 100644
--- a/nixpkgs/nixos/modules/services/editors/emacs.xml
+++ b/nixpkgs/nixos/modules/services/editors/emacs.xml
@@ -156,7 +156,7 @@ $ ./result/bin/emacs
 
 let
   myEmacs = pkgs.emacs; <co xml:id="ex-emacsNix-2" />
-  emacsWithPackages = (pkgs.emacsPackagesGen myEmacs).emacsWithPackages; <co xml:id="ex-emacsNix-3" />
+  emacsWithPackages = (pkgs.emacsPackagesFor myEmacs).emacsWithPackages; <co xml:id="ex-emacsNix-3" />
 in
   emacsWithPackages (epkgs: (with epkgs.melpaStablePackages; [ <co xml:id="ex-emacsNix-4" />
     magit          # ; Integrate git &lt;C-x g&gt;
@@ -254,10 +254,10 @@ in
     <example xml:id="module-services-emacs-querying-packages">
      <title>Querying Emacs packages</title>
 <programlisting><![CDATA[
-nix-env -f "<nixpkgs>" -qaP -A emacsPackages.elpaPackages
-nix-env -f "<nixpkgs>" -qaP -A emacsPackages.melpaPackages
-nix-env -f "<nixpkgs>" -qaP -A emacsPackages.melpaStablePackages
-nix-env -f "<nixpkgs>" -qaP -A emacsPackages.orgPackages
+nix-env -f "<nixpkgs>" -qaP -A emacs.pkgs.elpaPackages
+nix-env -f "<nixpkgs>" -qaP -A emacs.pkgs.melpaPackages
+nix-env -f "<nixpkgs>" -qaP -A emacs.pkgs.melpaStablePackages
+nix-env -f "<nixpkgs>" -qaP -A emacs.pkgs.orgPackages
 ]]></programlisting>
     </example>
    </para>
diff --git a/nixpkgs/nixos/modules/services/editors/infinoted.nix b/nixpkgs/nixos/modules/services/editors/infinoted.nix
index 8b997ccbf66e..10d868b7f161 100644
--- a/nixpkgs/nixos/modules/services/editors/infinoted.nix
+++ b/nixpkgs/nixos/modules/services/editors/infinoted.nix
@@ -141,14 +141,14 @@ in {
           install -o ${cfg.user} -g ${cfg.group} -m 0600 /dev/null /var/lib/infinoted/infinoted.conf
           cat >>/var/lib/infinoted/infinoted.conf <<EOF
           [infinoted]
-          ${optionalString (cfg.keyFile != null) ''key-file=${cfg.keyFile}''}
-          ${optionalString (cfg.certificateFile != null) ''certificate-file=${cfg.certificateFile}''}
-          ${optionalString (cfg.certificateChain != null) ''certificate-chain=${cfg.certificateChain}''}
+          ${optionalString (cfg.keyFile != null) "key-file=${cfg.keyFile}"}
+          ${optionalString (cfg.certificateFile != null) "certificate-file=${cfg.certificateFile}"}
+          ${optionalString (cfg.certificateChain != null) "certificate-chain=${cfg.certificateChain}"}
           port=${toString cfg.port}
           security-policy=${cfg.securityPolicy}
           root-directory=${cfg.rootDirectory}
           plugins=${concatStringsSep ";" cfg.plugins}
-          ${optionalString (cfg.passwordFile != null) ''password=$(head -n 1 ${cfg.passwordFile})''}
+          ${optionalString (cfg.passwordFile != null) "password=$(head -n 1 ${cfg.passwordFile})"}
 
           ${cfg.extraConfig}
           EOF
diff --git a/nixpkgs/nixos/modules/services/games/openarena.nix b/nixpkgs/nixos/modules/services/games/openarena.nix
index 8c014d78809b..9c441e98b206 100644
--- a/nixpkgs/nixos/modules/services/games/openarena.nix
+++ b/nixpkgs/nixos/modules/services/games/openarena.nix
@@ -19,7 +19,7 @@ in
       extraFlags = mkOption {
         type = types.listOf types.str;
         default = [];
-        description = ''Extra flags to pass to <command>oa_ded</command>'';
+        description = "Extra flags to pass to <command>oa_ded</command>";
         example = [
           "+set dedicated 2"
           "+set sv_hostname 'My NixOS OpenArena Server'"
diff --git a/nixpkgs/nixos/modules/services/hardware/sane_extra_backends/brscan4_etc_files.nix b/nixpkgs/nixos/modules/services/hardware/sane_extra_backends/brscan4_etc_files.nix
index ec0457bbd583..556f6bbb419a 100644
--- a/nixpkgs/nixos/modules/services/hardware/sane_extra_backends/brscan4_etc_files.nix
+++ b/nixpkgs/nixos/modules/services/hardware/sane_extra_backends/brscan4_etc_files.nix
@@ -19,18 +19,16 @@ nix-shell -E 'with import <nixpkgs> { }; brscan4-etc-files.override{netDevices=[
 
 */
 
-with lib;
-
 let
 
   addNetDev = nd: ''
     brsaneconfig4 -a \
     name="${nd.name}" \
     model="${nd.model}" \
-    ${if (hasAttr "nodename" nd && nd.nodename != null) then
+    ${if (lib.hasAttr "nodename" nd && nd.nodename != null) then
       ''nodename="${nd.nodename}"'' else
       ''ip="${nd.ip}"''}'';
-  addAllNetDev = xs: concatStringsSep "\n" (map addNetDev xs);
+  addAllNetDev = xs: lib.concatStringsSep "\n" (map addNetDev xs);
 in
 
 stdenv.mkDerivation {
@@ -61,11 +59,11 @@ stdenv.mkDerivation {
   dontStrip = true;
   dontPatchELF = true;
 
-  meta = {
+  meta = with lib; {
     description = "Brother brscan4 sane backend driver etc files";
     homepage = "http://www.brother.com";
-    platforms = stdenv.lib.platforms.linux;
-    license = stdenv.lib.licenses.unfree;
-    maintainers = with stdenv.lib.maintainers; [ jraygauthier ];
+    platforms = platforms.linux;
+    license = licenses.unfree;
+    maintainers = with maintainers; [ jraygauthier ];
   };
 }
diff --git a/nixpkgs/nixos/modules/services/logging/logstash.nix b/nixpkgs/nixos/modules/services/logging/logstash.nix
index bf92425f998b..a4fc315d080d 100644
--- a/nixpkgs/nixos/modules/services/logging/logstash.nix
+++ b/nixpkgs/nixos/modules/services/logging/logstash.nix
@@ -100,7 +100,7 @@ in
 
       inputConfig = mkOption {
         type = types.lines;
-        default = ''generator { }'';
+        default = "generator { }";
         description = "Logstash input configuration.";
         example = ''
           # Read from journal
@@ -131,7 +131,7 @@ in
 
       outputConfig = mkOption {
         type = types.lines;
-        default = ''stdout { codec => rubydebug }'';
+        default = "stdout { codec => rubydebug }";
         description = "Logstash output configuration.";
         example = ''
           redis { host => ["localhost"] data_type => "list" key => "logstash" codec => json }
diff --git a/nixpkgs/nixos/modules/services/mail/mailman.nix b/nixpkgs/nixos/modules/services/mail/mailman.nix
index c0fed360af86..a5f5588f90bc 100644
--- a/nixpkgs/nixos/modules/services/mail/mailman.nix
+++ b/nixpkgs/nixos/modules/services/mail/mailman.nix
@@ -360,7 +360,7 @@ in {
 
       mailman-web-setup = {
         description = "Prepare mailman-web files and database";
-        before = [ "uwsgi.service" "mailman-uwsgi.service" ];
+        before = [ "mailman-uwsgi.service" ];
         requiredBy = [ "mailman-uwsgi.service" ];
         restartTriggers = [ config.environment.etc."mailman3/settings.py".source ];
         script = ''
diff --git a/nixpkgs/nixos/modules/services/mail/postfix.nix b/nixpkgs/nixos/modules/services/mail/postfix.nix
index 37ba98339a6c..1dcdcab8d481 100644
--- a/nixpkgs/nixos/modules/services/mail/postfix.nix
+++ b/nixpkgs/nixos/modules/services/mail/postfix.nix
@@ -25,8 +25,6 @@ let
 
   clientRestrictions = concatStringsSep ", " (clientAccess ++ dnsBl);
 
-  smtpTlsSecurityLevel = if cfg.useDane then "dane" else mkDefault "may";
-
   mainCf = let
     escape = replaceStrings ["$"] ["$$"];
     mkList = items: "\n  " + concatStringsSep ",\n  " items;
@@ -510,14 +508,6 @@ in
         '';
       };
 
-      useDane = mkOption {
-        type = types.bool;
-        default = false;
-        description = ''
-          Sets smtp_tls_security_level to "dane" rather than "may". See postconf(5) for details.
-        '';
-      };
-
       sslCert = mkOption {
         type = types.str;
         default = "";
@@ -819,13 +809,13 @@ in
       // optionalAttrs cfg.enableHeaderChecks { header_checks = [ "regexp:/etc/postfix/header_checks" ]; }
       // optionalAttrs (cfg.tlsTrustedAuthorities != "") {
         smtp_tls_CAfile = cfg.tlsTrustedAuthorities;
-        smtp_tls_security_level = smtpTlsSecurityLevel;
+        smtp_tls_security_level = mkDefault "may";
       }
       // optionalAttrs (cfg.sslCert != "") {
         smtp_tls_cert_file = cfg.sslCert;
         smtp_tls_key_file = cfg.sslKey;
 
-        smtp_tls_security_level = smtpTlsSecurityLevel;
+        smtp_tls_security_level = mkDefault "may";
 
         smtpd_tls_cert_file = cfg.sslCert;
         smtpd_tls_key_file = cfg.sslKey;
@@ -969,5 +959,9 @@ in
   imports = [
    (mkRemovedOptionModule [ "services" "postfix" "sslCACert" ]
      "services.postfix.sslCACert was replaced by services.postfix.tlsTrustedAuthorities. In case you intend that your server should validate requested client certificates use services.postfix.extraConfig.")
+
+   (mkChangedOptionModule [ "services" "postfix" "useDane" ]
+     [ "services" "postfix" "config" "smtp_tls_security_level" ]
+     (config: mkIf config.services.postfix.useDane "dane"))
   ];
 }
diff --git a/nixpkgs/nixos/modules/services/mail/postgrey.nix b/nixpkgs/nixos/modules/services/mail/postgrey.nix
index 709f6b21aa0a..7c206e3725e6 100644
--- a/nixpkgs/nixos/modules/services/mail/postgrey.nix
+++ b/nixpkgs/nixos/modules/services/mail/postgrey.nix
@@ -163,7 +163,7 @@ in {
 
     systemd.services.postgrey = let
       bind-flag = if cfg.socket ? path then
-        ''--unix=${cfg.socket.path} --socketmode=${cfg.socket.mode}''
+        "--unix=${cfg.socket.path} --socketmode=${cfg.socket.mode}"
       else
         ''--inet=${optionalString (cfg.socket.addr != null) (cfg.socket.addr + ":")}${toString cfg.socket.port}'';
     in {
diff --git a/nixpkgs/nixos/modules/services/misc/autofs.nix b/nixpkgs/nixos/modules/services/misc/autofs.nix
index 5e7c1e668288..541f0d2db19f 100644
--- a/nixpkgs/nixos/modules/services/misc/autofs.nix
+++ b/nixpkgs/nixos/modules/services/misc/autofs.nix
@@ -52,6 +52,7 @@ in
       };
 
       timeout = mkOption {
+        type = types.int;
         default = 600;
         description = "Set the global minimum timeout, in seconds, until directories are unmounted";
       };
diff --git a/nixpkgs/nixos/modules/services/misc/cgminer.nix b/nixpkgs/nixos/modules/services/misc/cgminer.nix
index fa9c8c54509e..b80a4746fd1e 100644
--- a/nixpkgs/nixos/modules/services/misc/cgminer.nix
+++ b/nixpkgs/nixos/modules/services/misc/cgminer.nix
@@ -120,7 +120,7 @@ in
       wantedBy = [ "multi-user.target" ];
 
       environment = {
-        LD_LIBRARY_PATH = ''/run/opengl-driver/lib:/run/opengl-driver-32/lib'';
+        LD_LIBRARY_PATH = "/run/opengl-driver/lib:/run/opengl-driver-32/lib";
         DISPLAY = ":${toString config.services.xserver.display}";
         GPU_MAX_ALLOC_PERCENT = "100";
         GPU_USE_SYNC_OBJECTS = "1";
diff --git a/nixpkgs/nixos/modules/services/misc/dictd.nix b/nixpkgs/nixos/modules/services/misc/dictd.nix
index ae477dc3b634..12583bb5b6c6 100644
--- a/nixpkgs/nixos/modules/services/misc/dictd.nix
+++ b/nixpkgs/nixos/modules/services/misc/dictd.nix
@@ -27,7 +27,7 @@ in
         default = with pkgs.dictdDBs; [ wiktionary wordnet ];
         defaultText = "with pkgs.dictdDBs; [ wiktionary wordnet ]";
         example = literalExample "[ pkgs.dictdDBs.nld2eng ]";
-        description = ''List of databases to make available.'';
+        description = "List of databases to make available.";
       };
 
     };
diff --git a/nixpkgs/nixos/modules/services/misc/exhibitor.nix b/nixpkgs/nixos/modules/services/misc/exhibitor.nix
index f8c79f892da3..28c98edf47af 100644
--- a/nixpkgs/nixos/modules/services/misc/exhibitor.nix
+++ b/nixpkgs/nixos/modules/services/misc/exhibitor.nix
@@ -185,7 +185,7 @@ in
       };
       zkExtraCfg = mkOption {
         type = types.str;
-        default = ''initLimit=5&syncLimit=2&tickTime=2000'';
+        default = "initLimit=5&syncLimit=2&tickTime=2000";
         description = ''
           Extra options to pass into Zookeeper
         '';
diff --git a/nixpkgs/nixos/modules/services/misc/gitea.nix b/nixpkgs/nixos/modules/services/misc/gitea.nix
index af80e99746be..434e2d2429b5 100644
--- a/nixpkgs/nixos/modules/services/misc/gitea.nix
+++ b/nixpkgs/nixos/modules/services/misc/gitea.nix
@@ -349,7 +349,7 @@ in
         {
           DOMAIN = cfg.domain;
           STATIC_ROOT_PATH = cfg.staticRootPath;
-          LFS_JWT_SECRET = "#jwtsecret#";
+          LFS_JWT_SECRET = "#lfsjwtsecret#";
           ROOT_URL = cfg.rootUrl;
         }
         (mkIf cfg.enableUnixSocket {
@@ -381,6 +381,7 @@ in
 
       security = {
         SECRET_KEY = "#secretkey#";
+        INTERNAL_TOKEN = "#internaltoken#";
         INSTALL_LOCK = true;
       };
 
@@ -396,6 +397,10 @@ in
       mailer = mkIf (cfg.mailerPasswordFile != null) {
         PASSWD = "#mailerpass#";
       };
+
+      oauth2 = {
+        JWT_SECRET = "#oauth2jwtsecret#";
+      };
     };
 
     services.postgresql = optionalAttrs (usePostgresql && cfg.database.createDatabase) {
@@ -453,12 +458,22 @@ in
       description = "gitea";
       after = [ "network.target" ] ++ lib.optional usePostgresql "postgresql.service" ++ lib.optional useMysql "mysql.service";
       wantedBy = [ "multi-user.target" ];
-      path = [ gitea pkgs.gitAndTools.git ];
-
+      path = [ gitea pkgs.git ];
+
+      # In older versions the secret naming for JWT was kind of confusing.
+      # The file jwt_secret hold the value for LFS_JWT_SECRET and JWT_SECRET
+      # wasn't persistant at all.
+      # To fix that, there is now the file oauth2_jwt_secret containing the
+      # values for JWT_SECRET and the file jwt_secret gets renamed to
+      # lfs_jwt_secret.
+      # We have to consider this to stay compatible with older installations.
       preStart = let
         runConfig = "${cfg.stateDir}/custom/conf/app.ini";
         secretKey = "${cfg.stateDir}/custom/conf/secret_key";
-        jwtSecret = "${cfg.stateDir}/custom/conf/jwt_secret";
+        oauth2JwtSecret = "${cfg.stateDir}/custom/conf/oauth2_jwt_secret";
+        oldLfsJwtSecret = "${cfg.stateDir}/custom/conf/jwt_secret"; # old file for LFS_JWT_SECRET
+        lfsJwtSecret = "${cfg.stateDir}/custom/conf/lfs_jwt_secret"; # new file for LFS_JWT_SECRET
+        internalToken = "${cfg.stateDir}/custom/conf/internal_token";
       in ''
         # copy custom configuration and generate a random secret key if needed
         ${optionalString (cfg.useWizard == false) ''
@@ -468,24 +483,41 @@ in
               ${gitea}/bin/gitea generate secret SECRET_KEY > ${secretKey}
           fi
 
-          if [ ! -e ${jwtSecret} ]; then
-              ${gitea}/bin/gitea generate secret LFS_JWT_SECRET > ${jwtSecret}
+          # Migrate LFS_JWT_SECRET filename
+          if [[ -e ${oldLfsJwtSecret} && ! -e ${lfsJwtSecret} ]]; then
+              mv ${oldLfsJwtSecret} ${lfsJwtSecret}
+          fi
+
+          if [ ! -e ${oauth2JwtSecret} ]; then
+              ${gitea}/bin/gitea generate secret JWT_SECRET > ${oauth2JwtSecret}
+          fi
+
+          if [ ! -e ${lfsJwtSecret} ]; then
+              ${gitea}/bin/gitea generate secret LFS_JWT_SECRET > ${lfsJwtSecret}
+          fi
+
+          if [ ! -e ${internalToken} ]; then
+              ${gitea}/bin/gitea generate secret INTERNAL_TOKEN > ${internalToken}
           fi
 
-          KEY="$(head -n1 ${secretKey})"
+          SECRETKEY="$(head -n1 ${secretKey})"
           DBPASS="$(head -n1 ${cfg.database.passwordFile})"
-          JWTSECRET="$(head -n1 ${jwtSecret})"
+          OAUTH2JWTSECRET="$(head -n1 ${oauth2JwtSecret})"
+          LFSJWTSECRET="$(head -n1 ${lfsJwtSecret})"
+          INTERNALTOKEN="$(head -n1 ${internalToken})"
           ${if (cfg.mailerPasswordFile == null) then ''
             MAILERPASSWORD="#mailerpass#"
           '' else ''
             MAILERPASSWORD="$(head -n1 ${cfg.mailerPasswordFile} || :)"
           ''}
-          sed -e "s,#secretkey#,$KEY,g" \
+          sed -e "s,#secretkey#,$SECRETKEY,g" \
               -e "s,#dbpass#,$DBPASS,g" \
-              -e "s,#jwtsecret#,$JWTSECRET,g" \
+              -e "s,#oauth2jwtsecret#,$OAUTH2JWTSECRET,g" \
+              -e "s,#lfsjwtsecret#,$LFSJWTSECRET,g" \
+              -e "s,#internaltoken#,$INTERNALTOKEN,g" \
               -e "s,#mailerpass#,$MAILERPASSWORD,g" \
               -i ${runConfig}
-          chmod 640 ${runConfig} ${secretKey} ${jwtSecret}
+          chmod 640 ${runConfig} ${secretKey} ${oauth2JwtSecret} ${lfsJwtSecret} ${internalToken}
         ''}
 
         # update all hooks' binary paths
@@ -565,8 +597,7 @@ in
     users.groups.gitea = {};
 
     warnings =
-      optional (cfg.database.password != "") ''
-        config.services.gitea.database.password will be stored as plaintext in the Nix store. Use database.passwordFile instead.'' ++
+      optional (cfg.database.password != "") "config.services.gitea.database.password will be stored as plaintext in the Nix store. Use database.passwordFile instead." ++
       optional (cfg.extraConfig != null) ''
         services.gitea.`extraConfig` is deprecated, please use services.gitea.`settings`.
       '';
@@ -605,5 +636,5 @@ in
       timerConfig.OnCalendar = cfg.dump.interval;
     };
   };
-  meta.maintainers = with lib.maintainers; [ srhb ];
+  meta.maintainers = with lib.maintainers; [ srhb ma27 ];
 }
diff --git a/nixpkgs/nixos/modules/services/misc/gitlab.nix b/nixpkgs/nixos/modules/services/misc/gitlab.nix
index 35a9dccdff28..de4d1bf1987a 100644
--- a/nixpkgs/nixos/modules/services/misc/gitlab.nix
+++ b/nixpkgs/nixos/modules/services/misc/gitlab.nix
@@ -736,7 +736,7 @@ in {
       environment = gitlabEnv;
       path = with pkgs; [
         postgresqlPackage
-        gitAndTools.git
+        git
         ruby
         openssh
         nodejs
@@ -764,7 +764,7 @@ in {
       path = with pkgs; [
         openssh
         procps  # See https://gitlab.com/gitlab-org/gitaly/issues/1562
-        gitAndTools.git
+        git
         cfg.packages.gitaly.rubyEnv
         cfg.packages.gitaly.rubyEnv.wrappedRuby
         gzip
@@ -806,7 +806,7 @@ in {
       wantedBy = [ "multi-user.target" ];
       path = with pkgs; [
         exiftool
-        gitAndTools.git
+        git
         gnutar
         gzip
         openssh
@@ -854,7 +854,7 @@ in {
       environment = gitlabEnv;
       path = with pkgs; [
         postgresqlPackage
-        gitAndTools.git
+        git
         openssh
         nodejs
         procps
diff --git a/nixpkgs/nixos/modules/services/misc/gitolite.nix b/nixpkgs/nixos/modules/services/misc/gitolite.nix
index 59cbdac319c8..190ea9212d2a 100644
--- a/nixpkgs/nixos/modules/services/misc/gitolite.nix
+++ b/nixpkgs/nixos/modules/services/misc/gitolite.nix
@@ -227,6 +227,6 @@ in
     };
 
     environment.systemPackages = [ pkgs.gitolite pkgs.git ]
-        ++ optional cfg.enableGitAnnex pkgs.gitAndTools.git-annex;
+        ++ optional cfg.enableGitAnnex pkgs.git-annex;
   });
 }
diff --git a/nixpkgs/nixos/modules/services/misc/matrix-synapse.nix b/nixpkgs/nixos/modules/services/misc/matrix-synapse.nix
index 3abb9b7d69c8..8e3fa60206c2 100644
--- a/nixpkgs/nixos/modules/services/misc/matrix-synapse.nix
+++ b/nixpkgs/nixos/modules/services/misc/matrix-synapse.nix
@@ -504,8 +504,7 @@ in {
       report_stats = mkOption {
         type = types.bool;
         default = false;
-        description = ''
-        '';
+        description = "";
       };
       servers = mkOption {
         type = types.attrsOf (types.attrsOf types.str);
diff --git a/nixpkgs/nixos/modules/services/misc/matrix-synapse.xml b/nixpkgs/nixos/modules/services/misc/matrix-synapse.xml
index fbfa838b168b..358b631eb485 100644
--- a/nixpkgs/nixos/modules/services/misc/matrix-synapse.xml
+++ b/nixpkgs/nixos/modules/services/misc/matrix-synapse.xml
@@ -69,6 +69,9 @@ in {
       # i.e. to delegate from the host being accessible as ${config.networking.domain}
       # to another host actually running the Matrix homeserver.
       "${config.networking.domain}" = {
+        <link linkend="opt-services.nginx.virtualHosts._name_.enableACME">enableACME</link> = true;
+        <link linkend="opt-services.nginx.virtualHosts._name_.forceSSL">forceSSL</link> = true;
+
         <link linkend="opt-services.nginx.virtualHosts._name_.locations._name_.extraConfig">locations."= /.well-known/matrix/server".extraConfig</link> =
           let
             # use 443 instead of the default 8448 port to unite
@@ -203,7 +206,7 @@ Success!
     <link linkend="opt-services.nginx.virtualHosts._name_.root">root</link> = pkgs.element-web.override {
       conf = {
         default_server_config."m.homeserver" = {
-          "base_url" = "${config.networking.domain}";
+          "base_url" = "https://${fqdn}";
           "server_name" = "${fqdn}";
         };
       };
diff --git a/nixpkgs/nixos/modules/services/misc/nix-daemon.nix b/nixpkgs/nixos/modules/services/misc/nix-daemon.nix
index 0eeff31d6c4d..64bdbf159d51 100644
--- a/nixpkgs/nixos/modules/services/misc/nix-daemon.nix
+++ b/nixpkgs/nixos/modules/services/misc/nix-daemon.nix
@@ -587,10 +587,10 @@ in
 
     nix.systemFeatures = mkDefault (
       [ "nixos-test" "benchmark" "big-parallel" "kvm" ] ++
-      optionals (pkgs.hostPlatform.platform ? gcc.arch) (
-        # a builder can run code for `platform.gcc.arch` and inferior architectures
-        [ "gccarch-${pkgs.hostPlatform.platform.gcc.arch}" ] ++
-        map (x: "gccarch-${x}") lib.systems.architectures.inferiors.${pkgs.hostPlatform.platform.gcc.arch}
+      optionals (pkgs.hostPlatform ? gcc.arch) (
+        # a builder can run code for `gcc.arch` and inferior architectures
+        [ "gccarch-${pkgs.hostPlatform.gcc.arch}" ] ++
+        map (x: "gccarch-${x}") lib.systems.architectures.inferiors.${pkgs.hostPlatform.gcc.arch}
       )
     );
 
diff --git a/nixpkgs/nixos/modules/services/misc/nzbhydra2.nix b/nixpkgs/nixos/modules/services/misc/nzbhydra2.nix
new file mode 100644
index 000000000000..c396b4b8f6e9
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/misc/nzbhydra2.nix
@@ -0,0 +1,78 @@
+{ config, pkgs, lib, ... }:
+
+with lib;
+
+let cfg = config.services.nzbhydra2;
+
+in {
+  options = {
+    services.nzbhydra2 = {
+      enable = mkEnableOption "NZBHydra2";
+
+      dataDir = mkOption {
+        type = types.str;
+        default = "/var/lib/nzbhydra2";
+        description = "The directory where NZBHydra2 stores its data files.";
+      };
+
+      openFirewall = mkOption {
+        type = types.bool;
+        default = false;
+        description =
+          "Open ports in the firewall for the NZBHydra2 web interface.";
+      };
+
+      package = mkOption {
+        type = types.package;
+        default = pkgs.nzbhydra2;
+        defaultText = "pkgs.nzbhydra2";
+        description = "NZBHydra2 package to use.";
+      };
+    };
+  };
+
+  config = mkIf cfg.enable {
+    systemd.tmpfiles.rules =
+      [ "d '${cfg.dataDir}' 0700 nzbhydra2 nzbhydra2 - -" ];
+
+    systemd.services.nzbhydra2 = {
+      description = "NZBHydra2";
+      after = [ "network.target" ];
+      wantedBy = [ "multi-user.target" ];
+
+      serviceConfig = {
+        Type = "simple";
+        User = "nzbhydra2";
+        Group = "nzbhydra2";
+        ExecStart =
+          "${cfg.package}/bin/nzbhydra2 --nobrowser --datafolder '${cfg.dataDir}'";
+        Restart = "on-failure";
+        # Hardening
+        NoNewPrivileges = true;
+        PrivateTmp = true;
+        PrivateDevices = true;
+        DevicePolicy = "closed";
+        ProtectSystem = "strict";
+        ReadWritePaths = cfg.dataDir;
+        ProtectHome = "read-only";
+        ProtectControlGroups = true;
+        ProtectKernelModules = true;
+        ProtectKernelTunables = true;
+        RestrictAddressFamilies ="AF_UNIX AF_INET AF_INET6 AF_NETLINK";
+        RestrictNamespaces = true;
+        RestrictRealtime = true;
+        RestrictSUIDSGID = true;
+        LockPersonality = true;
+      };
+    };
+
+    networking.firewall = mkIf cfg.openFirewall { allowedTCPPorts = [ 5076 ]; };
+
+    users.users.nzbhydra2 = {
+      group = "nzbhydra2";
+      isSystemUser = true;
+    };
+
+    users.groups.nzbhydra2 = {};
+  };
+}
diff --git a/nixpkgs/nixos/modules/services/misc/redmine.nix b/nixpkgs/nixos/modules/services/misc/redmine.nix
index 1313bdaccc49..8b53eb471db6 100644
--- a/nixpkgs/nixos/modules/services/misc/redmine.nix
+++ b/nixpkgs/nixos/modules/services/misc/redmine.nix
@@ -230,7 +230,7 @@ in
       production = {
         scm_subversion_command = "${pkgs.subversion}/bin/svn";
         scm_mercurial_command = "${pkgs.mercurial}/bin/hg";
-        scm_git_command = "${pkgs.gitAndTools.git}/bin/git";
+        scm_git_command = "${pkgs.git}/bin/git";
         scm_cvs_command = "${pkgs.cvs}/bin/cvs";
         scm_bazaar_command = "${pkgs.breezy}/bin/bzr";
         scm_darcs_command = "${pkgs.darcs}/bin/darcs";
@@ -299,7 +299,7 @@ in
         breezy
         cvs
         darcs
-        gitAndTools.git
+        git
         mercurial
         subversion
       ];
diff --git a/nixpkgs/nixos/modules/services/misc/snapper.nix b/nixpkgs/nixos/modules/services/misc/snapper.nix
index 3560d08520b7..a821b9b6bf65 100644
--- a/nixpkgs/nixos/modules/services/misc/snapper.nix
+++ b/nixpkgs/nixos/modules/services/misc/snapper.nix
@@ -48,6 +48,8 @@ in
           subvolume = "/home";
           extraConfig = ''
             ALLOW_USERS="alice"
+            TIMELINE_CREATE=yes
+            TIMELINE_CLEANUP=yes
           '';
         };
       };
diff --git a/nixpkgs/nixos/modules/services/monitoring/apcupsd.nix b/nixpkgs/nixos/modules/services/monitoring/apcupsd.nix
index 75218aa1d46b..1dccbc93edf8 100644
--- a/nixpkgs/nixos/modules/services/monitoring/apcupsd.nix
+++ b/nixpkgs/nixos/modules/services/monitoring/apcupsd.nix
@@ -104,7 +104,7 @@ in
       hooks = mkOption {
         default = {};
         example = {
-          doshutdown = ''# shell commands to notify that the computer is shutting down'';
+          doshutdown = "# shell commands to notify that the computer is shutting down";
         };
         type = types.attrsOf types.lines;
         description = ''
diff --git a/nixpkgs/nixos/modules/services/monitoring/grafana-image-renderer.nix b/nixpkgs/nixos/modules/services/monitoring/grafana-image-renderer.nix
index a010a5316bae..b8b95d846c6a 100644
--- a/nixpkgs/nixos/modules/services/monitoring/grafana-image-renderer.nix
+++ b/nixpkgs/nixos/modules/services/monitoring/grafana-image-renderer.nix
@@ -122,7 +122,7 @@ in {
         timezone = config.time.timeZone;
       };
 
-      services = {
+      service = {
         logging.level = mkIf cfg.verbose (mkDefault "debug");
         metrics.enabled = mkDefault false;
       };
diff --git a/nixpkgs/nixos/modules/services/monitoring/graphite.nix b/nixpkgs/nixos/modules/services/monitoring/graphite.nix
index 64d9d61950da..9213748d3c9a 100644
--- a/nixpkgs/nixos/modules/services/monitoring/graphite.nix
+++ b/nixpkgs/nixos/modules/services/monitoring/graphite.nix
@@ -25,10 +25,10 @@ let
 
   graphiteApiConfig = pkgs.writeText "graphite-api.yaml" ''
     search_index: ${dataDir}/index
-    ${optionalString (config.time.timeZone != null) ''time_zone: ${config.time.timeZone}''}
-    ${optionalString (cfg.api.finders != []) ''finders:''}
+    ${optionalString (config.time.timeZone != null) "time_zone: ${config.time.timeZone}"}
+    ${optionalString (cfg.api.finders != []) "finders:"}
     ${concatMapStringsSep "\n" (f: "  - " + f.moduleName) cfg.api.finders}
-    ${optionalString (cfg.api.functions != []) ''functions:''}
+    ${optionalString (cfg.api.functions != []) "functions:"}
     ${concatMapStringsSep "\n" (f: "  - " + f) cfg.api.functions}
     ${cfg.api.extraConfig}
   '';
diff --git a/nixpkgs/nixos/modules/services/monitoring/incron.nix b/nixpkgs/nixos/modules/services/monitoring/incron.nix
index 1789fd9f2051..dc97af58562e 100644
--- a/nixpkgs/nixos/modules/services/monitoring/incron.nix
+++ b/nixpkgs/nixos/modules/services/monitoring/incron.nix
@@ -67,7 +67,7 @@ in
   config = mkIf cfg.enable {
 
     warnings = optional (cfg.allow != null && cfg.deny != null)
-      ''If `services.incron.allow` is set then `services.incron.deny` will be ignored.'';
+      "If `services.incron.allow` is set then `services.incron.deny` will be ignored.";
 
     environment.systemPackages = [ pkgs.incron ];
 
diff --git a/nixpkgs/nixos/modules/services/monitoring/prometheus/default.nix b/nixpkgs/nixos/modules/services/monitoring/prometheus/default.nix
index 4f9be38f7f14..9103a6f932db 100644
--- a/nixpkgs/nixos/modules/services/monitoring/prometheus/default.nix
+++ b/nixpkgs/nixos/modules/services/monitoring/prometheus/default.nix
@@ -370,6 +370,14 @@ let
         List of file service discovery configurations.
       '';
 
+      gce_sd_configs = mkOpt (types.listOf promTypes.gce_sd_config) ''
+        List of Google Compute Engine service discovery configurations.
+
+        See <link
+        xlink:href="https://prometheus.io/docs/prometheus/latest/configuration/configuration/#gce_sd_config">the
+        relevant Prometheus configuration docs</link> for more detail.
+      '';
+
       static_configs = mkOpt (types.listOf promTypes.static_config) ''
         List of labeled target groups for this job.
       '';
@@ -555,6 +563,52 @@ let
     };
   };
 
+  promTypes.gce_sd_config = types.submodule {
+    options = {
+      # Use `mkOption` instead of `mkOpt` for project and zone because they are
+      # required configuration values for `gce_sd_config`.
+      project = mkOption {
+        type = types.str;
+        description = ''
+          The GCP Project.
+        '';
+      };
+
+      zone = mkOption {
+        type = types.str;
+        description = ''
+          The zone of the scrape targets. If you need multiple zones use multiple
+          gce_sd_configs.
+        '';
+      };
+
+      filter = mkOpt types.str ''
+        Filter can be used optionally to filter the instance list by other
+        criteria Syntax of this filter string is described here in the filter
+        query parameter section: <link
+        xlink:href="https://cloud.google.com/compute/docs/reference/latest/instances/list"
+        />.
+      '';
+
+      refresh_interval = mkDefOpt types.str "60s" ''
+        Refresh interval to re-read the cloud instance list.
+      '';
+
+      port = mkDefOpt types.port "80" ''
+        The port to scrape metrics from. If using the public IP address, this
+        must instead be specified in the relabeling rule.
+      '';
+
+      tag_separator = mkDefOpt types.str "," ''
+        The tag separator used to separate concatenated GCE instance network tags.
+
+        See the GCP documentation on network tags for more information: <link
+        xlink:href="https://cloud.google.com/vpc/docs/add-remove-network-tags"
+        />
+      '';
+    };
+  };
+
   promTypes.relabel_config = types.submodule {
     options = {
       source_labels = mkOpt (types.listOf types.str) ''
diff --git a/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/collectd.nix b/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/collectd.nix
index 972104630275..a3b2b92bc347 100644
--- a/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/collectd.nix
+++ b/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/collectd.nix
@@ -20,7 +20,7 @@ in
       port = mkOption {
         type = types.int;
         default = 25826;
-        description = ''Network address on which to accept collectd binary network packets.'';
+        description = "Network address on which to accept collectd binary network packets.";
       };
 
       listenAddress = mkOption {
diff --git a/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/nextcloud.nix b/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/nextcloud.nix
index aee6bd5e66ce..ce7125bf5a83 100644
--- a/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/nextcloud.nix
+++ b/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/nextcloud.nix
@@ -46,11 +46,11 @@ in
       DynamicUser = false;
       ExecStart = ''
         ${pkgs.prometheus-nextcloud-exporter}/bin/nextcloud-exporter \
-          -a ${cfg.listenAddress}:${toString cfg.port} \
-          -u ${cfg.username} \
-          -t ${cfg.timeout} \
-          -l ${cfg.url} \
-          -p ${escapeShellArg "@${cfg.passwordFile}"} \
+          --addr ${cfg.listenAddress}:${toString cfg.port} \
+          --username ${cfg.username} \
+          --timeout ${cfg.timeout} \
+          --server ${cfg.url} \
+          --password ${escapeShellArg "@${cfg.passwordFile}"} \
           ${concatStringsSep " \\\n  " cfg.extraFlags}
       '';
     };
diff --git a/nixpkgs/nixos/modules/services/monitoring/telegraf.nix b/nixpkgs/nixos/modules/services/monitoring/telegraf.nix
index b341a9005c2a..bc30ca3b77cf 100644
--- a/nixpkgs/nixos/modules/services/monitoring/telegraf.nix
+++ b/nixpkgs/nixos/modules/services/monitoring/telegraf.nix
@@ -69,7 +69,7 @@ in {
             umask 077
             ${pkgs.envsubst}/bin/envsubst -i "${configFile}" > /var/run/telegraf/config.toml
           '');
-        ExecStart=''${cfg.package}/bin/telegraf -config ${finalConfigFile}'';
+        ExecStart="${cfg.package}/bin/telegraf -config ${finalConfigFile}";
         ExecReload="${pkgs.coreutils}/bin/kill -HUP $MAINPID";
         RuntimeDirectory = "telegraf";
         User = "telegraf";
diff --git a/nixpkgs/nixos/modules/services/monitoring/thanos.nix b/nixpkgs/nixos/modules/services/monitoring/thanos.nix
index 52dab28cf72f..474ea4b25054 100644
--- a/nixpkgs/nixos/modules/services/monitoring/thanos.nix
+++ b/nixpkgs/nixos/modules/services/monitoring/thanos.nix
@@ -12,7 +12,7 @@ let
   };
 
   optionToArgs = opt: v  : optional (v != null)  ''--${opt}="${toString v}"'';
-  flagToArgs   = opt: v  : optional v            ''--${opt}'';
+  flagToArgs   = opt: v  : optional v            "--${opt}";
   listToArgs   = opt: vs : map               (v: ''--${opt}="${v}"'') vs;
   attrsToArgs  = opt: kvs: mapAttrsToList (k: v: ''--${opt}=${k}=\"${v}\"'') kvs;
 
@@ -67,7 +67,7 @@ let
     preferLocalBuild = true;
     json = builtins.toFile "${name}.json" (builtins.toJSON attrs);
     nativeBuildInputs = [ pkgs.remarshal ];
-  } ''json2yaml -i $json -o $out'';
+  } "json2yaml -i $json -o $out";
 
   thanos = cmd: "${cfg.package}/bin/thanos ${cmd}" +
     (let args = cfg.${cmd}.arguments;
diff --git a/nixpkgs/nixos/modules/services/monitoring/ups.nix b/nixpkgs/nixos/modules/services/monitoring/ups.nix
index a45e806d4ad8..ae5097c54424 100644
--- a/nixpkgs/nixos/modules/services/monitoring/ups.nix
+++ b/nixpkgs/nixos/modules/services/monitoring/ups.nix
@@ -205,7 +205,7 @@ in
       after = [ "upsd.service" ];
       wantedBy = [ "multi-user.target" ];
       # TODO: replace 'root' by another username.
-      script = ''${pkgs.nut}/bin/upsdrvctl -u root start'';
+      script = "${pkgs.nut}/bin/upsdrvctl -u root start";
       serviceConfig = {
         Type = "oneshot";
         RemainAfterExit = true;
diff --git a/nixpkgs/nixos/modules/services/network-filesystems/ceph.nix b/nixpkgs/nixos/modules/services/network-filesystems/ceph.nix
index f2dc740fd88e..632c3fb1059d 100644
--- a/nixpkgs/nixos/modules/services/network-filesystems/ceph.nix
+++ b/nixpkgs/nixos/modules/services/network-filesystems/ceph.nix
@@ -48,7 +48,7 @@ let
       ExecStart = ''${ceph.out}/bin/${if daemonType == "rgw" then "radosgw" else "ceph-${daemonType}"} \
                     -f --cluster ${clusterName} --id ${daemonId}'';
     } // optionalAttrs (daemonType == "osd") {
-      ExecStartPre = ''${ceph.lib}/libexec/ceph/ceph-osd-prestart.sh --id ${daemonId} --cluster ${clusterName}'';
+      ExecStartPre = "${ceph.lib}/libexec/ceph/ceph-osd-prestart.sh --id ${daemonId} --cluster ${clusterName}";
       RestartSec = "20s";
       PrivateDevices = "no"; # osd needs disk access
     } // optionalAttrs ( daemonType == "mon") {
@@ -353,7 +353,7 @@ in
     ];
 
     warnings = optional (cfg.global.monInitialMembers == null)
-      ''Not setting up a list of members in monInitialMembers requires that you set the host variable for each mon daemon or else the cluster won't function'';
+      "Not setting up a list of members in monInitialMembers requires that you set the host variable for each mon daemon or else the cluster won't function";
 
     environment.etc."ceph/ceph.conf".text = let
       # Merge the extraConfig set for mgr daemons, as mgr don't have their own section
diff --git a/nixpkgs/nixos/modules/services/networking/amuled.nix b/nixpkgs/nixos/modules/services/networking/amuled.nix
index 1128ee2c3e61..39320643dd5e 100644
--- a/nixpkgs/nixos/modules/services/networking/amuled.nix
+++ b/nixpkgs/nixos/modules/services/networking/amuled.nix
@@ -24,13 +24,15 @@ in
       };
 
       dataDir = mkOption {
-        default = ''/home/${user}/'';
+        type = types.str;
+        default = "/home/${user}/";
         description = ''
           The directory holding configuration, incoming and temporary files.
         '';
       };
 
       user = mkOption {
+        type = types.nullOr types.str;
         default = null;
         description = ''
           The user the AMule daemon should run as.
diff --git a/nixpkgs/nixos/modules/services/networking/bitlbee.nix b/nixpkgs/nixos/modules/services/networking/bitlbee.nix
index 9ebf382fce42..59ad9e546863 100644
--- a/nixpkgs/nixos/modules/services/networking/bitlbee.nix
+++ b/nixpkgs/nixos/modules/services/networking/bitlbee.nix
@@ -58,6 +58,7 @@ in
       };
 
       interface = mkOption {
+        type = types.str;
         default = "127.0.0.1";
         description = ''
           The interface the BitlBee deamon will be listening to.  If `127.0.0.1',
@@ -68,6 +69,7 @@ in
 
       portNumber = mkOption {
         default = 6667;
+        type = types.int;
         description = ''
           Number of the port BitlBee will be listening to.
         '';
@@ -142,6 +144,7 @@ in
 
       extraSettings = mkOption {
         default = "";
+        type = types.lines;
         description = ''
           Will be inserted in the Settings section of the config file.
         '';
@@ -149,6 +152,7 @@ in
 
       extraDefaults = mkOption {
         default = "";
+        type = types.lines;
         description = ''
           Will be inserted in the Default section of the config file.
         '';
diff --git a/nixpkgs/nixos/modules/services/networking/cntlm.nix b/nixpkgs/nixos/modules/services/networking/cntlm.nix
index 5b5068e43d7c..c8e08fdefaa4 100644
--- a/nixpkgs/nixos/modules/services/networking/cntlm.nix
+++ b/nixpkgs/nixos/modules/services/networking/cntlm.nix
@@ -42,13 +42,13 @@ in
     };
 
     domain = mkOption {
-      description = ''Proxy account domain/workgroup name.'';
+      description = "Proxy account domain/workgroup name.";
     };
 
     password = mkOption {
       default = "/etc/cntlm.password";
       type = types.str;
-      description = ''Proxy account password. Note: use chmod 0600 on /etc/cntlm.password for security.'';
+      description = "Proxy account password. Note: use chmod 0600 on /etc/cntlm.password for security.";
     };
 
     netbios_hostname = mkOption {
diff --git a/nixpkgs/nixos/modules/services/networking/connman.nix b/nixpkgs/nixos/modules/services/networking/connman.nix
index 6ccc2dffb267..11f66b05df12 100644
--- a/nixpkgs/nixos/modules/services/networking/connman.nix
+++ b/nixpkgs/nixos/modules/services/networking/connman.nix
@@ -42,8 +42,7 @@ in {
 
       extraConfig = mkOption {
         type = types.lines;
-        default = ''
-        '';
+        default = "";
         description = ''
           Configuration lines appended to the generated connman configuration file.
         '';
diff --git a/nixpkgs/nixos/modules/services/networking/dnscrypt-wrapper.nix b/nixpkgs/nixos/modules/services/networking/dnscrypt-wrapper.nix
index ee7e9b0454de..89360f4bf373 100644
--- a/nixpkgs/nixos/modules/services/networking/dnscrypt-wrapper.nix
+++ b/nixpkgs/nixos/modules/services/networking/dnscrypt-wrapper.nix
@@ -83,7 +83,7 @@ let
   # correctly implement key rotation of dnscrypt-wrapper ephemeral keys.
   dnscrypt-proxy1 = pkgs.callPackage
     ({ stdenv, fetchFromGitHub, autoreconfHook
-    , pkgconfig, libsodium, ldns, openssl, systemd }:
+    , pkg-config, libsodium, ldns, openssl, systemd }:
 
     stdenv.mkDerivation rec {
       pname = "dnscrypt-proxy";
@@ -98,7 +98,7 @@ let
 
       configureFlags = optional stdenv.isLinux "--with-systemd";
 
-      nativeBuildInputs = [ autoreconfHook pkgconfig ];
+      nativeBuildInputs = [ autoreconfHook pkg-config ];
 
       # <ldns/ldns.h> depends on <openssl/ssl.h>
       buildInputs = [ libsodium openssl.dev ldns ] ++ optional stdenv.isLinux systemd;
diff --git a/nixpkgs/nixos/modules/services/networking/dnsdist.nix b/nixpkgs/nixos/modules/services/networking/dnsdist.nix
index 05c2bdef83e7..3584915d0aa3 100644
--- a/nixpkgs/nixos/modules/services/networking/dnsdist.nix
+++ b/nixpkgs/nixos/modules/services/networking/dnsdist.nix
@@ -26,8 +26,7 @@ in {
 
       extraConfig = mkOption {
         type = types.lines;
-        default = ''
-        '';
+        default = "";
         description = ''
           Extra lines to be added verbatim to dnsdist.conf.
         '';
diff --git a/nixpkgs/nixos/modules/services/networking/gateone.nix b/nixpkgs/nixos/modules/services/networking/gateone.nix
index 56f2ba21a125..3e3a3c1aa94d 100644
--- a/nixpkgs/nixos/modules/services/networking/gateone.nix
+++ b/nixpkgs/nixos/modules/services/networking/gateone.nix
@@ -10,12 +10,12 @@ options = {
       pidDir = mkOption {
         default = "/run/gateone";
         type = types.path;
-        description = ''Path of pid files for GateOne.'';
+        description = "Path of pid files for GateOne.";
       };
       settingsDir = mkOption {
         default = "/var/lib/gateone";
         type = types.path;
-        description = ''Path of configuration files for GateOne.'';
+        description = "Path of configuration files for GateOne.";
       };
     };
 };
diff --git a/nixpkgs/nixos/modules/services/networking/hostapd.nix b/nixpkgs/nixos/modules/services/networking/hostapd.nix
index 5d73038363a9..e9569b2ba6b9 100644
--- a/nixpkgs/nixos/modules/services/networking/hostapd.nix
+++ b/nixpkgs/nixos/modules/services/networking/hostapd.nix
@@ -20,8 +20,8 @@ let
     ssid=${cfg.ssid}
     hw_mode=${cfg.hwMode}
     channel=${toString cfg.channel}
-    ${optionalString (cfg.countryCode != null) ''country_code=${cfg.countryCode}''}
-    ${optionalString (cfg.countryCode != null) ''ieee80211d=1''}
+    ${optionalString (cfg.countryCode != null) "country_code=${cfg.countryCode}"}
+    ${optionalString (cfg.countryCode != null) "ieee80211d=1"}
 
     # logging (debug level)
     logger_syslog=-1
diff --git a/nixpkgs/nixos/modules/services/networking/hylafax/modem-default.nix b/nixpkgs/nixos/modules/services/networking/hylafax/modem-default.nix
index 7529b5b0aafd..707b82092829 100644
--- a/nixpkgs/nixos/modules/services/networking/hylafax/modem-default.nix
+++ b/nixpkgs/nixos/modules/services/networking/hylafax/modem-default.nix
@@ -5,7 +5,7 @@
 {
 
   TagLineFont = "etc/LiberationSans-25.pcf";
-  TagLineLocale = ''en_US.UTF-8'';
+  TagLineLocale = "en_US.UTF-8";
 
   AdminGroup = "root";  # groups that can change server config
   AnswerRotary = "fax";  # don't accept anything else but faxes
@@ -16,7 +16,7 @@
   SessionTracing = "0x78701";
   UUCPLockDir = "/var/lock";
 
-  SendPageCmd = ''${pkgs.coreutils}/bin/false'';  # prevent pager transmit
-  SendUUCPCmd = ''${pkgs.coreutils}/bin/false'';  # prevent UUCP transmit
+  SendPageCmd = "${pkgs.coreutils}/bin/false";  # prevent pager transmit
+  SendUUCPCmd = "${pkgs.coreutils}/bin/false";  # prevent UUCP transmit
 
 }
diff --git a/nixpkgs/nixos/modules/services/networking/hylafax/options.nix b/nixpkgs/nixos/modules/services/networking/hylafax/options.nix
index 9e28d09dffca..7f18c0d39ab4 100644
--- a/nixpkgs/nixos/modules/services/networking/hylafax/options.nix
+++ b/nixpkgs/nixos/modules/services/networking/hylafax/options.nix
@@ -85,8 +85,8 @@ let
       # Otherwise, we use `false` to provoke
       # an error if hylafax tries to use it.
       c.sendmailPath = mkMerge [
-        (mkIfDefault noWrapper ''${pkgs.coreutils}/bin/false'')
-        (mkIfDefault (!noWrapper) ''${wrapperDir}/${program}'')
+        (mkIfDefault noWrapper "${pkgs.coreutils}/bin/false")
+        (mkIfDefault (!noWrapper) "${wrapperDir}/${program}")
       ];
       importDefaultConfig = file:
         lib.attrsets.mapAttrs
@@ -121,7 +121,7 @@ in
 
   options.services.hylafax = {
 
-    enable = mkEnableOption ''HylaFAX server'';
+    enable = mkEnableOption "HylaFAX server";
 
     autostart = mkOption {
       type = bool;
@@ -139,28 +139,28 @@ in
       type = nullOr str1;
       default = null;
       example = "49";
-      description = ''Country code for server and all modems.'';
+      description = "Country code for server and all modems.";
     };
 
     areaCode = mkOption {
       type = nullOr str1;
       default = null;
       example = "30";
-      description = ''Area code for server and all modems.'';
+      description = "Area code for server and all modems.";
     };
 
     longDistancePrefix = mkOption {
       type = nullOr str;
       default = null;
       example = "0";
-      description = ''Long distance prefix for server and all modems.'';
+      description = "Long distance prefix for server and all modems.";
     };
 
     internationalPrefix = mkOption {
       type = nullOr str;
       default = null;
       example = "00";
-      description = ''International prefix for server and all modems.'';
+      description = "International prefix for server and all modems.";
     };
 
     spoolAreaPath = mkOption {
@@ -267,7 +267,7 @@ in
     spoolExtraInit = mkOption {
       type = lines;
       default = "";
-      example = ''chmod 0755 .  # everyone may read my faxes'';
+      example = "chmod 0755 .  # everyone may read my faxes";
       description = ''
         Additional shell code that is executed within the
         spooling area directory right after its setup.
@@ -345,7 +345,7 @@ in
     faxqclean.doneqMinutes = mkOption {
       type = int1;
       default = 15;
-      example = literalExample ''24*60'';
+      example = literalExample "24*60";
       description = ''
         Set the job
         age threshold (in minutes) that controls how long
@@ -355,7 +355,7 @@ in
     faxqclean.docqMinutes = mkOption {
       type = int1;
       default = 60;
-      example = literalExample ''24*60'';
+      example = literalExample "24*60";
       description = ''
         Set the document
         age threshold (in minutes) that controls how long
diff --git a/nixpkgs/nixos/modules/services/networking/hylafax/systemd.nix b/nixpkgs/nixos/modules/services/networking/hylafax/systemd.nix
index b9b9b9dca4f0..f63f7c97ad1c 100644
--- a/nixpkgs/nixos/modules/services/networking/hylafax/systemd.nix
+++ b/nixpkgs/nixos/modules/services/networking/hylafax/systemd.nix
@@ -16,12 +16,12 @@ let
       mkLines = conf:
         (lib.concatLists
         (lib.flip lib.mapAttrsToList conf
-        (k: map (v: ''${k}: ${v}'')
+        (k: map (v: "${k}: ${v}")
       )));
       include = mkLines { Include = conf.Include or []; };
       other = mkLines ( conf // { Include = []; } );
     in
-      pkgs.writeText ''hylafax-config${name}''
+      pkgs.writeText "hylafax-config${name}"
       (concatStringsSep "\n" (include ++ other));
 
   globalConfigPath = mkConfigFile "" cfg.faxqConfig;
@@ -29,7 +29,7 @@ let
   modemConfigPath =
     let
       mkModemConfigFile = { config, name, ... }:
-        mkConfigFile ''.${name}''
+        mkConfigFile ".${name}"
         (cfg.commonModemConfig // config);
       mkLine = { name, type, ... }@modem: ''
         # check if modem config file exists:
@@ -81,7 +81,7 @@ let
     description = "HylaFAX queue manager sendq watch";
     documentation = [ "man:faxq(8)" "man:sendq(5)" ];
     wantedBy = [ "multi-user.target" ];
-    pathConfig.PathExistsGlob = [ ''${cfg.spoolAreaPath}/sendq/q*'' ];
+    pathConfig.PathExistsGlob = [ "${cfg.spoolAreaPath}/sendq/q*" ];
   };
 
   timers = mkMerge [
@@ -134,7 +134,7 @@ let
         exit 1
       fi
     '';
-    serviceConfig.ExecStop = ''${setupSpoolScript}'';
+    serviceConfig.ExecStop = "${setupSpoolScript}";
     serviceConfig.RemainAfterExit = true;
     serviceConfig.Type = "oneshot";
     unitConfig.RequiresMountsFor = [ cfg.spoolAreaPath ];
@@ -145,7 +145,7 @@ let
     documentation = [ "man:faxq(8)" ];
     requires = [ "hylafax-spool.service" ];
     after = [ "hylafax-spool.service" ];
-    wants = mapModems ( { name, ... }: ''hylafax-faxgetty@${name}.service'' );
+    wants = mapModems ( { name, ... }: "hylafax-faxgetty@${name}.service" );
     wantedBy = mkIf cfg.autostart [ "multi-user.target" ];
     serviceConfig.Type = "forking";
     serviceConfig.ExecStart = ''${pkgs.hylafaxplus}/spool/bin/faxq -q "${cfg.spoolAreaPath}"'';
@@ -155,7 +155,7 @@ let
     # stopped will always yield a failed send attempt:
     # The fax service is started when the job is created with
     # `sendfax`, but modems need some time to initialize.
-    serviceConfig.ExecStartPost = [ ''${waitFaxqScript}'' ];
+    serviceConfig.ExecStartPost = [ "${waitFaxqScript}" ];
     # faxquit fails if the pipe is already gone
     # (e.g. the service is already stopping)
     serviceConfig.ExecStop = ''-${pkgs.hylafaxplus}/spool/bin/faxquit -q "${cfg.spoolAreaPath}"'';
@@ -186,7 +186,7 @@ let
     wantedBy = mkIf cfg.faxcron.enable.spoolInit requires;
     startAt = mkIf (cfg.faxcron.enable.frequency!=null) cfg.faxcron.enable.frequency;
     serviceConfig.ExecStart = concatStringsSep " " [
-      ''${pkgs.hylafaxplus}/spool/bin/faxcron''
+      "${pkgs.hylafaxplus}/spool/bin/faxcron"
       ''-q "${cfg.spoolAreaPath}"''
       ''-info ${toString cfg.faxcron.infoDays}''
       ''-log  ${toString cfg.faxcron.logDays}''
@@ -202,18 +202,18 @@ let
     wantedBy = mkIf cfg.faxqclean.enable.spoolInit requires;
     startAt = mkIf (cfg.faxqclean.enable.frequency!=null) cfg.faxqclean.enable.frequency;
     serviceConfig.ExecStart = concatStringsSep " " [
-      ''${pkgs.hylafaxplus}/spool/bin/faxqclean''
+      "${pkgs.hylafaxplus}/spool/bin/faxqclean"
       ''-q "${cfg.spoolAreaPath}"''
-      ''-v''
-      (optionalString (cfg.faxqclean.archiving!="never") ''-a'')
-      (optionalString (cfg.faxqclean.archiving=="always")  ''-A'')
+      "-v"
+      (optionalString (cfg.faxqclean.archiving!="never") "-a")
+      (optionalString (cfg.faxqclean.archiving=="always")  "-A")
       ''-j ${toString (cfg.faxqclean.doneqMinutes*60)}''
       ''-d ${toString (cfg.faxqclean.docqMinutes*60)}''
     ];
   };
 
   mkFaxgettyService = { name, ... }:
-    lib.nameValuePair ''hylafax-faxgetty@${name}'' rec {
+    lib.nameValuePair "hylafax-faxgetty@${name}" rec {
       description = "HylaFAX faxgetty for %I";
       documentation = [ "man:faxgetty(8)" ];
       bindsTo = [ "dev-%i.device" ];
@@ -221,7 +221,7 @@ let
       after = bindsTo ++ requires;
       before = [ "hylafax-faxq.service" "getty.target" ];
       unitConfig.StopWhenUnneeded = true;
-      unitConfig.AssertFileNotEmpty = ''${cfg.spoolAreaPath}/etc/config.%I'';
+      unitConfig.AssertFileNotEmpty = "${cfg.spoolAreaPath}/etc/config.%I";
       serviceConfig.UtmpIdentifier = "%I";
       serviceConfig.TTYPath = "/dev/%I";
       serviceConfig.Restart = "always";
diff --git a/nixpkgs/nixos/modules/services/networking/iwd.nix b/nixpkgs/nixos/modules/services/networking/iwd.nix
index 6be67a8b96f4..99e5e78badd2 100644
--- a/nixpkgs/nixos/modules/services/networking/iwd.nix
+++ b/nixpkgs/nixos/modules/services/networking/iwd.nix
@@ -22,6 +22,11 @@ in {
 
     systemd.packages = [ pkgs.iwd ];
 
+    systemd.network.links."80-iwd" = {
+      matchConfig.Type = "wlan";
+      linkConfig.NamePolicy = "keep kernel";
+    };
+
     systemd.services.iwd.wantedBy = [ "multi-user.target" ];
   };
 
diff --git a/nixpkgs/nixos/modules/services/networking/kippo.nix b/nixpkgs/nixos/modules/services/networking/kippo.nix
index 553415a2f329..6fedb0a270f4 100644
--- a/nixpkgs/nixos/modules/services/networking/kippo.nix
+++ b/nixpkgs/nixos/modules/services/networking/kippo.nix
@@ -17,37 +17,37 @@ in
       enable = mkOption {
         default = false;
         type = types.bool;
-        description = ''Enable the kippo honeypot ssh server.'';
+        description = "Enable the kippo honeypot ssh server.";
       };
       port = mkOption {
         default = 2222;
         type = types.int;
-        description = ''TCP port number for kippo to bind to.'';
+        description = "TCP port number for kippo to bind to.";
       };
       hostname = mkOption {
         default = "nas3";
         type = types.str;
-        description = ''Hostname for kippo to present to SSH login'';
+        description = "Hostname for kippo to present to SSH login";
       };
       varPath = mkOption {
         default = "/var/lib/kippo";
         type = types.path;
-        description = ''Path of read/write files needed for operation and configuration.'';
+        description = "Path of read/write files needed for operation and configuration.";
       };
       logPath = mkOption {
         default = "/var/log/kippo";
         type = types.path;
-        description = ''Path of log files needed for operation and configuration.'';
+        description = "Path of log files needed for operation and configuration.";
       };
       pidPath = mkOption {
         default = "/run/kippo";
         type = types.path;
-        description = ''Path of pid files needed for operation.'';
+        description = "Path of pid files needed for operation.";
       };
       extraConfig = mkOption {
         default = "";
         type = types.lines;
-        description = ''Extra verbatim configuration added to the end of kippo.cfg.'';
+        description = "Extra verbatim configuration added to the end of kippo.cfg.";
       };
     };
 
diff --git a/nixpkgs/nixos/modules/services/networking/murmur.nix b/nixpkgs/nixos/modules/services/networking/murmur.nix
index c6e5649ec479..b03630208df8 100644
--- a/nixpkgs/nixos/modules/services/networking/murmur.nix
+++ b/nixpkgs/nixos/modules/services/networking/murmur.nix
@@ -109,6 +109,13 @@ in
         description = "Host to bind to. Defaults binding on all addresses.";
       };
 
+      package = mkOption {
+        type = types.package;
+        default = pkgs.murmur;
+        defaultText = "pkgs.murmur";
+        description = "Overridable attribute of the murmur package to use.";
+      };
+
       password = mkOption {
         type = types.str;
         default = "";
@@ -299,7 +306,7 @@ in
         Type = if forking then "forking" else "simple";
         PIDFile = mkIf forking "/run/murmur/murmurd.pid";
         EnvironmentFile = mkIf (cfg.environmentFile != null) cfg.environmentFile;
-        ExecStart = "${pkgs.murmur}/bin/murmurd -ini /run/murmur/murmurd.ini";
+        ExecStart = "${cfg.package}/bin/murmurd -ini /run/murmur/murmurd.ini";
         Restart = "always";
         RuntimeDirectory = "murmur";
         RuntimeDirectoryMode = "0700";
diff --git a/nixpkgs/nixos/modules/services/networking/nomad.nix b/nixpkgs/nixos/modules/services/networking/nomad.nix
new file mode 100644
index 000000000000..9f1b443b89bc
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/networking/nomad.nix
@@ -0,0 +1,165 @@
+{ config, lib, pkgs, ... }:
+with lib;
+let
+  cfg = config.services.nomad;
+  format = pkgs.formats.json { };
+in
+{
+  ##### interface
+  options = {
+    services.nomad = {
+      enable = mkEnableOption "Nomad, a distributed, highly available, datacenter-aware scheduler";
+
+      package = mkOption {
+        type = types.package;
+        default = pkgs.nomad;
+        defaultText = "pkgs.nomad";
+        description = ''
+          The package used for the Nomad agent and CLI.
+        '';
+      };
+
+      extraPackages = mkOption {
+        type = types.listOf types.package;
+        default = [ ];
+        description = ''
+          Extra packages to add to <envar>PATH</envar> for the Nomad agent process.
+        '';
+        example = literalExample ''
+          with pkgs; [ cni-plugins ]
+        '';
+      };
+
+      dropPrivileges = mkOption {
+        type = types.bool;
+        default = true;
+        description = ''
+          Whether the nomad agent should be run as a non-root nomad user.
+        '';
+      };
+
+      enableDocker = mkOption {
+        type = types.bool;
+        default = true;
+        description = ''
+          Enable Docker support. Needed for Nomad's docker driver.
+
+          Note that the docker group membership is effectively equivalent
+          to being root, see https://github.com/moby/moby/issues/9976.
+        '';
+      };
+
+      extraSettingsPaths = mkOption {
+        type = types.listOf types.path;
+        default = [];
+        description = ''
+          Additional settings paths used to configure nomad. These can be files or directories.
+        '';
+        example = literalExample ''
+          [ "/etc/nomad-mutable.json" "/run/keys/nomad-with-secrets.json" "/etc/nomad/config.d" ]
+        '';
+      };
+
+      settings = mkOption {
+        type = format.type;
+        default = {};
+        description = ''
+          Configuration for Nomad. See the <link xlink:href="https://www.nomadproject.io/docs/configuration">documentation</link>
+          for supported values.
+
+          Notes about <literal>data_dir</literal>:
+
+          If <literal>data_dir</literal> is set to a value other than the
+          default value of <literal>"/var/lib/nomad"</literal> it is the Nomad
+          cluster manager's responsibility to make sure that this directory
+          exists and has the appropriate permissions.
+
+          Additionally, if <literal>dropPrivileges</literal> is
+          <literal>true</literal> then <literal>data_dir</literal>
+          <emphasis>cannot</emphasis> be customized. Setting
+          <literal>dropPrivileges</literal> to <literal>true</literal> enables
+          the <literal>DynamicUser</literal> feature of systemd which directly
+          manages and operates on <literal>StateDirectory</literal>.
+        '';
+        example = literalExample ''
+          {
+            # A minimal config example:
+            server = {
+              enabled = true;
+              bootstrap_expect = 1; # for demo; no fault tolerance
+            };
+            client = {
+              enabled = true;
+            };
+          }
+        '';
+      };
+    };
+  };
+
+  ##### implementation
+  config = mkIf cfg.enable {
+    services.nomad.settings = {
+      # Agrees with `StateDirectory = "nomad"` set below.
+      data_dir = mkDefault "/var/lib/nomad";
+    };
+
+    environment = {
+      etc."nomad.json".source = format.generate "nomad.json" cfg.settings;
+      systemPackages = [ cfg.package ];
+    };
+
+    systemd.services.nomad = {
+      description = "Nomad";
+      wantedBy = [ "multi-user.target" ];
+      wants = [ "network-online.target" ];
+      after = [ "network-online.target" ];
+      restartTriggers = [ config.environment.etc."nomad.json".source ];
+
+      path = cfg.extraPackages ++ (with pkgs; [
+        # Client mode requires at least the following:
+        coreutils
+        iproute
+        iptables
+      ]);
+
+      serviceConfig = mkMerge [
+        {
+          DynamicUser = cfg.dropPrivileges;
+          ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
+          ExecStart = "${cfg.package}/bin/nomad agent -config=/etc/nomad.json" +
+            concatMapStrings (path: " -config=${path}") cfg.extraSettingsPaths;
+          KillMode = "process";
+          KillSignal = "SIGINT";
+          LimitNOFILE = 65536;
+          LimitNPROC = "infinity";
+          OOMScoreAdjust = -1000;
+          Restart = "on-failure";
+          RestartSec = 2;
+          TasksMax = "infinity";
+        }
+        (mkIf cfg.enableDocker {
+          SupplementaryGroups = "docker"; # space-separated string
+        })
+        (mkIf (cfg.settings.data_dir == "/var/lib/nomad") {
+          StateDirectory = "nomad";
+        })
+      ];
+
+      unitConfig = {
+        StartLimitIntervalSec = 10;
+        StartLimitBurst = 3;
+      };
+    };
+
+    assertions = [
+      {
+        assertion = cfg.dropPrivileges -> cfg.settings.data_dir == "/var/lib/nomad";
+        message = "settings.data_dir must be equal to \"/var/lib/nomad\" if dropPrivileges is true";
+      }
+    ];
+
+    # Docker support requires the Docker daemon to be running.
+    virtualisation.docker.enable = mkIf cfg.enableDocker true;
+  };
+}
diff --git a/nixpkgs/nixos/modules/services/networking/ntp/chrony.nix b/nixpkgs/nixos/modules/services/networking/ntp/chrony.nix
index e6fa48daf46c..96c6444c23a1 100644
--- a/nixpkgs/nixos/modules/services/networking/ntp/chrony.nix
+++ b/nixpkgs/nixos/modules/services/networking/ntp/chrony.nix
@@ -4,13 +4,14 @@ with lib;
 
 let
   cfg = config.services.chrony;
+  chronyPkg = cfg.package;
 
-  stateDir = "/var/lib/chrony";
+  stateDir = cfg.directory;
   driftFile = "${stateDir}/chrony.drift";
   keyFile = "${stateDir}/chrony.keys";
 
   configFile = pkgs.writeText "chrony.conf" ''
-    ${concatMapStringsSep "\n" (server: "server " + server + " iburst") cfg.servers}
+    ${concatMapStringsSep "\n" (server: "server " + server + " " + cfg.serverOption + optionalString (cfg.enableNTS) " nts") cfg.servers}
 
     ${optionalString
       (cfg.initstepslew.enabled && (cfg.servers != []))
@@ -19,6 +20,7 @@ let
 
     driftfile ${driftFile}
     keyfile ${keyFile}
+    ${optionalString (cfg.enableNTS) "ntsdumpdir ${stateDir}"}
 
     ${optionalString (!config.time.hardwareClockInLocalTime) "rtconutc"}
 
@@ -39,14 +41,48 @@ in
         '';
       };
 
+      package = mkOption {
+        type = types.package;
+        default = pkgs.chrony;
+        defaultText = "pkgs.chrony";
+        description = ''
+          Which chrony package to use.
+        '';
+      };
+
       servers = mkOption {
         default = config.networking.timeServers;
+        type = types.listOf types.str;
         description = ''
           The set of NTP servers from which to synchronise.
         '';
       };
 
+      serverOption = mkOption {
+        default = "iburst";
+        type = types.enum [ "iburst" "offline" ];
+        description = ''
+          Set option for server directives.
+
+          Use "iburst" to rapidly poll on startup. Recommended if your machine
+          is consistently online.
+
+          Use "offline" to prevent polling on startup. Recommended if your
+          machine boots offline or is otherwise frequently offline.
+        '';
+      };
+
+      enableNTS = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Whether to enable Network Time Security authentication.
+          Make sure it is supported by your selected NTP server(s).
+        '';
+      };
+
       initstepslew = mkOption {
+        type = types.attrsOf (types.either types.bool types.int);
         default = {
           enabled = true;
           threshold = 1000; # by default, same threshold as 'ntpd -g' (1000s)
@@ -58,6 +94,12 @@ in
         '';
       };
 
+      directory = mkOption {
+        type = types.str;
+        default = "/var/lib/chrony";
+        description = "Directory where chrony state is stored.";
+      };
+
       extraConfig = mkOption {
         type = types.lines;
         default = "";
@@ -79,7 +121,7 @@ in
   config = mkIf cfg.enable {
     meta.maintainers = with lib.maintainers; [ thoughtpolice ];
 
-    environment.systemPackages = [ pkgs.chrony ];
+    environment.systemPackages = [ chronyPkg ];
 
     users.groups.chrony.gid = config.ids.gids.chrony;
 
@@ -109,12 +151,12 @@ in
         after    = [ "network.target" ];
         conflicts = [ "ntpd.service" "systemd-timesyncd.service" ];
 
-        path = [ pkgs.chrony ];
+        path = [ chronyPkg ];
 
         unitConfig.ConditionCapability = "CAP_SYS_TIME";
         serviceConfig =
           { Type = "simple";
-            ExecStart = "${pkgs.chrony}/bin/chronyd ${chronyFlags}";
+            ExecStart = "${chronyPkg}/bin/chronyd ${chronyFlags}";
 
             ProtectHome = "yes";
             ProtectSystem = "full";
diff --git a/nixpkgs/nixos/modules/services/networking/ntp/ntpd.nix b/nixpkgs/nixos/modules/services/networking/ntp/ntpd.nix
index 51398851adc6..861b0db01a48 100644
--- a/nixpkgs/nixos/modules/services/networking/ntp/ntpd.nix
+++ b/nixpkgs/nixos/modules/services/networking/ntp/ntpd.nix
@@ -79,6 +79,7 @@ in
 
       servers = mkOption {
         default = config.networking.timeServers;
+        type = types.listOf types.str;
         description = ''
           The set of NTP servers from which to synchronise.
         '';
diff --git a/nixpkgs/nixos/modules/services/networking/owamp.nix b/nixpkgs/nixos/modules/services/networking/owamp.nix
index 637ed618b893..baf64347b099 100644
--- a/nixpkgs/nixos/modules/services/networking/owamp.nix
+++ b/nixpkgs/nixos/modules/services/networking/owamp.nix
@@ -10,7 +10,7 @@ in
   ###### interface
 
   options = {
-    services.owamp.enable = mkEnableOption ''Enable OWAMP server'';
+    services.owamp.enable = mkEnableOption "Enable OWAMP server";
   };
 
 
diff --git a/nixpkgs/nixos/modules/services/networking/privoxy.nix b/nixpkgs/nixos/modules/services/networking/privoxy.nix
index e3b34cb0c616..7caae3282032 100644
--- a/nixpkgs/nixos/modules/services/networking/privoxy.nix
+++ b/nixpkgs/nixos/modules/services/networking/privoxy.nix
@@ -16,7 +16,7 @@ let
     ${concatMapStrings (f: "actionsfile ${f}\n") cfg.actionsFiles}
     ${concatMapStrings (f: "filterfile ${f}\n") cfg.filterFiles}
   '' + optionalString cfg.enableTor ''
-    forward-socks4a / ${config.services.tor.client.socksListenAddressFaster} .
+    forward-socks5t / 127.0.0.1:9063 .
     toggle 1
     enable-remote-toggle 0
     enable-edit-actions 0
@@ -123,6 +123,11 @@ in
       serviceConfig.ProtectSystem = "full";
     };
 
+    services.tor.settings.SOCKSPort = mkIf cfg.enableTor [
+      # Route HTTP traffic over a faster port (without IsolateDestAddr).
+      { addr = "127.0.0.1"; port = 9063; IsolateDestAddr = false; }
+    ];
+
   };
 
   meta.maintainers = with lib.maintainers; [ rnhmjoj ];
diff --git a/nixpkgs/nixos/modules/services/networking/quassel.nix b/nixpkgs/nixos/modules/services/networking/quassel.nix
index da723ec86adf..2958fb9a8b33 100644
--- a/nixpkgs/nixos/modules/services/networking/quassel.nix
+++ b/nixpkgs/nixos/modules/services/networking/quassel.nix
@@ -61,7 +61,7 @@ in
       };
 
       dataDir = mkOption {
-        default = ''/home/${user}/.config/quassel-irc.org'';
+        default = "/home/${user}/.config/quassel-irc.org";
         description = ''
           The directory holding configuration files, the SQlite database and the SSL Cert.
         '';
diff --git a/nixpkgs/nixos/modules/services/networking/searx.nix b/nixpkgs/nixos/modules/services/networking/searx.nix
index 60fb3d5d6d44..a515e4a3dc3b 100644
--- a/nixpkgs/nixos/modules/services/networking/searx.nix
+++ b/nixpkgs/nixos/modules/services/networking/searx.nix
@@ -1,34 +1,114 @@
-{ config, lib, pkgs, ... }:
+{ options, config, lib, pkgs, ... }:
 
 with lib;
 
 let
-
+  runDir = "/run/searx";
   cfg = config.services.searx;
 
-  configFile = cfg.configFile;
+  generateConfig = ''
+    cd ${runDir}
+
+    # write NixOS settings as JSON
+    cat <<'EOF' > settings.yml
+      ${builtins.toJSON cfg.settings}
+    EOF
+
+    # substitute environment variables
+    env -0 | while IFS='=' read -r -d ''' n v; do
+      sed "s#@$n@#$v#g" -i settings.yml
+    done
+
+    # set strict permissions
+    chmod 400 settings.yml
+  '';
+
+  settingType = with types; (oneOf
+    [ bool int float str
+      (listOf settingType)
+      (attrsOf settingType)
+    ]) // { description = "JSON value"; };
 
 in
 
 {
 
+  imports = [
+    (mkRenamedOptionModule
+      [ "services" "searx" "configFile" ]
+      [ "services" "searx" "settingsFile" ])
+  ];
+
   ###### interface
 
   options = {
 
     services.searx = {
 
-      enable = mkEnableOption
-        "the searx server. See https://github.com/asciimoo/searx";
+      enable = mkOption {
+        type = types.bool;
+        default = false;
+        relatedPackages = [ "searx" ];
+        description = "Whether to enable Searx, the meta search engine.";
+      };
 
-      configFile = mkOption {
+      environmentFile = mkOption {
         type = types.nullOr types.path;
         default = null;
-        description = "
-          The path of the Searx server configuration file. If no file
-          is specified, a default file is used (default config file has
-          debug mode enabled).
-        ";
+        description = ''
+          Environment file (see <literal>systemd.exec(5)</literal>
+          "EnvironmentFile=" section for the syntax) to define variables for
+          Searx. This option can be used to safely include secret keys into the
+          Searx configuration.
+        '';
+      };
+
+      settings = mkOption {
+        type = types.attrsOf settingType;
+        default = { };
+        example = literalExample ''
+          { server.port = 8080;
+            server.bind_address = "0.0.0.0";
+            server.secret_key = "@SEARX_SECRET_KEY@";
+
+            engines = lib.singleton
+              { name = "wolframalpha";
+                shortcut = "wa";
+                api_key = "@WOLFRAM_API_KEY@";
+                engine = "wolframalpha_api";
+              };
+          }
+        '';
+        description = ''
+          Searx settings. These will be merged with (taking precedence over)
+          the default configuration. It's also possible to refer to
+          environment variables
+          (defined in <xref linkend="opt-services.searx.environmentFile"/>)
+          using the syntax <literal>@VARIABLE_NAME@</literal>.
+          <note>
+            <para>
+              For available settings, see the Searx
+              <link xlink:href="https://searx.github.io/searx/admin/settings.html">docs</link>.
+            </para>
+          </note>
+        '';
+      };
+
+      settingsFile = mkOption {
+        type = types.path;
+        default = "${runDir}/settings.yml";
+        description = ''
+          The path of the Searx server settings.yml file. If no file is
+          specified, a default file is used (default config file has debug mode
+          enabled). Note: setting this options overrides
+          <xref linkend="opt-services.searx.settings"/>.
+          <warning>
+            <para>
+              This file, along with any secret key it contains, will be copied
+              into the world-readable Nix store.
+            </para>
+          </warning>
+        '';
       };
 
       package = mkOption {
@@ -38,6 +118,38 @@ in
         description = "searx package to use.";
       };
 
+      runInUwsgi = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Whether to run searx in uWSGI as a "vassal", instead of using its
+          built-in HTTP server. This is the recommended mode for public or
+          large instances, but is unecessary for LAN or local-only use.
+          <warning>
+            <para>
+              The built-in HTTP server logs all queries by default.
+            </para>
+          </warning>
+        '';
+      };
+
+      uwsgiConfig = mkOption {
+        type = options.services.uwsgi.instance.type;
+        default = { http = ":8080"; };
+        example = literalExample ''
+          {
+            disable-logging = true;
+            http = ":8080";                   # serve via HTTP...
+            socket = "/run/searx/searx.sock"; # ...or UNIX socket
+          }
+        '';
+        description = ''
+          Additional configuration of the uWSGI vassal running searx. It
+          should notably specify on which interfaces and ports the vassal
+          should listen.
+        '';
+      };
+
     };
 
   };
@@ -45,36 +157,74 @@ in
 
   ###### implementation
 
-  config = mkIf config.services.searx.enable {
+  config = mkIf cfg.enable {
+    environment.systemPackages = [ cfg.package ];
 
     users.users.searx =
-      { uid = config.ids.uids.searx;
-        description = "Searx user";
-        createHome = true;
-        home = "/var/lib/searx";
+      { description = "Searx daemon user";
+        group = "searx";
+        isSystemUser = true;
       };
 
-    users.groups.searx =
-      { gid = config.ids.gids.searx;
+    users.groups.searx = { };
+
+    systemd.services.searx-init = {
+      description = "Initialise Searx settings";
+      serviceConfig = {
+        Type = "oneshot";
+        RemainAfterExit = true;
+        User = "searx";
+        RuntimeDirectory = "searx";
+        RuntimeDirectoryMode = "750";
+      } // optionalAttrs (cfg.environmentFile != null)
+        { EnvironmentFile = builtins.toPath cfg.environmentFile; };
+      script = generateConfig;
+    };
+
+    systemd.services.searx = mkIf (!cfg.runInUwsgi) {
+      description = "Searx server, the meta search engine.";
+      wantedBy = [ "network.target" "multi-user.target" ];
+      requires = [ "searx-init.service" ];
+      after = [ "searx-init.service" ];
+      serviceConfig = {
+        User  = "searx";
+        Group = "searx";
+        ExecStart = "${cfg.package}/bin/searx-run";
+      } // optionalAttrs (cfg.environmentFile != null)
+        { EnvironmentFile = builtins.toPath cfg.environmentFile; };
+      environment.SEARX_SETTINGS_PATH = cfg.settingsFile;
+    };
+
+    systemd.services.uwsgi = mkIf (cfg.runInUwsgi)
+      { requires = [ "searx-init.service" ];
+        after = [ "searx-init.service" ];
       };
 
-    systemd.services.searx =
-      {
-        description = "Searx server, the meta search engine.";
-        after = [ "network.target" ];
-        wantedBy = [ "multi-user.target" ];
-        serviceConfig = {
-          User = "searx";
-          ExecStart = "${cfg.package}/bin/searx-run";
-        };
-      } // (optionalAttrs (configFile != null) {
-        environment.SEARX_SETTINGS_PATH = configFile;
-      });
+    services.searx.settings = {
+      # merge NixOS settings with defaults settings.yml
+      use_default_settings = mkDefault true;
+    };
 
-    environment.systemPackages = [ cfg.package ];
+    services.uwsgi = mkIf (cfg.runInUwsgi) {
+      enable = true;
+      plugins = [ "python3" ];
+
+      instance.type = "emperor";
+      instance.vassals.searx = {
+        type = "normal";
+        strict = true;
+        immediate-uid = "searx";
+        immediate-gid = "searx";
+        lazy-apps = true;
+        enable-threads = true;
+        module = "searx.webapp";
+        env = [ "SEARX_SETTINGS_PATH=${cfg.settingsFile}" ];
+        pythonPackages = self: [ cfg.package ];
+      } // cfg.uwsgiConfig;
+    };
 
   };
 
-  meta.maintainers = with lib.maintainers; [ rnhmjoj ];
+  meta.maintainers = with maintainers; [ rnhmjoj ];
 
 }
diff --git a/nixpkgs/nixos/modules/services/networking/smokeping.nix b/nixpkgs/nixos/modules/services/networking/smokeping.nix
index 37ee2a803890..0747ff6dd5a9 100644
--- a/nixpkgs/nixos/modules/services/networking/smokeping.nix
+++ b/nixpkgs/nixos/modules/services/networking/smokeping.nix
@@ -303,7 +303,7 @@ in
         ${cfg.package}/bin/smokeping --check --config=${configPath}
         ${cfg.package}/bin/smokeping --static --config=${configPath}
       '';
-      script = ''${cfg.package}/bin/smokeping --config=${configPath} --nodaemon'';
+      script = "${cfg.package}/bin/smokeping --config=${configPath} --nodaemon";
     };
     systemd.services.thttpd = mkIf cfg.webService {
       wantedBy = [ "multi-user.target"];
diff --git a/nixpkgs/nixos/modules/services/networking/ssh/lshd.nix b/nixpkgs/nixos/modules/services/networking/ssh/lshd.nix
index 41d0584080e4..e46d62bf1e82 100644
--- a/nixpkgs/nixos/modules/services/networking/ssh/lshd.nix
+++ b/nixpkgs/nixos/modules/services/networking/ssh/lshd.nix
@@ -56,25 +56,25 @@ in
       syslog = mkOption {
         type = types.bool;
         default = true;
-        description = ''Whether to enable syslog output.'';
+        description = "Whether to enable syslog output.";
       };
 
       passwordAuthentication = mkOption {
         type = types.bool;
         default = true;
-        description = ''Whether to enable password authentication.'';
+        description = "Whether to enable password authentication.";
       };
 
       publicKeyAuthentication = mkOption {
         type = types.bool;
         default = true;
-        description = ''Whether to enable public key authentication.'';
+        description = "Whether to enable public key authentication.";
       };
 
       rootLogin = mkOption {
         type = types.bool;
         default = false;
-        description = ''Whether to enable remote root login.'';
+        description = "Whether to enable remote root login.";
       };
 
       loginShell = mkOption {
@@ -96,13 +96,13 @@ in
       tcpForwarding = mkOption {
         type = types.bool;
         default = true;
-        description = ''Whether to enable TCP/IP forwarding.'';
+        description = "Whether to enable TCP/IP forwarding.";
       };
 
       x11Forwarding = mkOption {
         type = types.bool;
         default = true;
-        description = ''Whether to enable X11 forwarding.'';
+        description = "Whether to enable X11 forwarding.";
       };
 
       subsystems = mkOption {
diff --git a/nixpkgs/nixos/modules/services/networking/strongswan-swanctl/swanctl-params.nix b/nixpkgs/nixos/modules/services/networking/strongswan-swanctl/swanctl-params.nix
index 1d1e0bd1ca19..8ae62931a8f9 100644
--- a/nixpkgs/nixos/modules/services/networking/strongswan-swanctl/swanctl-params.nix
+++ b/nixpkgs/nixos/modules/services/networking/strongswan-swanctl/swanctl-params.nix
@@ -1273,7 +1273,7 @@ in {
         provided the user is prompted during an interactive
         <literal>--load-creds</literal> call.
       '';
-    } ''Definition for a private key that's stored on a token/smartcard/TPM.'';
+    } "Definition for a private key that's stored on a token/smartcard/TPM.";
 
   };
 
diff --git a/nixpkgs/nixos/modules/services/networking/supybot.nix b/nixpkgs/nixos/modules/services/networking/supybot.nix
index 7a62e04ec7c4..864c3319c547 100644
--- a/nixpkgs/nixos/modules/services/networking/supybot.nix
+++ b/nixpkgs/nixos/modules/services/networking/supybot.nix
@@ -70,7 +70,7 @@ in
           value must be a function which receives the attrset defined
           in <varname>python3Packages</varname> as the sole argument.
         '';
-        example = literalExample ''p: [ p.lxml p.requests ]'';
+        example = literalExample "p: [ p.lxml p.requests ]";
       };
 
     };
diff --git a/nixpkgs/nixos/modules/services/networking/wpa_supplicant.nix b/nixpkgs/nixos/modules/services/networking/wpa_supplicant.nix
index 395139879036..61482596763a 100644
--- a/nixpkgs/nixos/modules/services/networking/wpa_supplicant.nix
+++ b/nixpkgs/nixos/modules/services/networking/wpa_supplicant.nix
@@ -14,8 +14,8 @@ let
         then ''"${psk}"''
         else pskRaw;
       baseAuth = if key != null
-        then ''psk=${key}''
-        else ''key_mgmt=NONE'';
+        then "psk=${key}"
+        else "key_mgmt=NONE";
     in ''
       network={
         ssid="${ssid}"
diff --git a/nixpkgs/nixos/modules/services/security/fprintd.nix b/nixpkgs/nixos/modules/services/security/fprintd.nix
index cbac4ef05b8d..48f8a9616c3e 100644
--- a/nixpkgs/nixos/modules/services/security/fprintd.nix
+++ b/nixpkgs/nixos/modules/services/security/fprintd.nix
@@ -43,9 +43,9 @@ in
 
   config = mkIf cfg.enable {
 
-    services.dbus.packages = [ pkgs.fprintd ];
+    services.dbus.packages = [ cfg.package ];
 
-    environment.systemPackages = [ pkgs.fprintd ];
+    environment.systemPackages = [ cfg.package ];
 
     systemd.packages = [ cfg.package ];
 
diff --git a/nixpkgs/nixos/modules/services/security/tor.nix b/nixpkgs/nixos/modules/services/security/tor.nix
index 1cceee065b1b..54c2c2dea23a 100644
--- a/nixpkgs/nixos/modules/services/security/tor.nix
+++ b/nixpkgs/nixos/modules/services/security/tor.nix
@@ -1,297 +1,300 @@
 { config, lib, pkgs, ... }:
 
+with builtins;
 with lib;
 
 let
   cfg = config.services.tor;
-  torDirectory = "/var/lib/tor";
-  torRunDirectory = "/run/tor";
-
-  opt    = name: value: optionalString (value != null) "${name} ${value}";
-  optint = name: value: optionalString (value != null && value != 0)    "${name} ${toString value}";
-
-  isolationOptions = {
-    type = types.listOf (types.enum [
-      "IsolateClientAddr"
-      "IsolateSOCKSAuth"
-      "IsolateClientProtocol"
-      "IsolateDestPort"
-      "IsolateDestAddr"
+  stateDir = "/var/lib/tor";
+  runDir = "/run/tor";
+  descriptionGeneric = option: ''
+    See <link xlink:href="https://2019.www.torproject.org/docs/tor-manual.html.en#${option}">torrc manual</link>.
+  '';
+  bindsPrivilegedPort =
+    any (p0:
+      let p1 = if p0 ? "port" then p0.port else p0; in
+      if p1 == "auto" then false
+      else let p2 = if isInt p1 then p1 else toInt p1; in
+        p1 != null && 0 < p2 && p2 < 1024)
+    (flatten [
+      cfg.settings.ORPort
+      cfg.settings.DirPort
+      cfg.settings.DNSPort
+      cfg.settings.ExtORPort
+      cfg.settings.HTTPTunnelPort
+      cfg.settings.NATDPort
+      cfg.settings.SOCKSPort
+      cfg.settings.TransPort
     ]);
+  optionBool = optionName: mkOption {
+    type = with types; nullOr bool;
+    default = null;
+    description = descriptionGeneric optionName;
+  };
+  optionInt = optionName: mkOption {
+    type = with types; nullOr int;
+    default = null;
+    description = descriptionGeneric optionName;
+  };
+  optionString = optionName: mkOption {
+    type = with types; nullOr str;
+    default = null;
+    description = descriptionGeneric optionName;
+  };
+  optionStrings = optionName: mkOption {
+    type = with types; listOf str;
     default = [];
-    example = [
-      "IsolateClientAddr"
-      "IsolateSOCKSAuth"
-      "IsolateClientProtocol"
-      "IsolateDestPort"
-      "IsolateDestAddr"
+    description = descriptionGeneric optionName;
+  };
+  optionAddress = mkOption {
+    type = with types; nullOr str;
+    default = null;
+    example = "0.0.0.0";
+    description = ''
+      IPv4 or IPv6 (if between brackets) address.
+    '';
+  };
+  optionUnix = mkOption {
+    type = with types; nullOr path;
+    default = null;
+    description = ''
+      Unix domain socket path to use.
+    '';
+  };
+  optionPort = mkOption {
+    type = with types; nullOr (oneOf [port (enum ["auto"])]);
+    default = null;
+  };
+  optionPorts = optionName: mkOption {
+    type = with types; listOf port;
+    default = [];
+    description = descriptionGeneric optionName;
+  };
+  optionIsolablePort = with types; oneOf [
+    port (enum ["auto"])
+    (submodule ({config, ...}: {
+      options = {
+        addr = optionAddress;
+        port = optionPort;
+        flags = optionFlags;
+        SessionGroup = mkOption { type = nullOr int; default = null; };
+      } // genAttrs isolateFlags (name: mkOption { type = types.bool; default = false; });
+      config = {
+        flags = filter (name: config.${name} == true) isolateFlags ++
+                optional (config.SessionGroup != null) "SessionGroup=${toString config.SessionGroup}";
+      };
+    }))
+  ];
+  optionIsolablePorts = optionName: mkOption {
+    default = [];
+    type = with types; either optionIsolablePort (listOf optionIsolablePort);
+    description = descriptionGeneric optionName;
+  };
+  isolateFlags = [
+    "IsolateClientAddr"
+    "IsolateClientProtocol"
+    "IsolateDestAddr"
+    "IsolateDestPort"
+    "IsolateSOCKSAuth"
+    "KeepAliveIsolateSOCKSAuth"
+  ];
+  optionSOCKSPort = doConfig: let
+    flags = [
+      "CacheDNS" "CacheIPv4DNS" "CacheIPv6DNS" "GroupWritable" "IPv6Traffic"
+      "NoDNSRequest" "NoIPv4Traffic" "NoOnionTraffic" "OnionTrafficOnly"
+      "PreferIPv6" "PreferIPv6Automap" "PreferSOCKSNoAuth" "UseDNSCache"
+      "UseIPv4Cache" "UseIPv6Cache" "WorldWritable"
+    ] ++ isolateFlags;
+    in with types; oneOf [
+      port (submodule ({config, ...}: {
+        options = {
+          unix = optionUnix;
+          addr = optionAddress;
+          port = optionPort;
+          flags = optionFlags;
+          SessionGroup = mkOption { type = nullOr int; default = null; };
+        } // genAttrs flags (name: mkOption { type = types.bool; default = false; });
+        config = mkIf doConfig { # Only add flags in SOCKSPort to avoid duplicates
+          flags = filter (name: config.${name} == true) flags ++
+                  optional (config.SessionGroup != null) "SessionGroup=${toString config.SessionGroup}";
+        };
+      }))
     ];
-    description = "Tor isolation options";
+  optionFlags = mkOption {
+    type = with types; listOf str;
+    default = [];
+  };
+  optionORPort = optionName: mkOption {
+    default = [];
+    example = 443;
+    type = with types; oneOf [port (enum ["auto"]) (listOf (oneOf [
+      port
+      (enum ["auto"])
+      (submodule ({config, ...}:
+        let flags = [ "IPv4Only" "IPv6Only" "NoAdvertise" "NoListen" ];
+        in {
+        options = {
+          addr = optionAddress;
+          port = optionPort;
+          flags = optionFlags;
+        } // genAttrs flags (name: mkOption { type = types.bool; default = false; });
+        config = {
+          flags = filter (name: config.${name} == true) flags;
+        };
+      }))
+    ]))];
+    description = descriptionGeneric optionName;
+  };
+  optionBandwith = optionName: mkOption {
+    type = with types; nullOr (either int str);
+    default = null;
+    description = descriptionGeneric optionName;
+  };
+  optionPath = optionName: mkOption {
+    type = with types; nullOr path;
+    default = null;
+    description = descriptionGeneric optionName;
   };
 
-
-  torRc = ''
-    User tor
-    DataDirectory ${torDirectory}
-    ${optionalString cfg.enableGeoIP ''
-      GeoIPFile ${cfg.package.geoip}/share/tor/geoip
-      GeoIPv6File ${cfg.package.geoip}/share/tor/geoip6
-    ''}
-
-    ${optint "ControlPort" cfg.controlPort}
-    ${optionalString cfg.controlSocket.enable "ControlPort unix:${torRunDirectory}/control GroupWritable RelaxDirModeCheck"}
-  ''
-  # Client connection config
-  + optionalString cfg.client.enable ''
-    SOCKSPort ${cfg.client.socksListenAddress} ${toString cfg.client.socksIsolationOptions}
-    SOCKSPort ${cfg.client.socksListenAddressFaster}
-    ${opt "SocksPolicy" cfg.client.socksPolicy}
-
-    ${optionalString cfg.client.transparentProxy.enable ''
-    TransPort ${cfg.client.transparentProxy.listenAddress} ${toString cfg.client.transparentProxy.isolationOptions}
-    ''}
-
-    ${optionalString cfg.client.dns.enable ''
-    DNSPort ${cfg.client.dns.listenAddress} ${toString cfg.client.dns.isolationOptions}
-    AutomapHostsOnResolve 1
-    AutomapHostsSuffixes ${concatStringsSep "," cfg.client.dns.automapHostsSuffixes}
-    ''}
-  ''
-  # Explicitly disable the SOCKS server if the client is disabled.  In
-  # particular, this makes non-anonymous hidden services possible.
-  + optionalString (! cfg.client.enable) ''
-  SOCKSPort 0
-  ''
-  # Relay config
-  + optionalString cfg.relay.enable ''
-    ORPort ${toString cfg.relay.port}
-    ${opt "Address" cfg.relay.address}
-    ${opt "Nickname" cfg.relay.nickname}
-    ${opt "ContactInfo" cfg.relay.contactInfo}
-
-    ${optint "RelayBandwidthRate" cfg.relay.bandwidthRate}
-    ${optint "RelayBandwidthBurst" cfg.relay.bandwidthBurst}
-    ${opt "AccountingMax" cfg.relay.accountingMax}
-    ${opt "AccountingStart" cfg.relay.accountingStart}
-
-    ${if (cfg.relay.role == "exit") then
-        opt "ExitPolicy" cfg.relay.exitPolicy
-      else
-        "ExitPolicy reject *:*"}
-
-    ${optionalString (elem cfg.relay.role ["bridge" "private-bridge"]) ''
-      BridgeRelay 1
-      ServerTransportPlugin ${concatStringsSep "," cfg.relay.bridgeTransports} exec ${pkgs.obfs4}/bin/obfs4proxy managed
-      ExtORPort auto
-      ${optionalString (cfg.relay.role == "private-bridge") ''
-        ExtraInfoStatistics 0
-        PublishServerDescriptor 0
-      ''}
-    ''}
-  ''
-  # Hidden services
-  + concatStrings (flip mapAttrsToList cfg.hiddenServices (n: v: ''
-    HiddenServiceDir ${torDirectory}/onion/${v.name}
-    ${optionalString (v.version != null) "HiddenServiceVersion ${toString v.version}"}
-    ${flip concatMapStrings v.map (p: ''
-      HiddenServicePort ${toString p.port} ${p.destination}
-    '')}
-    ${optionalString (v.authorizeClient != null) ''
-      HiddenServiceAuthorizeClient ${v.authorizeClient.authType} ${concatStringsSep "," v.authorizeClient.clientNames}
-    ''}
-  ''))
-  + cfg.extraConfig;
-
-  torRcFile = pkgs.writeText "torrc" torRc;
-
+  mkValueString = k: v:
+    if v == null then ""
+    else if isBool v then
+      (if v then "1" else "0")
+    else if v ? "unix" && v.unix != null then
+      "unix:"+v.unix +
+      optionalString (v ? "flags") (" " + concatStringsSep " " v.flags)
+    else if v ? "port" && v.port != null then
+      optionalString (v ? "addr" && v.addr != null) "${v.addr}:" +
+      toString v.port +
+      optionalString (v ? "flags") (" " + concatStringsSep " " v.flags)
+    else if k == "ServerTransportPlugin" then
+      optionalString (v.transports != []) "${concatStringsSep "," v.transports} exec ${v.exec}"
+    else if k == "HidServAuth" then
+      concatMapStringsSep "\n${k} " (settings: settings.onion + " " settings.auth) v
+    else generators.mkValueStringDefault {} v;
+  genTorrc = settings:
+    generators.toKeyValue {
+      listsAsDuplicateKeys = true;
+      mkKeyValue = k: generators.mkKeyValueDefault { mkValueString = mkValueString k; } " " k;
+    }
+    (lib.mapAttrs (k: v:
+      # Not necesssary, but prettier rendering
+      if elem k [ "AutomapHostsSuffixes" "DirPolicy" "ExitPolicy" "SocksPolicy" ]
+      && v != []
+      then concatStringsSep "," v
+      else v)
+    (lib.filterAttrs (k: v: !(v == null || v == ""))
+    settings));
+  torrc = pkgs.writeText "torrc" (
+    genTorrc cfg.settings +
+    concatStrings (mapAttrsToList (name: onion:
+      "HiddenServiceDir ${onion.path}\n" +
+      genTorrc onion.settings) cfg.relay.onionServices)
+  );
 in
 {
   imports = [
-    (mkRemovedOptionModule [ "services" "tor" "client" "privoxy" "enable" ] ''
-      Use services.privoxy.enable and services.privoxy.enableTor instead.
-    '')
-    (mkRenamedOptionModule [ "services" "tor" "relay" "portSpec" ] [ "services" "tor" "relay" "port" ])
+    (mkRenamedOptionModule [ "services" "tor" "client" "dns" "automapHostsSuffixes" ] [ "services" "tor" "settings" "AutomapHostsSuffixes" ])
+    (mkRemovedOptionModule [ "services" "tor" "client" "dns" "isolationOptions" ] "Use services.tor.settings.DNSPort instead.")
+    (mkRemovedOptionModule [ "services" "tor" "client" "dns" "listenAddress" ] "Use services.tor.settings.DNSPort instead.")
+    (mkRemovedOptionModule [ "services" "tor" "client" "privoxy" "enable" ] "Use services.privoxy.enable and services.privoxy.enableTor instead.")
+    (mkRemovedOptionModule [ "services" "tor" "client" "socksIsolationOptions" ] "Use services.tor.settings.SOCKSPort instead.")
+    (mkRemovedOptionModule [ "services" "tor" "client" "socksListenAddressFaster" ] "Use services.tor.settings.SOCKSPort instead.")
+    (mkRenamedOptionModule [ "services" "tor" "client" "socksPolicy" ] [ "services" "tor" "settings" "SocksPolicy" ])
+    (mkRemovedOptionModule [ "services" "tor" "client" "transparentProxy" "isolationOptions" ] "Use services.tor.settings.TransPort instead.")
+    (mkRemovedOptionModule [ "services" "tor" "client" "transparentProxy" "listenAddress" ] "Use services.tor.settings.TransPort instead.")
+    (mkRenamedOptionModule [ "services" "tor" "controlPort" ] [ "services" "tor" "settings" "ControlPort" ])
+    (mkRemovedOptionModule [ "services" "tor" "extraConfig" ] "Plese use services.tor.settings instead.")
+    (mkRenamedOptionModule [ "services" "tor" "hiddenServices" ] [ "services" "tor" "relay" "onionServices" ])
+    (mkRenamedOptionModule [ "services" "tor" "relay" "accountingMax" ] [ "services" "tor" "settings" "AccountingMax" ])
+    (mkRenamedOptionModule [ "services" "tor" "relay" "accountingStart" ] [ "services" "tor" "settings" "AccountingStart" ])
+    (mkRenamedOptionModule [ "services" "tor" "relay" "address" ] [ "services" "tor" "settings" "Address" ])
+    (mkRenamedOptionModule [ "services" "tor" "relay" "bandwidthBurst" ] [ "services" "tor" "settings" "BandwidthBurst" ])
+    (mkRenamedOptionModule [ "services" "tor" "relay" "bandwidthRate" ] [ "services" "tor" "settings" "BandwidthRate" ])
+    (mkRenamedOptionModule [ "services" "tor" "relay" "bridgeTransports" ] [ "services" "tor" "settings" "ServerTransportPlugin" "transports" ])
+    (mkRenamedOptionModule [ "services" "tor" "relay" "contactInfo" ] [ "services" "tor" "settings" "ContactInfo" ])
+    (mkRenamedOptionModule [ "services" "tor" "relay" "exitPolicy" ] [ "services" "tor" "settings" "ExitPolicy" ])
     (mkRemovedOptionModule [ "services" "tor" "relay" "isBridge" ] "Use services.tor.relay.role instead.")
     (mkRemovedOptionModule [ "services" "tor" "relay" "isExit" ] "Use services.tor.relay.role instead.")
+    (mkRenamedOptionModule [ "services" "tor" "relay" "nickname" ] [ "services" "tor" "settings" "Nickname" ])
+    (mkRenamedOptionModule [ "services" "tor" "relay" "port" ] [ "services" "tor" "settings" "ORPort" ])
+    (mkRenamedOptionModule [ "services" "tor" "relay" "portSpec" ] [ "services" "tor" "settings" "ORPort" ])
   ];
 
   options = {
     services.tor = {
-      enable = mkOption {
-        type = types.bool;
-        default = false;
-        description = ''
-          Enable the Tor daemon. By default, the daemon is run without
-          relay, exit, bridge or client connectivity.
-        '';
-      };
+      enable = mkEnableOption ''Tor daemon.
+        By default, the daemon is run without
+        relay, exit, bridge or client connectivity'';
+
+      openFirewall = mkEnableOption "opening of the relay port(s) in the firewall";
 
       package = mkOption {
         type = types.package;
         default = pkgs.tor;
         defaultText = "pkgs.tor";
         example = literalExample "pkgs.tor";
-        description = ''
-          Tor package to use
-        '';
+        description = "Tor package to use.";
       };
 
-      enableGeoIP = mkOption {
-        type = types.bool;
-        default = true;
-        description = ''
-          Whenever to configure Tor daemon to use GeoIP databases.
+      enableGeoIP = mkEnableOption ''use of GeoIP databases.
+        Disabling this will disable by-country statistics for bridges and relays
+        and some client and third-party software functionality'' // { default = true; };
 
-          Disabling this will disable by-country statistics for
-          bridges and relays and some client and third-party software
-          functionality.
-        '';
-      };
-
-      extraConfig = mkOption {
-        type = types.lines;
-        default = "";
-        description = ''
-          Extra configuration. Contents will be added verbatim to the
-          configuration file at the end.
-        '';
-      };
-
-      controlPort = mkOption {
-        type = types.nullOr (types.either types.int types.str);
-        default = null;
-        example = 9051;
-        description = ''
-          If set, Tor will accept connections on the specified port
-          and allow them to control the tor process.
-        '';
-      };
-
-      controlSocket = {
-        enable = mkOption {
-          type = types.bool;
-          default = false;
-          description = ''
-            Whether to enable Tor control socket. Control socket is created
-            in <literal>${torRunDirectory}/control</literal>
-          '';
-        };
-      };
+      controlSocket.enable = mkEnableOption ''control socket,
+        created in <literal>${runDir}/control</literal>'';
 
       client = {
-        enable = mkOption {
-          type = types.bool;
-          default = false;
-          description = ''
-            Whether to enable Tor daemon to route application
-            connections.  You might want to disable this if you plan
-            running a dedicated Tor relay.
-          '';
-        };
+        enable = mkEnableOption ''the routing of application connections.
+          You might want to disable this if you plan running a dedicated Tor relay'';
 
-        socksListenAddress = mkOption {
-          type = types.str;
-          default = "127.0.0.1:9050";
-          example = "192.168.0.1:9100";
-          description = ''
-            Bind to this address to listen for connections from
-            Socks-speaking applications. Provides strong circuit
-            isolation, separate circuit per IP address.
-          '';
-        };
+        transparentProxy.enable = mkEnableOption "transparent proxy";
+        dns.enable = mkEnableOption "DNS resolver";
 
-        socksListenAddressFaster = mkOption {
-          type = types.str;
-          default = "127.0.0.1:9063";
-          example = "192.168.0.1:9101";
+        socksListenAddress = mkOption {
+          type = optionSOCKSPort false;
+          default = {addr = "127.0.0.1"; port = 9050; IsolateDestAddr = true;};
+          example = {addr = "192.168.0.1"; port = 9090; IsolateDestAddr = true;};
           description = ''
             Bind to this address to listen for connections from
-            Socks-speaking applications. Same as
-            <option>socksListenAddress</option> but uses weaker
-            circuit isolation to provide performance suitable for a
-            web browser.
-           '';
-         };
-
-        socksPolicy = mkOption {
-          type = types.nullOr types.str;
-          default = null;
-          example = "accept 192.168.0.0/16, reject *";
-          description = ''
-            Entry policies to allow/deny SOCKS requests based on IP
-            address. First entry that matches wins. If no SocksPolicy
-            is set, we accept all (and only) requests from
-            <option>socksListenAddress</option>.
+            Socks-speaking applications.
           '';
         };
 
-        socksIsolationOptions = mkOption (isolationOptions // {
-          default = ["IsolateDestAddr"];
-        });
-
-        transparentProxy = {
-          enable = mkOption {
-            type = types.bool;
-            default = false;
-            description = "Whether to enable tor transparent proxy";
-          };
-
-          listenAddress = mkOption {
-            type = types.str;
-            default = "127.0.0.1:9040";
-            example = "192.168.0.1:9040";
-            description = ''
-              Bind transparent proxy to this address.
-            '';
-          };
-
-          isolationOptions = mkOption isolationOptions;
-        };
-
-        dns = {
-          enable = mkOption {
-            type = types.bool;
-            default = false;
-            description = "Whether to enable tor dns resolver";
-          };
-
-          listenAddress = mkOption {
-            type = types.str;
-            default = "127.0.0.1:9053";
-            example = "192.168.0.1:9053";
-            description = ''
-              Bind tor dns to this address.
-            '';
-          };
-
-          isolationOptions = mkOption isolationOptions;
-
-          automapHostsSuffixes = mkOption {
-            type = types.listOf types.str;
-            default = [".onion" ".exit"];
-            example = [".onion"];
-            description = "List of suffixes to use with automapHostsOnResolve";
+        onionServices = mkOption {
+          description = descriptionGeneric "HiddenServiceDir";
+          default = {};
+          example = {
+            "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" = {
+              clientAuthorizations = ["/run/keys/tor/alice.prv.x25519"];
+            };
           };
+          type = types.attrsOf (types.submodule ({name, config, ...}: {
+            options.clientAuthorizations = mkOption {
+              description = ''
+                Clients' authorizations for a v3 onion service,
+                as a list of files containing each one private key, in the format:
+                <screen>descriptor:x25519:&lt;base32-private-key&gt;</screen>
+              '' + descriptionGeneric "_client_authorization";
+              type = with types; listOf path;
+              default = [];
+              example = ["/run/keys/tor/alice.prv.x25519"];
+            };
+          }));
         };
       };
 
       relay = {
-        enable = mkOption {
-          type = types.bool;
-          default = false;
-          description = ''
-            Whether to enable relaying TOR traffic for others.
+        enable = mkEnableOption ''relaying of Tor traffic for others.
 
-            See <link xlink:href="https://www.torproject.org/docs/tor-doc-relay" />
-            for details.
+          See <link xlink:href="https://www.torproject.org/docs/tor-doc-relay" />
+          for details.
 
-            Setting this to true requires setting
-            <option>services.tor.relay.role</option>
-            and
-            <option>services.tor.relay.port</option>
-            options.
-          '';
-        };
+          Setting this to true requires setting
+          <option>services.tor.relay.role</option>
+          and
+          <option>services.tor.settings.ORPort</option>
+          options'';
 
         role = mkOption {
           type = types.enum [ "exit" "relay" "bridge" "private-bridge" ];
@@ -310,13 +313,13 @@ in
                 <important><para>
                   Running an exit relay may expose you to abuse
                   complaints. See
-                  <link xlink:href="https://www.torproject.org/faq.html.en#ExitPolicies" />
+                  <link xlink:href="https://www.torproject.org/faq.html.en#ExitPolicies"/>
                   for more info.
                 </para></important>
 
                 <para>
                   You can specify which services Tor users may access via
-                  your exit relay using <option>exitPolicy</option> option.
+                  your exit relay using <option>settings.ExitPolicy</option> option.
                 </para>
               </listitem>
             </varlistentry>
@@ -369,15 +372,14 @@ in
                 <important>
                   <para>
                     WARNING: THE FOLLOWING PARAGRAPH IS NOT LEGAL ADVICE.
-                    Consult with your lawer when in doubt.
+                    Consult with your lawyer when in doubt.
                   </para>
 
                   <para>
                     This role should be safe to use in most situations
                     (unless the act of forwarding traffic for others is
                     a punishable offence under your local laws, which
-                    would be pretty insane as it would make ISP
-                    illegal).
+                    would be pretty insane as it would make ISP illegal).
                   </para>
                 </important>
 
@@ -404,7 +406,7 @@ in
 
                 <para>
                   Use this if you want to run a private bridge, for
-                  example because you'll give out your bridge address
+                  example because you'll give out your bridge addr
                   manually to your friends.
                 </para>
 
@@ -426,269 +428,393 @@ in
           '';
         };
 
-        bridgeTransports = mkOption {
-          type = types.listOf types.str;
-          default = ["obfs4"];
-          example = ["obfs2" "obfs3" "obfs4" "scramblesuit"];
-          description = "List of pluggable transports";
-        };
-
-        nickname = mkOption {
-          type = types.str;
-          default = "anonymous";
-          description = ''
-            A unique handle for your TOR relay.
-          '';
-        };
-
-        contactInfo = mkOption {
-          type = types.nullOr types.str;
-          default = null;
-          example = "admin@relay.com";
-          description = ''
-            Contact information for the relay owner (e.g. a mail
-            address and GPG key ID).
-          '';
-        };
-
-        accountingMax = mkOption {
-          type = types.nullOr types.str;
-          default = null;
-          example = "450 GBytes";
-          description = ''
-            Specify maximum bandwidth allowed during an accounting period. This
-            allows you to limit overall tor bandwidth over some time period.
-            See the <literal>AccountingMax</literal> option by looking at the
-            tor manual <citerefentry><refentrytitle>tor</refentrytitle>
-            <manvolnum>1</manvolnum></citerefentry> for more.
-
-            Note this limit applies individually to upload and
-            download; if you specify <literal>"500 GBytes"</literal>
-            here, then you may transfer up to 1 TBytes of overall
-            bandwidth (500 GB upload, 500 GB download).
-          '';
-        };
-
-        accountingStart = mkOption {
-          type = types.nullOr types.str;
-          default = null;
-          example = "month 1 1:00";
-          description = ''
-            Specify length of an accounting period. This allows you to limit
-            overall tor bandwidth over some time period. See the
-            <literal>AccountingStart</literal> option by looking at the tor
-            manual <citerefentry><refentrytitle>tor</refentrytitle>
-            <manvolnum>1</manvolnum></citerefentry> for more.
-          '';
-        };
-
-        bandwidthRate = mkOption {
-          type = types.nullOr types.int;
-          default = null;
-          example = 100;
-          description = ''
-            Specify this to limit the bandwidth usage of relayed (server)
-            traffic. Your own traffic is still unthrottled. Units: bytes/second.
-          '';
-        };
-
-        bandwidthBurst = mkOption {
-          type = types.nullOr types.int;
-          default = cfg.relay.bandwidthRate;
-          example = 200;
-          description = ''
-            Specify this to allow bursts of the bandwidth usage of relayed (server)
-            traffic. The average usage will still be as specified in relayBandwidthRate.
-            Your own traffic is still unthrottled. Units: bytes/second.
-          '';
-        };
-
-        address = mkOption {
-          type    = types.nullOr types.str;
-          default = null;
-          example = "noname.example.com";
-          description = ''
-            The IP address or full DNS name for advertised address of your relay.
-            Leave unset and Tor will guess.
-          '';
-        };
-
-        port = mkOption {
-          type    = types.either types.int types.str;
-          example = 143;
-          description = ''
-            What port to advertise for Tor connections. This corresponds to the
-            <literal>ORPort</literal> section in the Tor manual; see
-            <citerefentry><refentrytitle>tor</refentrytitle>
-            <manvolnum>1</manvolnum></citerefentry> for more details.
-
-            At a minimum, you should just specify the port for the
-            relay to listen on; a common one like 143, 22, 80, or 443
-            to help Tor users who may have very restrictive port-based
-            firewalls.
-          '';
-        };
-
-        exitPolicy = mkOption {
-          type    = types.nullOr types.str;
-          default = null;
-          example = "accept *:6660-6667,reject *:*";
-          description = ''
-            A comma-separated list of exit policies. They're
-            considered first to last, and the first match wins. If you
-            want to _replace_ the default exit policy, end this with
-            either a reject *:* or an accept *:*. Otherwise, you're
-            _augmenting_ (prepending to) the default exit policy.
-            Leave commented to just use the default, which is
-            available in the man page or at
-            <link xlink:href="https://www.torproject.org/documentation.html" />.
-
-            Look at
-            <link xlink:href="https://www.torproject.org/faq-abuse.html#TypicalAbuses" />
-            for issues you might encounter if you use the default
-            exit policy.
-
-            If certain IPs and ports are blocked externally, e.g. by
-            your firewall, you should update your exit policy to
-            reflect this -- otherwise Tor users will be told that
-            those destinations are down.
-          '';
+        onionServices = mkOption {
+          description = descriptionGeneric "HiddenServiceDir";
+          default = {};
+          example = {
+            "example.org/www" = {
+              map = [ 80 ];
+              authorizedClients = [
+                "descriptor:x25519:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
+              ];
+            };
+          };
+          type = types.attrsOf (types.submodule ({name, config, ...}: {
+            options.path = mkOption {
+              type = types.path;
+              description = ''
+                Path where to store the data files of the hidden service.
+                If the <option>secretKey</option> is null
+                this defaults to <literal>${stateDir}/onion/$onion</literal>,
+                otherwise to <literal>${runDir}/onion/$onion</literal>.
+              '';
+            };
+            options.secretKey = mkOption {
+              type = with types; nullOr path;
+              default = null;
+              example = "/run/keys/tor/onion/expyuzz4wqqyqhjn/hs_ed25519_secret_key";
+              description = ''
+                Secret key of the onion service.
+                If null, Tor reuses any preexisting secret key (in <option>path</option>)
+                or generates a new one.
+                The associated public key and hostname are deterministically regenerated
+                from this file if they do not exist.
+              '';
+            };
+            options.authorizeClient = mkOption {
+              description = descriptionGeneric "HiddenServiceAuthorizeClient";
+              default = null;
+              type = types.nullOr (types.submodule ({...}: {
+                options = {
+                  authType = mkOption {
+                    type = types.enum [ "basic" "stealth" ];
+                    description = ''
+                      Either <literal>"basic"</literal> for a general-purpose authorization protocol
+                      or <literal>"stealth"</literal> for a less scalable protocol
+                      that also hides service activity from unauthorized clients.
+                    '';
+                  };
+                  clientNames = mkOption {
+                    type = with types; nonEmptyListOf (strMatching "[A-Za-z0-9+-_]+");
+                    description = ''
+                      Only clients that are listed here are authorized to access the hidden service.
+                      Generated authorization data can be found in <filename>${stateDir}/onion/$name/hostname</filename>.
+                      Clients need to put this authorization data in their configuration file using
+                      <xref linkend="opt-services.tor.settings.HidServAuth"/>.
+                    '';
+                  };
+                };
+              }));
+            };
+            options.authorizedClients = mkOption {
+              description = ''
+                Authorized clients for a v3 onion service,
+                as a list of public key, in the format:
+                <screen>descriptor:x25519:&lt;base32-public-key&gt;</screen>
+              '' + descriptionGeneric "_client_authorization";
+              type = with types; listOf str;
+              default = [];
+              example = ["descriptor:x25519:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"];
+            };
+            options.map = mkOption {
+              description = descriptionGeneric "HiddenServicePort";
+              type = with types; listOf (oneOf [
+                port (submodule ({...}: {
+                  options = {
+                    port = optionPort;
+                    target = mkOption {
+                      default = null;
+                      type = nullOr (submodule ({...}: {
+                        options = {
+                          unix = optionUnix;
+                          addr = optionAddress;
+                          port = optionPort;
+                        };
+                      }));
+                    };
+                  };
+                }))
+              ]);
+              apply = map (v: if isInt v then {port=v; target=null;} else v);
+            };
+            options.version = mkOption {
+              description = descriptionGeneric "HiddenServiceVersion";
+              type = with types; nullOr (enum [2 3]);
+              default = null;
+            };
+            options.settings = mkOption {
+              description = ''
+                Settings of the onion service.
+              '' + descriptionGeneric "_hidden_service_options";
+              default = {};
+              type = types.submodule {
+                freeformType = with types;
+                  (attrsOf (nullOr (oneOf [str int bool (listOf str)]))) // {
+                    description = "settings option";
+                  };
+                options.HiddenServiceAllowUnknownPorts = optionBool "HiddenServiceAllowUnknownPorts";
+                options.HiddenServiceDirGroupReadable = optionBool "HiddenServiceDirGroupReadable";
+                options.HiddenServiceExportCircuitID = mkOption {
+                  description = descriptionGeneric "HiddenServiceExportCircuitID";
+                  type = with types; nullOr (enum ["haproxy"]);
+                  default = null;
+                };
+                options.HiddenServiceMaxStreams = mkOption {
+                  description = descriptionGeneric "HiddenServiceMaxStreams";
+                  type = with types; nullOr (ints.between 0 65535);
+                  default = null;
+                };
+                options.HiddenServiceMaxStreamsCloseCircuit = optionBool "HiddenServiceMaxStreamsCloseCircuit";
+                options.HiddenServiceNumIntroductionPoints = mkOption {
+                  description = descriptionGeneric "HiddenServiceNumIntroductionPoints";
+                  type = with types; nullOr (ints.between 0 20);
+                  default = null;
+                };
+                options.HiddenServiceSingleHopMode = optionBool "HiddenServiceSingleHopMode";
+                options.RendPostPeriod = optionString "RendPostPeriod";
+              };
+            };
+            config = {
+              path = mkDefault ((if config.secretKey == null then stateDir else runDir) + "/onion/${name}");
+              settings.HiddenServiceVersion = config.version;
+              settings.HiddenServiceAuthorizeClient =
+                if config.authorizeClient != null then
+                  config.authorizeClient.authType + " " +
+                  concatStringsSep "," config.authorizeClient.clientNames
+                else null;
+              settings.HiddenServicePort = map (p: mkValueString "" p.port + " " + mkValueString "" p.target) config.map;
+            };
+          }));
         };
       };
 
-      hiddenServices = mkOption {
+      settings = mkOption {
         description = ''
-          A set of static hidden services that terminate their Tor
-          circuits at this node.
-
-          Every element in this set declares a virtual onion host.
-
-          You can specify your onion address by putting corresponding
-          private key to an appropriate place in ${torDirectory}.
-
-          For services without private keys in ${torDirectory} Tor
-          daemon will generate random key pairs (which implies random
-          onion addresses) on restart. The latter could take a while,
-          please be patient.
-
-          <note><para>
-            Hidden services can be useful even if you don't intend to
-            actually <emphasis>hide</emphasis> them, since they can
-            also be seen as a kind of NAT traversal mechanism.
-
-            E.g. the example will make your sshd, whatever runs on
-            "8080" and your mail server available from anywhere where
-            the Tor network is available (which, with the help from
-            bridges, is pretty much everywhere), even if both client
-            and server machines are behind NAT you have no control
-            over.
-          </para></note>
+          See <link xlink:href="https://2019.www.torproject.org/docs/tor-manual.html.en">torrc manual</link>
+          for documentation.
         '';
         default = {};
-        example = literalExample ''
-          { "my-hidden-service-example".map = [
-              { port = 22; }                # map ssh port to this machine's ssh
-              { port = 80; toPort = 8080; } # map http port to whatever runs on 8080
-              { port = "sip"; toHost = "mail.example.com"; toPort = "imap"; } # because we can
-            ];
-          }
-        '';
-        type = types.attrsOf (types.submodule ({name, ...}: {
-          options = {
-
-             name = mkOption {
-               type = types.str;
-               description = ''
-                 Name of this tor hidden service.
-
-                 This is purely descriptive.
-
-                 After restarting Tor daemon you should be able to
-                 find your .onion address in
-                 <literal>${torDirectory}/onion/$name/hostname</literal>.
-               '';
-             };
-
-             map = mkOption {
-               default = [];
-               description = "Port mapping for this hidden service.";
-               type = types.listOf (types.submodule ({config, ...}: {
-                 options = {
-
-                   port = mkOption {
-                     type = types.either types.int types.str;
-                     example = 80;
-                     description = ''
-                       Hidden service port to "bind to".
-                     '';
-                   };
-
-                   destination = mkOption {
-                     internal = true;
-                     type = types.str;
-                     description = "Forward these connections where?";
-                   };
-
-                   toHost = mkOption {
-                     type = types.str;
-                     default = "127.0.0.1";
-                     description = "Mapping destination host.";
-                   };
-
-                   toPort = mkOption {
-                     type = types.either types.int types.str;
-                     example = 8080;
-                     description = "Mapping destination port.";
-                   };
-
-                 };
-
-                 config = {
-                   toPort = mkDefault config.port;
-                   destination = mkDefault "${config.toHost}:${toString config.toPort}";
-                 };
-               }));
-             };
-
-             authorizeClient = mkOption {
-               default = null;
-               description = "If configured, the hidden service is accessible for authorized clients only.";
-               type = types.nullOr (types.submodule ({...}: {
-
-                 options = {
-
-                   authType = mkOption {
-                     type = types.enum [ "basic" "stealth" ];
-                     description = ''
-                       Either <literal>"basic"</literal> for a general-purpose authorization protocol
-                       or <literal>"stealth"</literal> for a less scalable protocol
-                       that also hides service activity from unauthorized clients.
-                     '';
-                   };
-
-                   clientNames = mkOption {
-                     type = types.nonEmptyListOf (types.strMatching "[A-Za-z0-9+-_]+");
-                     description = ''
-                       Only clients that are listed here are authorized to access the hidden service.
-                       Generated authorization data can be found in <filename>${torDirectory}/onion/$name/hostname</filename>.
-                       Clients need to put this authorization data in their configuration file using <literal>HidServAuth</literal>.
-                     '';
-                   };
-                 };
-               }));
-             };
-
-             version = mkOption {
-               default = null;
-               description = "Rendezvous service descriptor version to publish for the hidden service. Currently, versions 2 and 3 are supported. (Default: 2)";
-               type = types.nullOr (types.enum [ 2 3 ]);
-             };
+        type = types.submodule {
+          freeformType = with types;
+            (attrsOf (nullOr (oneOf [str int bool (listOf str)]))) // {
+              description = "settings option";
+            };
+          options.Address = optionString "Address";
+          options.AssumeReachable = optionBool "AssumeReachable";
+          options.AccountingMax = optionBandwith "AccountingMax";
+          options.AccountingStart = optionString "AccountingStart";
+          options.AuthDirHasIPv6Connectivity = optionBool "AuthDirHasIPv6Connectivity";
+          options.AuthDirListBadExits = optionBool "AuthDirListBadExits";
+          options.AuthDirPinKeys = optionBool "AuthDirPinKeys";
+          options.AuthDirSharedRandomness = optionBool "AuthDirSharedRandomness";
+          options.AuthDirTestEd25519LinkKeys = optionBool "AuthDirTestEd25519LinkKeys";
+          options.AuthoritativeDirectory = optionBool "AuthoritativeDirectory";
+          options.AutomapHostsOnResolve = optionBool "AutomapHostsOnResolve";
+          options.AutomapHostsSuffixes = optionStrings "AutomapHostsSuffixes" // {
+            default = [".onion" ".exit"];
+            example = [".onion"];
           };
-
-          config = {
-            name = mkDefault name;
+          options.BandwidthBurst = optionBandwith "BandwidthBurst";
+          options.BandwidthRate = optionBandwith "BandwidthRate";
+          options.BridgeAuthoritativeDir = optionBool "BridgeAuthoritativeDir";
+          options.BridgeRecordUsageByCountry = optionBool "BridgeRecordUsageByCountry";
+          options.BridgeRelay = optionBool "BridgeRelay" // { default = false; };
+          options.CacheDirectory = optionPath "CacheDirectory";
+          options.CacheDirectoryGroupReadable = optionBool "CacheDirectoryGroupReadable"; # default is null and like "auto"
+          options.CellStatistics = optionBool "CellStatistics";
+          options.ClientAutoIPv6ORPort = optionBool "ClientAutoIPv6ORPort";
+          options.ClientDNSRejectInternalAddresses = optionBool "ClientDNSRejectInternalAddresses";
+          options.ClientOnionAuthDir = mkOption {
+            description = descriptionGeneric "ClientOnionAuthDir";
+            default = null;
+            type = with types; nullOr path;
+          };
+          options.ClientPreferIPv6DirPort = optionBool "ClientPreferIPv6DirPort"; # default is null and like "auto"
+          options.ClientPreferIPv6ORPort = optionBool "ClientPreferIPv6ORPort"; # default is null and like "auto"
+          options.ClientRejectInternalAddresses = optionBool "ClientRejectInternalAddresses";
+          options.ClientUseIPv4 = optionBool "ClientUseIPv4";
+          options.ClientUseIPv6 = optionBool "ClientUseIPv6";
+          options.ConnDirectionStatistics = optionBool "ConnDirectionStatistics";
+          options.ConstrainedSockets = optionBool "ConstrainedSockets";
+          options.ContactInfo = optionString "ContactInfo";
+          options.ControlPort = mkOption rec {
+            description = descriptionGeneric "ControlPort";
+            default = [];
+            example = [{port = 9051;}];
+            type = with types; oneOf [port (enum ["auto"]) (listOf (oneOf [
+              port (enum ["auto"]) (submodule ({config, ...}: let
+                flags = ["GroupWritable" "RelaxDirModeCheck" "WorldWritable"];
+                in {
+                options = {
+                  unix = optionUnix;
+                  flags = optionFlags;
+                  addr = optionAddress;
+                  port = optionPort;
+                } // genAttrs flags (name: mkOption { type = types.bool; default = false; });
+                config = {
+                  flags = filter (name: config.${name} == true) flags;
+                };
+              }))
+            ]))];
+          };
+          options.ControlPortFileGroupReadable= optionBool "ControlPortFileGroupReadable";
+          options.ControlPortWriteToFile = optionPath "ControlPortWriteToFile";
+          options.ControlSocket = optionPath "ControlSocket";
+          options.ControlSocketsGroupWritable = optionBool "ControlSocketsGroupWritable";
+          options.CookieAuthFile = optionPath "CookieAuthFile";
+          options.CookieAuthFileGroupReadable = optionBool "CookieAuthFileGroupReadable";
+          options.CookieAuthentication = optionBool "CookieAuthentication";
+          options.DataDirectory = optionPath "DataDirectory" // { default = stateDir; };
+          options.DataDirectoryGroupReadable = optionBool "DataDirectoryGroupReadable";
+          options.DirPortFrontPage = optionPath "DirPortFrontPage";
+          options.DirAllowPrivateAddresses = optionBool "DirAllowPrivateAddresses";
+          options.DormantCanceledByStartup = optionBool "DormantCanceledByStartup";
+          options.DormantOnFirstStartup = optionBool "DormantOnFirstStartup";
+          options.DormantTimeoutDisabledByIdleStreams = optionBool "DormantTimeoutDisabledByIdleStreams";
+          options.DirCache = optionBool "DirCache";
+          options.DirPolicy = mkOption {
+            description = descriptionGeneric "DirPolicy";
+            type = with types; listOf str;
+            default = [];
+            example = ["accept *:*"];
+          };
+          options.DirPort = optionORPort "DirPort";
+          options.DirReqStatistics = optionBool "DirReqStatistics";
+          options.DisableAllSwap = optionBool "DisableAllSwap";
+          options.DisableDebuggerAttachment = optionBool "DisableDebuggerAttachment";
+          options.DisableNetwork = optionBool "DisableNetwork";
+          options.DisableOOSCheck = optionBool "DisableOOSCheck";
+          options.DNSPort = optionIsolablePorts "DNSPort";
+          options.DoSCircuitCreationEnabled = optionBool "DoSCircuitCreationEnabled";
+          options.DoSConnectionEnabled = optionBool "DoSConnectionEnabled"; # default is null and like "auto"
+          options.DoSRefuseSingleHopClientRendezvous = optionBool "DoSRefuseSingleHopClientRendezvous";
+          options.DownloadExtraInfo = optionBool "DownloadExtraInfo";
+          options.EnforceDistinctSubnets = optionBool "EnforceDistinctSubnets";
+          options.EntryStatistics = optionBool "EntryStatistics";
+          options.ExitPolicy = optionStrings "ExitPolicy" // {
+            default = ["reject *:*"];
+            example = ["accept *:*"];
+          };
+          options.ExitPolicyRejectLocalInterfaces = optionBool "ExitPolicyRejectLocalInterfaces";
+          options.ExitPolicyRejectPrivate = optionBool "ExitPolicyRejectPrivate";
+          options.ExitPortStatistics = optionBool "ExitPortStatistics";
+          options.ExitRelay = optionBool "ExitRelay"; # default is null and like "auto"
+          options.ExtORPort = mkOption {
+            description = descriptionGeneric "ExtORPort";
+            default = null;
+            type = with types; nullOr (oneOf [
+              port (enum ["auto"]) (submodule ({...}: {
+                options = {
+                  addr = optionAddress;
+                  port = optionPort;
+                };
+              }))
+            ]);
+            apply = p: if isInt p || isString p then { port = p; } else p;
           };
-        }));
+          options.ExtORPortCookieAuthFile = optionPath "ExtORPortCookieAuthFile";
+          options.ExtORPortCookieAuthFileGroupReadable = optionBool "ExtORPortCookieAuthFileGroupReadable";
+          options.ExtendAllowPrivateAddresses = optionBool "ExtendAllowPrivateAddresses";
+          options.ExtraInfoStatistics = optionBool "ExtraInfoStatistics";
+          options.FascistFirewall = optionBool "FascistFirewall";
+          options.FetchDirInfoEarly = optionBool "FetchDirInfoEarly";
+          options.FetchDirInfoExtraEarly = optionBool "FetchDirInfoExtraEarly";
+          options.FetchHidServDescriptors = optionBool "FetchHidServDescriptors";
+          options.FetchServerDescriptors = optionBool "FetchServerDescriptors";
+          options.FetchUselessDescriptors = optionBool "FetchUselessDescriptors";
+          options.ReachableAddresses = optionStrings "ReachableAddresses";
+          options.ReachableDirAddresses = optionStrings "ReachableDirAddresses";
+          options.ReachableORAddresses = optionStrings "ReachableORAddresses";
+          options.GeoIPFile = optionPath "GeoIPFile";
+          options.GeoIPv6File = optionPath "GeoIPv6File";
+          options.GuardfractionFile = optionPath "GuardfractionFile";
+          options.HidServAuth = mkOption {
+            description = descriptionGeneric "HidServAuth";
+            default = [];
+            type = with types; listOf (oneOf [
+              (submodule {
+                options = {
+                  onion = mkOption {
+                    type = strMatching "[a-z2-7]{16}(\\.onion)?";
+                    description = "Onion address.";
+                    example = "xxxxxxxxxxxxxxxx.onion";
+                  };
+                  auth = mkOption {
+                    type = strMatching "[A-Za-z0-9+/]{22}";
+                    description = "Authentication cookie.";
+                  };
+                };
+              })
+            ]);
+          };
+          options.HiddenServiceNonAnonymousMode = optionBool "HiddenServiceNonAnonymousMode";
+          options.HiddenServiceStatistics = optionBool "HiddenServiceStatistics";
+          options.HSLayer2Nodes = optionStrings "HSLayer2Nodes";
+          options.HSLayer3Nodes = optionStrings "HSLayer3Nodes";
+          options.HTTPTunnelPort = optionIsolablePorts "HTTPTunnelPort";
+          options.IPv6Exit = optionBool "IPv6Exit";
+          options.KeyDirectory = optionPath "KeyDirectory";
+          options.KeyDirectoryGroupReadable = optionBool "KeyDirectoryGroupReadable";
+          options.LogMessageDomains = optionBool "LogMessageDomains";
+          options.LongLivedPorts = optionPorts "LongLivedPorts";
+          options.MainloopStats = optionBool "MainloopStats";
+          options.MaxAdvertisedBandwidth = optionBandwith "MaxAdvertisedBandwidth";
+          options.MaxCircuitDirtiness = optionInt "MaxCircuitDirtiness";
+          options.MaxClientCircuitsPending = optionInt "MaxClientCircuitsPending";
+          options.NATDPort = optionIsolablePorts "NATDPort";
+          options.NewCircuitPeriod = optionInt "NewCircuitPeriod";
+          options.Nickname = optionString "Nickname";
+          options.ORPort = optionORPort "ORPort";
+          options.OfflineMasterKey = optionBool "OfflineMasterKey";
+          options.OptimisticData = optionBool "OptimisticData"; # default is null and like "auto"
+          options.PaddingStatistics = optionBool "PaddingStatistics";
+          options.PerConnBWBurst = optionBandwith "PerConnBWBurst";
+          options.PerConnBWRate = optionBandwith "PerConnBWRate";
+          options.PidFile = optionPath "PidFile";
+          options.ProtocolWarnings = optionBool "ProtocolWarnings";
+          options.PublishHidServDescriptors = optionBool "PublishHidServDescriptors";
+          options.PublishServerDescriptor = mkOption {
+            description = descriptionGeneric "PublishServerDescriptor";
+            type = with types; nullOr (enum [false true 0 1 "0" "1" "v3" "bridge"]);
+            default = null;
+          };
+          options.ReducedExitPolicy = optionBool "ReducedExitPolicy";
+          options.RefuseUnknownExits = optionBool "RefuseUnknownExits"; # default is null and like "auto"
+          options.RejectPlaintextPorts = optionPorts "RejectPlaintextPorts";
+          options.RelayBandwidthBurst = optionBandwith "RelayBandwidthBurst";
+          options.RelayBandwidthRate = optionBandwith "RelayBandwidthRate";
+          #options.RunAsDaemon
+          options.Sandbox = optionBool "Sandbox";
+          options.ServerDNSAllowBrokenConfig = optionBool "ServerDNSAllowBrokenConfig";
+          options.ServerDNSAllowNonRFC953Hostnames = optionBool "ServerDNSAllowNonRFC953Hostnames";
+          options.ServerDNSDetectHijacking = optionBool "ServerDNSDetectHijacking";
+          options.ServerDNSRandomizeCase = optionBool "ServerDNSRandomizeCase";
+          options.ServerDNSResolvConfFile = optionPath "ServerDNSResolvConfFile";
+          options.ServerDNSSearchDomains = optionBool "ServerDNSSearchDomains";
+          options.ServerTransportPlugin = mkOption {
+            description = descriptionGeneric "ServerTransportPlugin";
+            default = null;
+            type = with types; nullOr (submodule ({...}: {
+              options = {
+                transports = mkOption {
+                  description = "List of pluggable transports.";
+                  type = listOf str;
+                  example = ["obfs2" "obfs3" "obfs4" "scramblesuit"];
+                };
+                exec = mkOption {
+                  type = types.str;
+                  description = "Command of pluggable transport.";
+                };
+              };
+            }));
+          };
+          options.SocksPolicy = optionStrings "SocksPolicy" // {
+            example = ["accept *:*"];
+          };
+          options.SOCKSPort = mkOption {
+            description = descriptionGeneric "SOCKSPort";
+            default = if cfg.settings.HiddenServiceNonAnonymousMode == true then [{port = 0;}] else [];
+            example = [{port = 9090;}];
+            type = types.listOf (optionSOCKSPort true);
+          };
+          options.TestingTorNetwork = optionBool "TestingTorNetwork";
+          options.TransPort = optionIsolablePorts "TransPort";
+          options.TransProxyType = mkOption {
+            description = descriptionGeneric "TransProxyType";
+            type = with types; nullOr (enum ["default" "TPROXY" "ipfw" "pf-divert"]);
+            default = null;
+          };
+          #options.TruncateLogFile
+          options.UnixSocksGroupWritable = optionBool "UnixSocksGroupWritable";
+          options.UseDefaultFallbackDirs = optionBool "UseDefaultFallbackDirs";
+          options.UseMicrodescriptors = optionBool "UseMicrodescriptors";
+          options.V3AuthUseLegacyKey = optionBool "V3AuthUseLegacyKey";
+          options.V3AuthoritativeDirectory = optionBool "V3AuthoritativeDirectory";
+          options.VersioningAuthoritativeDirectory = optionBool "VersioningAuthoritativeDirectory";
+          options.VirtualAddrNetworkIPv4 = optionString "VirtualAddrNetworkIPv4";
+          options.VirtualAddrNetworkIPv6 = optionString "VirtualAddrNetworkIPv6";
+          options.WarnPlaintextPorts = optionPorts "WarnPlaintextPorts";
+        };
       };
     };
   };
@@ -696,79 +822,219 @@ in
   config = mkIf cfg.enable {
     # Not sure if `cfg.relay.role == "private-bridge"` helps as tor
     # sends a lot of stats
-    warnings = optional (cfg.relay.enable && cfg.hiddenServices != {})
+    warnings = optional (cfg.settings.BridgeRelay &&
+      flatten (mapAttrsToList (n: o: o.map) cfg.relay.onionServices) != [])
       ''
         Running Tor hidden services on a public relay makes the
         presence of hidden services visible through simple statistical
         analysis of publicly available data.
+        See https://trac.torproject.org/projects/tor/ticket/8742
 
         You can safely ignore this warning if you don't intend to
         actually hide your hidden services. In either case, you can
         always create a container/VM with a separate Tor daemon instance.
-      '';
+      '' ++
+      flatten (mapAttrsToList (n: o:
+        optional (o.settings.HiddenServiceVersion == 2) [
+          (optional (o.settings.HiddenServiceExportCircuitID != null) ''
+            HiddenServiceExportCircuitID is used in the HiddenService: ${n}
+            but this option is only for v3 hidden services.
+          '')
+        ] ++
+        optional (o.settings.HiddenServiceVersion != 2) [
+          (optional (o.settings.HiddenServiceAuthorizeClient != null) ''
+            HiddenServiceAuthorizeClient is used in the HiddenService: ${n}
+            but this option is only for v2 hidden services.
+          '')
+          (optional (o.settings.RendPostPeriod != null) ''
+            RendPostPeriod is used in the HiddenService: ${n}
+            but this option is only for v2 hidden services.
+          '')
+        ]
+      ) cfg.relay.onionServices);
 
     users.groups.tor.gid = config.ids.gids.tor;
     users.users.tor =
       { description = "Tor Daemon User";
         createHome  = true;
-        home        = torDirectory;
+        home        = stateDir;
         group       = "tor";
         uid         = config.ids.uids.tor;
       };
 
-    # We have to do this instead of using RuntimeDirectory option in
-    # the service below because systemd has no way to set owners of
-    # RuntimeDirectory and putting this into the service below
-    # requires that service to relax it's sandbox since this needs
-    # writable /run
-    systemd.services.tor-init =
-      { description = "Tor Daemon Init";
-        wantedBy = [ "tor.service" ];
-        script = ''
-          install -m 0700 -o tor -g tor -d ${torDirectory} ${torDirectory}/onion
-          install -m 0750 -o tor -g tor -d ${torRunDirectory}
-        '';
-        serviceConfig = {
-          Type = "oneshot";
-          RemainAfterExit = true;
-        };
-      };
+    services.tor.settings = mkMerge [
+      (mkIf cfg.enableGeoIP {
+        GeoIPFile = "${cfg.package.geoip}/share/tor/geoip";
+        GeoIPv6File = "${cfg.package.geoip}/share/tor/geoip6";
+      })
+      (mkIf cfg.controlSocket.enable {
+        ControlPort = [ { unix = runDir + "/control"; GroupWritable=true; RelaxDirModeCheck=true; } ];
+      })
+      (mkIf cfg.relay.enable (
+        optionalAttrs (cfg.relay.role != "exit") {
+          ExitPolicy = mkForce ["reject *:*"];
+        } //
+        optionalAttrs (elem cfg.relay.role ["bridge" "private-bridge"]) {
+          BridgeRelay = true;
+          ExtORPort.port = mkDefault "auto";
+          ServerTransportPlugin.transports = mkDefault ["obfs4"];
+          ServerTransportPlugin.exec = mkDefault "${pkgs.obfs4}/bin/obfs4proxy managed";
+        } // optionalAttrs (cfg.relay.role == "private-bridge") {
+          ExtraInfoStatistics = false;
+          PublishServerDescriptor = false;
+        }
+      ))
+      (mkIf (!cfg.relay.enable) {
+        # Avoid surprises when leaving ORPort/DirPort configurations in cfg.settings,
+        # because it would still enable Tor as a relay,
+        # which can trigger all sort of problems when not carefully done,
+        # like the blocklisting of the machine's IP addresses
+        # by some hosting providers...
+        DirPort = mkForce [];
+        ORPort = mkForce [];
+        PublishServerDescriptor = mkForce false;
+      })
+      (mkIf cfg.client.enable (
+        { SOCKSPort = [ cfg.client.socksListenAddress ];
+        } // optionalAttrs cfg.client.transparentProxy.enable {
+          TransPort = [{ addr = "127.0.0.1"; port = 9040; }];
+        } // optionalAttrs cfg.client.dns.enable {
+          DNSPort = [{ addr = "127.0.0.1"; port = 9053; }];
+          AutomapHostsOnResolve = true;
+        } // optionalAttrs (flatten (mapAttrsToList (n: o: o.clientAuthorizations) cfg.client.onionServices) != []) {
+          ClientOnionAuthDir = runDir + "/ClientOnionAuthDir";
+        }
+      ))
+    ];
 
-    systemd.services.tor =
-      { description = "Tor Daemon";
-        path = [ pkgs.tor ];
-
-        wantedBy = [ "multi-user.target" ];
-        after    = [ "tor-init.service" "network.target" ];
-        restartTriggers = [ torRcFile ];
-
-        serviceConfig =
-          { Type         = "simple";
-            # Translated from the upstream contrib/dist/tor.service.in
-            ExecStartPre = "${cfg.package}/bin/tor -f ${torRcFile} --verify-config";
-            ExecStart    = "${cfg.package}/bin/tor -f ${torRcFile}";
-            ExecReload   = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
-            KillSignal   = "SIGINT";
-            TimeoutSec   = 30;
-            Restart      = "on-failure";
-            LimitNOFILE  = 32768;
-
-            # Hardening
-            # this seems to unshare /run despite what systemd.exec(5) says
-            PrivateTmp              = mkIf (!cfg.controlSocket.enable) "yes";
-            PrivateDevices          = "yes";
-            ProtectHome             = "yes";
-            ProtectSystem           = "strict";
-            InaccessiblePaths       = "/home";
-            ReadOnlyPaths           = "/";
-            ReadWritePaths          = [ torDirectory torRunDirectory ];
-            NoNewPrivileges         = "yes";
-
-            # tor.service.in has this in, but this line it fails to spawn a namespace when using hidden services
-            #CapabilityBoundingSet   = "CAP_SETUID CAP_SETGID CAP_NET_BIND_SERVICE";
-          };
+    networking.firewall = mkIf cfg.openFirewall {
+      allowedTCPPorts =
+        concatMap (o:
+          if isInt o && o > 0 then [o]
+          else if o ? "port" && isInt o.port && o.port > 0 then [o.port]
+          else []
+        ) (flatten [
+          cfg.settings.ORPort
+          cfg.settings.DirPort
+        ]);
+    };
+
+    systemd.services.tor = {
+      description = "Tor Daemon";
+      path = [ pkgs.tor ];
+
+      wantedBy = [ "multi-user.target" ];
+      after    = [ "network.target" ];
+      restartTriggers = [ torrc ];
+
+      serviceConfig = {
+        Type = "simple";
+        User = "tor";
+        Group = "tor";
+        ExecStartPre = [
+          "${cfg.package}/bin/tor -f ${torrc} --verify-config"
+          # DOC: Appendix G of https://spec.torproject.org/rend-spec-v3
+          ("+" + pkgs.writeShellScript "ExecStartPre" (concatStringsSep "\n" (flatten (["set -eu"] ++
+            mapAttrsToList (name: onion:
+              optional (onion.authorizedClients != []) ''
+                rm -rf ${escapeShellArg onion.path}/authorized_clients
+                install -d -o tor -g tor -m 0700 ${escapeShellArg onion.path} ${escapeShellArg onion.path}/authorized_clients
+              '' ++
+              imap0 (i: pubKey: ''
+                echo ${pubKey} |
+                install -o tor -g tor -m 0400 /dev/stdin ${escapeShellArg onion.path}/authorized_clients/${toString i}.auth
+              '') onion.authorizedClients ++
+              optional (onion.secretKey != null) ''
+                install -d -o tor -g tor -m 0700 ${escapeShellArg onion.path}
+                key="$(cut -f1 -d: ${escapeShellArg onion.secretKey})"
+                case "$key" in
+                 ("== ed25519v"*"-secret")
+                  install -o tor -g tor -m 0400 ${escapeShellArg onion.secretKey} ${escapeShellArg onion.path}/hs_ed25519_secret_key;;
+                 (*) echo >&2 "NixOS does not (yet) support secret key type for onion: ${name}"; exit 1;;
+                esac
+              ''
+            ) cfg.relay.onionServices ++
+            mapAttrsToList (name: onion: imap0 (i: prvKeyPath:
+              let hostname = removeSuffix ".onion" name; in ''
+              printf "%s:" ${escapeShellArg hostname} | cat - ${escapeShellArg prvKeyPath} |
+              install -o tor -g tor -m 0700 /dev/stdin \
+               ${runDir}/ClientOnionAuthDir/${escapeShellArg hostname}.${toString i}.auth_private
+            '') onion.clientAuthorizations)
+            cfg.client.onionServices
+          ))))
+        ];
+        ExecStart = "${cfg.package}/bin/tor -f ${torrc}";
+        ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
+        KillSignal = "SIGINT";
+        TimeoutSec = 30;
+        Restart = "on-failure";
+        LimitNOFILE = 32768;
+        RuntimeDirectory = [
+          # g+x allows access to the control socket
+          "tor"
+          "tor/root"
+          # g+x can't be removed in ExecStart=, but will be removed by Tor
+          "tor/ClientOnionAuthDir"
+        ];
+        RuntimeDirectoryMode = "0710";
+        StateDirectoryMode = "0700";
+        StateDirectory = [
+            "tor"
+            "tor/onion"
+          ] ++
+          flatten (mapAttrsToList (name: onion:
+            optional (onion.secretKey == null) "tor/onion/${name}"
+          ) cfg.relay.onionServices);
+        # The following options are only to optimize:
+        # systemd-analyze security tor
+        RootDirectory = runDir + "/root";
+        RootDirectoryStartOnly = true;
+        #InaccessiblePaths = [ "-+${runDir}/root" ];
+        UMask = "0066";
+        BindPaths = [ stateDir ];
+        BindReadOnlyPaths = [ storeDir "/etc" ];
+        AmbientCapabilities   = [""] ++ lib.optional bindsPrivilegedPort "CAP_NET_BIND_SERVICE";
+        CapabilityBoundingSet = [""] ++ lib.optional bindsPrivilegedPort "CAP_NET_BIND_SERVICE";
+        # ProtectClock= adds DeviceAllow=char-rtc r
+        DeviceAllow = "";
+        LockPersonality = true;
+        MemoryDenyWriteExecute = true;
+        NoNewPrivileges = true;
+        PrivateDevices = true;
+        PrivateMounts = true;
+        PrivateNetwork = mkDefault false;
+        PrivateTmp = true;
+        # Tor cannot currently bind privileged port when PrivateUsers=true,
+        # see https://gitlab.torproject.org/legacy/trac/-/issues/20930
+        PrivateUsers = !bindsPrivilegedPort;
+        ProtectClock = true;
+        ProtectControlGroups = true;
+        ProtectHome = true;
+        ProtectHostname = true;
+        ProtectKernelLogs = true;
+        ProtectKernelModules = true;
+        ProtectKernelTunables = true;
+        ProtectSystem = "strict";
+        RemoveIPC = true;
+        RestrictAddressFamilies = [ "AF_UNIX" "AF_INET" "AF_INET6" ];
+        RestrictNamespaces = true;
+        RestrictRealtime = true;
+        RestrictSUIDSGID = true;
+        # See also the finer but experimental option settings.Sandbox
+        SystemCallFilter = [
+          "@system-service"
+          # Groups in @system-service which do not contain a syscall listed by:
+          # perf stat -x, 2>perf.log -e 'syscalls:sys_enter_*' tor
+          # in tests, and seem likely not necessary for tor.
+          "~@aio" "~@chown" "~@keyring" "~@memlock" "~@resources" "~@setuid" "~@timer"
+        ];
+        SystemCallArchitectures = "native";
+        SystemCallErrorNumber = "EPERM";
       };
+    };
 
     environment.systemPackages = [ cfg.package ];
   };
+
+  meta.maintainers = with lib.maintainers; [ julm ];
 }
diff --git a/nixpkgs/nixos/modules/services/security/usbguard.nix b/nixpkgs/nixos/modules/services/security/usbguard.nix
index 71fd71a2cab2..4cdb3a041b59 100644
--- a/nixpkgs/nixos/modules/services/security/usbguard.nix
+++ b/nixpkgs/nixos/modules/services/security/usbguard.nix
@@ -173,7 +173,7 @@ in
 
       serviceConfig = {
         Type = "simple";
-        ExecStart = ''${cfg.package}/bin/usbguard-daemon -P -k -c ${daemonConfFile}'';
+        ExecStart = "${cfg.package}/bin/usbguard-daemon -P -k -c ${daemonConfFile}";
         Restart = "on-failure";
 
         StateDirectory = [
diff --git a/nixpkgs/nixos/modules/services/security/vault.nix b/nixpkgs/nixos/modules/services/security/vault.nix
index 64622454b9de..5a20f6413b1b 100644
--- a/nixpkgs/nixos/modules/services/security/vault.nix
+++ b/nixpkgs/nixos/modules/services/security/vault.nix
@@ -27,6 +27,11 @@ let
       ''}
     ${cfg.extraConfig}
   '';
+
+  allConfigPaths = [configFile] ++ cfg.extraSettingsPaths;
+
+  configOptions = escapeShellArgs (concatMap (p: ["-config" p]) allConfigPaths);
+
 in
 
 {
@@ -84,7 +89,14 @@ in
       storageConfig = mkOption {
         type = types.nullOr types.lines;
         default = null;
-        description = "Storage configuration";
+        description = ''
+          HCL configuration to insert in the storageBackend section.
+
+          Confidential values should not be specified here because this option's
+          value is written to the Nix store, which is publicly readable.
+          Provide credentials and such in a separate file using
+          <xref linkend="opt-services.vault.extraSettingsPaths"/>.
+        '';
       };
 
       telemetryConfig = mkOption {
@@ -98,6 +110,36 @@ in
         default = "";
         description = "Extra text appended to <filename>vault.hcl</filename>.";
       };
+
+      extraSettingsPaths = mkOption {
+        type = types.listOf types.path;
+        default = [];
+        description = ''
+          Configuration files to load besides the immutable one defined by the NixOS module.
+          This can be used to avoid putting credentials in the Nix store, which can be read by any user.
+
+          Each path can point to a JSON- or HCL-formatted file, or a directory
+          to be scanned for files with <literal>.hcl</literal> or
+          <literal>.json</literal> extensions.
+
+          To upload the confidential file with NixOps, use for example:
+
+          <programlisting><![CDATA[
+          # https://releases.nixos.org/nixops/latest/manual/manual.html#opt-deployment.keys
+          deployment.keys."vault.hcl" = let db = import ./db-credentials.nix; in {
+            text = ${"''"}
+              storage "postgresql" {
+                connection_url = "postgres://''${db.username}:''${db.password}@host.example.com/exampledb?sslmode=verify-ca"
+              }
+            ${"''"};
+            user = "vault";
+          };
+          services.vault.extraSettingsPaths = ["/run/keys/vault.hcl"];
+          services.vault.storageBackend = "postgresql";
+          users.users.vault.extraGroups = ["keys"];
+          ]]></programlisting>
+        '';
+      };
     };
   };
 
@@ -136,7 +178,7 @@ in
       serviceConfig = {
         User = "vault";
         Group = "vault";
-        ExecStart = "${cfg.package}/bin/vault server -config ${configFile}";
+        ExecStart = "${cfg.package}/bin/vault server ${configOptions}";
         ExecReload = "${pkgs.coreutils}/bin/kill -SIGHUP $MAINPID";
         PrivateDevices = true;
         PrivateTmp = true;
diff --git a/nixpkgs/nixos/modules/services/system/cloud-init.nix b/nixpkgs/nixos/modules/services/system/cloud-init.nix
index 3518e0ee9dca..f83db30c1f02 100644
--- a/nixpkgs/nixos/modules/services/system/cloud-init.nix
+++ b/nixpkgs/nixos/modules/services/system/cloud-init.nix
@@ -98,7 +98,7 @@ in
            - final-message
            - power-state-change
           '';
-        description = ''cloud-init configuration.'';
+        description = "cloud-init configuration.";
       };
 
     };
diff --git a/nixpkgs/nixos/modules/services/ttys/agetty.nix b/nixpkgs/nixos/modules/services/ttys/getty.nix
index 5d8b21cea3f1..ecfabef5fb13 100644
--- a/nixpkgs/nixos/modules/services/ttys/agetty.nix
+++ b/nixpkgs/nixos/modules/services/ttys/getty.nix
@@ -3,7 +3,7 @@
 with lib;
 
 let
-  cfg = config.services.mingetty;
+  cfg = config.services.getty;
 
   loginArgs = [
     "--login-program" "${pkgs.shadow}/bin/login"
@@ -23,9 +23,13 @@ in
 
   ###### interface
 
+  imports = [
+    (mkRenamedOptionModule [ "services" "mingetty" ] [ "services" "getty" ])
+  ];
+
   options = {
 
-    services.mingetty = {
+    services.getty = {
 
       autologinUser = mkOption {
         type = types.nullOr types.str;
@@ -56,7 +60,7 @@ in
       greetingLine = mkOption {
         type = types.str;
         description = ''
-          Welcome line printed by mingetty.
+          Welcome line printed by agetty.
           The default shows current NixOS version label, machine type and tty.
         '';
       };
@@ -65,7 +69,7 @@ in
         type = types.lines;
         default = "";
         description = ''
-          Help line printed by mingetty below the welcome line.
+          Help line printed by agetty below the welcome line.
           Used by the installation CD to give some hints on
           how to proceed.
         '';
@@ -92,7 +96,7 @@ in
   config = {
     # Note: this is set here rather than up there so that changing
     # nixos.label would not rebuild manual pages
-    services.mingetty.greetingLine = mkDefault ''<<< Welcome to NixOS ${config.system.nixos.label} (\m) - \l >>>'';
+    services.getty.greetingLine = mkDefault ''<<< Welcome to NixOS ${config.system.nixos.label} (\m) - \l >>>'';
 
     systemd.services."getty@" =
       { serviceConfig.ExecStart = [
@@ -103,7 +107,7 @@ in
       };
 
     systemd.services."serial-getty@" =
-      let speeds = concatStringsSep "," (map toString config.services.mingetty.serialSpeed); in
+      let speeds = concatStringsSep "," (map toString config.services.getty.serialSpeed); in
       { serviceConfig.ExecStart = [
           "" # override upstream default with an empty ExecStart
           (gettyCmd "%I ${speeds} $TERM")
@@ -133,8 +137,8 @@ in
       { # Friendly greeting on the virtual consoles.
         source = pkgs.writeText "issue" ''
 
-          ${config.services.mingetty.greetingLine}
-          ${config.services.mingetty.helpLine}
+          ${config.services.getty.greetingLine}
+          ${config.services.getty.helpLine}
 
         '';
       };
diff --git a/nixpkgs/nixos/modules/services/web-apps/dokuwiki.nix b/nixpkgs/nixos/modules/services/web-apps/dokuwiki.nix
index d9ebb3a98808..9567223ebc7b 100644
--- a/nixpkgs/nixos/modules/services/web-apps/dokuwiki.nix
+++ b/nixpkgs/nixos/modules/services/web-apps/dokuwiki.nix
@@ -336,7 +336,7 @@ in
         locations."/" = {
           priority = 1;
           index = "doku.php";
-          extraConfig = ''try_files $uri $uri/ @dokuwiki;'';
+          extraConfig = "try_files $uri $uri/ @dokuwiki;";
         };
 
         locations."@dokuwiki" = {
diff --git a/nixpkgs/nixos/modules/services/web-apps/ihatemoney/default.nix b/nixpkgs/nixos/modules/services/web-apps/ihatemoney/default.nix
index 68769ac8c031..b4987fa4702c 100644
--- a/nixpkgs/nixos/modules/services/web-apps/ihatemoney/default.nix
+++ b/nixpkgs/nixos/modules/services/web-apps/ihatemoney/default.nix
@@ -44,7 +44,7 @@ let
 in
   {
     options.services.ihatemoney = {
-      enable = mkEnableOption "ihatemoney webapp. Note that this will set uwsgi to emperor mode running as root";
+      enable = mkEnableOption "ihatemoney webapp. Note that this will set uwsgi to emperor mode";
       backend = mkOption {
         type = types.enum [ "sqlite" "postgresql" ];
         default = "sqlite";
@@ -116,16 +116,13 @@ in
       services.uwsgi = {
         enable = true;
         plugins = [ "python3" ];
-        # the vassal needs to be able to setuid
-        user = "root";
-        group = "root";
         instance = {
           type = "emperor";
           vassals.ihatemoney = {
             type = "normal";
             strict = true;
-            uid = user;
-            gid = group;
+            immediate-uid = user;
+            immediate-gid = group;
             # apparently flask uses threads: https://github.com/spiral-project/ihatemoney/commit/c7815e48781b6d3a457eaff1808d179402558f8c
             enable-threads = true;
             module = "wsgi:application";
diff --git a/nixpkgs/nixos/modules/services/web-apps/keycloak.nix b/nixpkgs/nixos/modules/services/web-apps/keycloak.nix
index bbb0c8d04831..a93e93279331 100644
--- a/nixpkgs/nixos/modules/services/web-apps/keycloak.nix
+++ b/nixpkgs/nixos/modules/services/web-apps/keycloak.nix
@@ -565,7 +565,7 @@ in
         assertions = [
           {
             assertion = (cfg.databaseUseSSL && cfg.databaseType == "postgresql") -> (cfg.databaseCaCert != null);
-            message = ''A CA certificate must be specified (in 'services.keycloak.databaseCaCert') when PostgreSQL is used with SSL'';
+            message = "A CA certificate must be specified (in 'services.keycloak.databaseCaCert') when PostgreSQL is used with SSL";
           }
         ];
 
diff --git a/nixpkgs/nixos/modules/services/web-apps/moodle.nix b/nixpkgs/nixos/modules/services/web-apps/moodle.nix
index 8887136ea5e7..ad1e55d62d1d 100644
--- a/nixpkgs/nixos/modules/services/web-apps/moodle.nix
+++ b/nixpkgs/nixos/modules/services/web-apps/moodle.nix
@@ -84,7 +84,7 @@ in
       type = mkOption {
         type = types.enum [ "mysql" "pgsql" ];
         default = "mysql";
-        description = ''Database engine to use.'';
+        description = "Database engine to use.";
       };
 
       host = mkOption {
diff --git a/nixpkgs/nixos/modules/services/web-apps/nextcloud.xml b/nixpkgs/nixos/modules/services/web-apps/nextcloud.xml
index 02e4dba28610..f71c8df6c6d4 100644
--- a/nixpkgs/nixos/modules/services/web-apps/nextcloud.xml
+++ b/nixpkgs/nixos/modules/services/web-apps/nextcloud.xml
@@ -10,6 +10,10 @@
   <link linkend="opt-services.nextcloud.enable">services.nextcloud</link>. A
   desktop client is packaged at <literal>pkgs.nextcloud-client</literal>.
  </para>
+ <para>
+  The current default by NixOS is <package>nextcloud20</package> which is also the latest
+  major version available.
+ </para>
  <section xml:id="module-services-nextcloud-basic-usage">
   <title>Basic usage</title>
 
@@ -210,7 +214,7 @@
   nextcloud17 = generic {
     version = "17.0.x";
     sha256 = "0000000000000000000000000000000000000000000000000000";
-    insecure = true;
+    eol = true;
   };
 }</programlisting>
   </para>
diff --git a/nixpkgs/nixos/modules/services/web-apps/trilium.nix b/nixpkgs/nixos/modules/services/web-apps/trilium.nix
index 3fa8dad04908..3a6ea02676aa 100644
--- a/nixpkgs/nixos/modules/services/web-apps/trilium.nix
+++ b/nixpkgs/nixos/modules/services/web-apps/trilium.nix
@@ -85,7 +85,7 @@ in
 
   config = lib.mkIf cfg.enable (lib.mkMerge [
   {
-    meta.maintainers = with lib.maintainers; [ kampka ];
+    meta.maintainers = with lib.maintainers; [ ];
 
     users.groups.trilium = {};
     users.users.trilium = {
diff --git a/nixpkgs/nixos/modules/services/web-apps/whitebophir.nix b/nixpkgs/nixos/modules/services/web-apps/whitebophir.nix
new file mode 100644
index 000000000000..a19812547c44
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/web-apps/whitebophir.nix
@@ -0,0 +1,45 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.services.whitebophir;
+in {
+  options = {
+    services.whitebophir = {
+      enable = mkEnableOption "whitebophir, an online collaborative whiteboard server (persistent state will be maintained under <filename>/var/lib/whitebophir</filename>)";
+
+      package = mkOption {
+        default = pkgs.whitebophir;
+        defaultText = "pkgs.whitebophir";
+        type = types.package;
+        description = "Whitebophir package to use.";
+      };
+
+      port = mkOption {
+        type = types.port;
+        default = 5001;
+        description = "Port to bind to.";
+      };
+    };
+  };
+
+  config = mkIf cfg.enable {
+    systemd.services.whitebophir = {
+      description = "Whitebophir Service";
+      wantedBy    = [ "multi-user.target" ];
+      after       = [ "network.target" ];
+      environment = {
+        PORT            = "${toString cfg.port}";
+        WBO_HISTORY_DIR = "/var/lib/whitebophir";
+      };
+
+      serviceConfig = {
+        DynamicUser    = true;
+        ExecStart      = "${cfg.package}/bin/whitebophir";
+        Restart        = "always";
+        StateDirectory = "whitebophir";
+      };
+    };
+  };
+}
diff --git a/nixpkgs/nixos/modules/services/web-servers/jboss/default.nix b/nixpkgs/nixos/modules/services/web-servers/jboss/default.nix
index ca5b8635fc00..d243e0f3f1b7 100644
--- a/nixpkgs/nixos/modules/services/web-servers/jboss/default.nix
+++ b/nixpkgs/nixos/modules/services/web-servers/jboss/default.nix
@@ -31,32 +31,38 @@ in
 
       tempDir = mkOption {
         default = "/tmp";
+        type = types.str;
         description = "Location where JBoss stores its temp files";
       };
 
       logDir = mkOption {
         default = "/var/log/jboss";
+        type = types.str;
         description = "Location of the logfile directory of JBoss";
       };
 
       serverDir = mkOption {
         description = "Location of the server instance files";
         default = "/var/jboss/server";
+        type = types.str;
       };
 
       deployDir = mkOption {
         description = "Location of the deployment files";
         default = "/nix/var/nix/profiles/default/server/default/deploy/";
+        type = types.str;
       };
 
       libUrl = mkOption {
         default = "file:///nix/var/nix/profiles/default/server/default/lib";
         description = "Location where the shared library JARs are stored";
+        type = types.str;
       };
 
       user = mkOption {
         default = "nobody";
         description = "User account under which jboss runs.";
+        type = types.str;
       };
 
       useJK = mkOption {
diff --git a/nixpkgs/nixos/modules/services/web-servers/lighttpd/default.nix b/nixpkgs/nixos/modules/services/web-servers/lighttpd/default.nix
index 7a3df26e47a6..d1cb8a8dc258 100644
--- a/nixpkgs/nixos/modules/services/web-servers/lighttpd/default.nix
+++ b/nixpkgs/nixos/modules/services/web-servers/lighttpd/default.nix
@@ -193,7 +193,7 @@ in
       configText = mkOption {
         default = "";
         type = types.lines;
-        example = ''...verbatim config file contents...'';
+        example = "...verbatim config file contents...";
         description = ''
           Overridable config file contents to use for lighttpd. By default, use
           the contents automatically generated by NixOS.
diff --git a/nixpkgs/nixos/modules/services/web-servers/nginx/default.nix b/nixpkgs/nixos/modules/services/web-servers/nginx/default.nix
index 7fcd61880ea8..d6f463be9e81 100644
--- a/nixpkgs/nixos/modules/services/web-servers/nginx/default.nix
+++ b/nixpkgs/nixos/modules/services/web-servers/nginx/default.nix
@@ -206,6 +206,12 @@ let
       ${cfg.httpConfig}
     }''}
 
+    ${optionalString (cfg.streamConfig != "") ''
+    stream {
+      ${cfg.streamConfig}
+    }
+    ''}
+
     ${cfg.appendConfig}
   '';
 
@@ -483,6 +489,21 @@ in
         ";
       };
 
+      streamConfig = mkOption {
+        type = types.lines;
+        default = "";
+        example = ''
+          server {
+            listen 127.0.0.1:53 udp reuseport;
+            proxy_timeout 20s;
+            proxy_pass 192.168.0.1:53535;
+          }
+        '';
+        description = "
+          Configuration lines to be set inside the stream block.
+        ";
+      };
+
       eventsConfig = mkOption {
         type = types.lines;
         default = "";
diff --git a/nixpkgs/nixos/modules/services/web-servers/tomcat.nix b/nixpkgs/nixos/modules/services/web-servers/tomcat.nix
index 6d12925829f7..13fe98402c60 100644
--- a/nixpkgs/nixos/modules/services/web-servers/tomcat.nix
+++ b/nixpkgs/nixos/modules/services/web-servers/tomcat.nix
@@ -74,6 +74,7 @@ in
 
       extraGroups = mkOption {
         default = [];
+        type = types.listOf types.str;
         example = [ "users" ];
         description = "Defines extra groups to which the tomcat user belongs.";
       };
diff --git a/nixpkgs/nixos/modules/services/web-servers/uwsgi.nix b/nixpkgs/nixos/modules/services/web-servers/uwsgi.nix
index 7ac40c154730..ef4bc860a8f0 100644
--- a/nixpkgs/nixos/modules/services/web-servers/uwsgi.nix
+++ b/nixpkgs/nixos/modules/services/web-servers/uwsgi.nix
@@ -5,11 +5,24 @@ with lib;
 let
   cfg = config.services.uwsgi;
 
+  isEmperor = cfg.instance.type == "emperor";
+
+  imperialPowers =
+    [
+      # spawn other user processes
+      "CAP_SETUID" "CAP_SETGID"
+      "CAP_SYS_CHROOT"
+      # transfer capabilities
+      "CAP_SETPCAP"
+      # create other user sockets
+      "CAP_CHOWN"
+    ];
+
   buildCfg = name: c:
     let
       plugins =
         if any (n: !any (m: m == n) cfg.plugins) (c.plugins or [])
-        then throw "`plugins` attribute in UWSGI configuration contains plugins not in config.services.uwsgi.plugins"
+        then throw "`plugins` attribute in uWSGI configuration contains plugins not in config.services.uwsgi.plugins"
         else c.plugins or cfg.plugins;
 
       hasPython = v: filter (n: n == "python${v}") plugins != [];
@@ -18,7 +31,7 @@ let
 
       python =
         if hasPython2 && hasPython3 then
-          throw "`plugins` attribute in UWSGI configuration shouldn't contain both python2 and python3"
+          throw "`plugins` attribute in uWSGI configuration shouldn't contain both python2 and python3"
         else if hasPython2 then cfg.package.python2
         else if hasPython3 then cfg.package.python3
         else null;
@@ -43,7 +56,7 @@ let
                       oldPaths = filter (x: x != null) (map getPath env');
                   in env' ++ [ "PATH=${optionalString (oldPaths != []) "${last oldPaths}:"}${pythonEnv}/bin" ];
               }
-          else if c.type == "emperor"
+          else if isEmperor
             then {
               emperor = if builtins.typeOf c.vassals != "set" then c.vassals
                         else pkgs.buildEnv {
@@ -51,7 +64,7 @@ let
                           paths = mapAttrsToList buildCfg c.vassals;
                         };
             } // removeAttrs c [ "type" "vassals" ]
-          else throw "`type` attribute in UWSGI configuration should be either 'normal' or 'emperor'";
+          else throw "`type` attribute in uWSGI configuration should be either 'normal' or 'emperor'";
       };
 
     in pkgs.writeTextDir "${name}.json" (builtins.toJSON uwsgiCfg);
@@ -79,7 +92,7 @@ in {
       };
 
       instance = mkOption {
-        type =  with lib.types; let
+        type =  with types; let
           valueType = nullOr (oneOf [
             bool
             int
@@ -137,13 +150,43 @@ in {
       user = mkOption {
         type = types.str;
         default = "uwsgi";
-        description = "User account under which uwsgi runs.";
+        description = "User account under which uWSGI runs.";
       };
 
       group = mkOption {
         type = types.str;
         default = "uwsgi";
-        description = "Group account under which uwsgi runs.";
+        description = "Group account under which uWSGI runs.";
+      };
+
+      capabilities = mkOption {
+        type = types.listOf types.str;
+        apply = caps: caps ++ optionals isEmperor imperialPowers;
+        default = [ ];
+        example = literalExample ''
+          [
+            "CAP_NET_BIND_SERVICE" # bind on ports <1024
+            "CAP_NET_RAW"          # open raw sockets
+          ]
+        '';
+        description = ''
+          Grant capabilities to the uWSGI instance. See the
+          <literal>capabilities(7)</literal> for available values.
+          <note>
+            <para>
+              uWSGI runs as an unprivileged user (even as Emperor) with the minimal
+              capabilities required. This option can be used to add fine-grained
+              permissions without running the service as root.
+            </para>
+            <para>
+              When in Emperor mode, any capability to be inherited by a vassal must
+              be specified again in the vassal configuration using <literal>cap</literal>.
+              See the uWSGI <link
+              xlink:href="https://uwsgi-docs.readthedocs.io/en/latest/Capabilities.html">docs</link>
+              for more information.
+            </para>
+          </note>
+        '';
       };
 
       extraArgs = mkOption {
@@ -156,19 +199,23 @@ in {
   };
 
   config = mkIf cfg.enable {
+    systemd.tmpfiles.rules = optional (cfg.runDir != "/run/uwsgi") ''
+      d ${cfg.runDir} 775 ${cfg.user} ${cfg.group}
+    '';
+
     systemd.services.uwsgi = {
       wantedBy = [ "multi-user.target" ];
-      preStart = ''
-        mkdir -p ${cfg.runDir}
-        chown ${cfg.user}:${cfg.group} ${cfg.runDir}
-      '';
       serviceConfig = {
+        User = cfg.user;
+        Group = cfg.group;
         Type = "notify";
-        ExecStart = "${cfg.package}/bin/uwsgi --uid ${cfg.user} --gid ${cfg.group} ${escapeShellArgs cfg.extraArgs} --json ${buildCfg "server" cfg.instance}/server.json";
+        ExecStart = "${cfg.package}/bin/uwsgi ${escapeShellArgs cfg.extraArgs} --json ${buildCfg "server" cfg.instance}/server.json";
         ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
         ExecStop = "${pkgs.coreutils}/bin/kill -INT $MAINPID";
         NotifyAccess = "main";
         KillSignal = "SIGQUIT";
+        AmbientCapabilities = cfg.capabilities;
+        CapabilityBoundingSet = cfg.capabilities;
       };
     };
 
diff --git a/nixpkgs/nixos/modules/services/x11/desktop-managers/gnome3.nix b/nixpkgs/nixos/modules/services/x11/desktop-managers/gnome3.nix
index 68a65d77d62f..a36a47d376b6 100644
--- a/nixpkgs/nixos/modules/services/x11/desktop-managers/gnome3.nix
+++ b/nixpkgs/nixos/modules/services/x11/desktop-managers/gnome3.nix
@@ -19,7 +19,7 @@ let
 
   defaultFavoriteAppsOverride = ''
     [org.gnome.shell]
-    favorite-apps=[ 'org.gnome.Geary.desktop', 'org.gnome.Calendar.desktop', 'org.gnome.Music.desktop', 'org.gnome.Photos.desktop', 'org.gnome.Nautilus.desktop' ]
+    favorite-apps=[ 'org.gnome.Epiphany.desktop', 'org.gnome.Geary.desktop', 'org.gnome.Calendar.desktop', 'org.gnome.Music.desktop', 'org.gnome.Photos.desktop', 'org.gnome.Nautilus.desktop' ]
   '';
 
   nixos-gsettings-desktop-schemas = let
@@ -409,9 +409,7 @@ in
         baobab
         cheese
         eog
-        /* Not in good standing on nixos:
-         * https://github.com/NixOS/nixpkgs/issues/98819
-        /* epiphany */
+        epiphany
         gedit
         gnome-calculator
         gnome-calendar
diff --git a/nixpkgs/nixos/modules/services/x11/desktop-managers/plasma5.nix b/nixpkgs/nixos/modules/services/x11/desktop-managers/plasma5.nix
index 5f1c099c283d..d6cf86d3a2e6 100644
--- a/nixpkgs/nixos/modules/services/x11/desktop-managers/plasma5.nix
+++ b/nixpkgs/nixos/modules/services/x11/desktop-managers/plasma5.nix
@@ -7,8 +7,8 @@ let
   xcfg = config.services.xserver;
   cfg = xcfg.desktopManager.plasma5;
 
-  inherit (pkgs) kdeApplications kdeFrameworks plasma5;
-  inherit (pkgs) qt5 libsForQt5;
+  libsForQt5 = pkgs.plasma5Packages;
+  inherit (libsForQt5) kdeApplications kdeFrameworks plasma5;
   inherit (pkgs) writeText;
 
   pulseaudio = config.hardware.pulseaudio;
@@ -198,8 +198,8 @@ in
       };
 
       security.wrappers = {
-        kcheckpass.source = "${lib.getBin plasma5.kscreenlocker}/libexec/kcheckpass";
-        start_kdeinit.source = "${lib.getBin pkgs.kdeFrameworks.kinit}/libexec/kf5/start_kdeinit";
+        kcheckpass.source = "${lib.getBin libsForQt5.kscreenlocker}/libexec/kcheckpass";
+        start_kdeinit.source = "${lib.getBin libsForQt5.kinit}/libexec/kf5/start_kdeinit";
         kwin_wayland = {
           source = "${lib.getBin plasma5.kwin}/bin/kwin_wayland";
           capabilities = "cap_sys_nice+ep";
@@ -213,7 +213,7 @@ in
       '';
 
       environment.systemPackages =
-        with qt5; with libsForQt5;
+        with libsForQt5;
         with plasma5; with kdeApplications; with kdeFrameworks;
         [
           frameworkintegration
diff --git a/nixpkgs/nixos/modules/services/x11/hardware/libinput.nix b/nixpkgs/nixos/modules/services/x11/hardware/libinput.nix
index 9548ecb8ef6d..9b0757153cc2 100644
--- a/nixpkgs/nixos/modules/services/x11/hardware/libinput.nix
+++ b/nixpkgs/nixos/modules/services/x11/hardware/libinput.nix
@@ -3,23 +3,18 @@
 with lib;
 
 let cfg = config.services.xserver.libinput;
-    xorgBool = v: if v then "on" else "off";
-in {
 
-  options = {
-
-    services.xserver.libinput = {
-
-      enable = mkEnableOption "libinput";
+    xorgBool = v: if v then "on" else "off";
 
+    mkConfigForDevice = deviceType: {
       dev = mkOption {
         type = types.nullOr types.str;
         default = null;
         example = "/dev/input/event0";
         description =
           ''
-            Path for touchpad device.  Set to null to apply to any
-            auto-detected touchpad.
+            Path for ${deviceType} device.  Set to null to apply to any
+            auto-detected ${deviceType}.
           '';
       };
 
@@ -185,14 +180,64 @@ in {
           Option "DragLockButtons" "L1 B1 L2 B2"
         '';
         description = ''
-          Additional options for libinput touchpad driver. See
+          Additional options for libinput ${deviceType} driver. See
           <citerefentry><refentrytitle>libinput</refentrytitle><manvolnum>4</manvolnum></citerefentry>
           for available options.";
         '';
       };
-
     };
 
+    mkX11ConfigForDevice = deviceType: matchIs: ''
+        Identifier "libinput ${deviceType} configuration"
+        MatchDriver "libinput"
+        MatchIs${matchIs} "${xorgBool true}"
+        ${optionalString (cfg.${deviceType}.dev != null) ''MatchDevicePath "${cfg.${deviceType}.dev}"''}
+        Option "AccelProfile" "${cfg.${deviceType}.accelProfile}"
+        ${optionalString (cfg.${deviceType}.accelSpeed != null) ''Option "AccelSpeed" "${cfg.${deviceType}.accelSpeed}"''}
+        ${optionalString (cfg.${deviceType}.buttonMapping != null) ''Option "ButtonMapping" "${cfg.${deviceType}.buttonMapping}"''}
+        ${optionalString (cfg.${deviceType}.calibrationMatrix != null) ''Option "CalibrationMatrix" "${cfg.${deviceType}.calibrationMatrix}"''}
+        ${optionalString (cfg.${deviceType}.clickMethod != null) ''Option "ClickMethod" "${cfg.${deviceType}.clickMethod}"''}
+        Option "LeftHanded" "${xorgBool cfg.${deviceType}.leftHanded}"
+        Option "MiddleEmulation" "${xorgBool cfg.${deviceType}.middleEmulation}"
+        Option "NaturalScrolling" "${xorgBool cfg.${deviceType}.naturalScrolling}"
+        ${optionalString (cfg.${deviceType}.scrollButton != null) ''Option "ScrollButton" "${toString cfg.${deviceType}.scrollButton}"''}
+        Option "ScrollMethod" "${cfg.${deviceType}.scrollMethod}"
+        Option "HorizontalScrolling" "${xorgBool cfg.${deviceType}.horizontalScrolling}"
+        Option "SendEventsMode" "${cfg.${deviceType}.sendEventsMode}"
+        Option "Tapping" "${xorgBool cfg.${deviceType}.tapping}"
+        Option "TappingDragLock" "${xorgBool cfg.${deviceType}.tappingDragLock}"
+        Option "DisableWhileTyping" "${xorgBool cfg.${deviceType}.disableWhileTyping}"
+        ${cfg.${deviceType}.additionalOptions}
+  '';
+in {
+
+  imports =
+    (map (option: mkRenamedOptionModule ([ "services" "xserver" "libinput" option ]) [ "services" "xserver" "libinput" "touchpad" option ]) [
+      "accelProfile"
+      "accelSpeed"
+      "buttonMapping"
+      "calibrationMatrix"
+      "clickMethod"
+      "leftHanded"
+      "middleEmulation"
+      "naturalScrolling"
+      "scrollButton"
+      "scrollMethod"
+      "horizontalScrolling"
+      "sendEventsMode"
+      "tapping"
+      "tappingDragLock"
+      "disableWhileTyping"
+      "additionalOptions"
+    ]);
+
+  options = {
+
+    services.xserver.libinput = {
+      enable = mkEnableOption "libinput";
+      mouse = mkConfigForDevice "mouse";
+      touchpad = mkConfigForDevice "touchpad";
+    };
   };
 
 
@@ -212,32 +257,10 @@ in {
 
     services.udev.packages = [ pkgs.libinput.out ];
 
-    services.xserver.config =
-      ''
-        # General libinput configuration.
-        # See CONFIGURATION DETAILS section of man:libinput(4).
-        Section "InputClass"
-          Identifier "libinputConfiguration"
-          MatchDriver "libinput"
-          ${optionalString (cfg.dev != null) ''MatchDevicePath "${cfg.dev}"''}
-          Option "AccelProfile" "${cfg.accelProfile}"
-          ${optionalString (cfg.accelSpeed != null) ''Option "AccelSpeed" "${cfg.accelSpeed}"''}
-          ${optionalString (cfg.buttonMapping != null) ''Option "ButtonMapping" "${cfg.buttonMapping}"''}
-          ${optionalString (cfg.calibrationMatrix != null) ''Option "CalibrationMatrix" "${cfg.calibrationMatrix}"''}
-          ${optionalString (cfg.clickMethod != null) ''Option "ClickMethod" "${cfg.clickMethod}"''}
-          Option "LeftHanded" "${xorgBool cfg.leftHanded}"
-          Option "MiddleEmulation" "${xorgBool cfg.middleEmulation}"
-          Option "NaturalScrolling" "${xorgBool cfg.naturalScrolling}"
-          ${optionalString (cfg.scrollButton != null) ''Option "ScrollButton" "${toString cfg.scrollButton}"''}
-          Option "ScrollMethod" "${cfg.scrollMethod}"
-          Option "HorizontalScrolling" "${xorgBool cfg.horizontalScrolling}"
-          Option "SendEventsMode" "${cfg.sendEventsMode}"
-          Option "Tapping" "${xorgBool cfg.tapping}"
-          Option "TappingDragLock" "${xorgBool cfg.tappingDragLock}"
-          Option "DisableWhileTyping" "${xorgBool cfg.disableWhileTyping}"
-          ${cfg.additionalOptions}
-        EndSection
-      '';
+    services.xserver.inputClassSections = [
+      (mkX11ConfigForDevice "mouse" "Pointer")
+      (mkX11ConfigForDevice "touchpad" "Touchpad")
+    ];
 
     assertions = [
       # already present in synaptics.nix
diff --git a/nixpkgs/nixos/modules/services/x11/window-managers/clfswm.nix b/nixpkgs/nixos/modules/services/x11/window-managers/clfswm.nix
index 176c1f461271..171660c53ac3 100644
--- a/nixpkgs/nixos/modules/services/x11/window-managers/clfswm.nix
+++ b/nixpkgs/nixos/modules/services/x11/window-managers/clfswm.nix
@@ -15,10 +15,10 @@ in
     services.xserver.windowManager.session = singleton {
       name = "clfswm";
       start = ''
-        ${pkgs.clfswm}/bin/clfswm &
+        ${pkgs.lispPackages.clfswm}/bin/clfswm &
         waitPID=$!
       '';
     };
-    environment.systemPackages = [ pkgs.clfswm ];
+    environment.systemPackages = [ pkgs.lispPackages.clfswm ];
   };
 }
diff --git a/nixpkgs/nixos/modules/services/x11/window-managers/default.nix b/nixpkgs/nixos/modules/services/x11/window-managers/default.nix
index 87702c58727a..9ca24310e567 100644
--- a/nixpkgs/nixos/modules/services/x11/window-managers/default.nix
+++ b/nixpkgs/nixos/modules/services/x11/window-managers/default.nix
@@ -13,6 +13,7 @@ in
     ./berry.nix
     ./bspwm.nix
     ./cwm.nix
+    ./clfswm.nix
     ./dwm.nix
     ./evilwm.nix
     ./exwm.nix
diff --git a/nixpkgs/nixos/modules/services/x11/window-managers/exwm.nix b/nixpkgs/nixos/modules/services/x11/window-managers/exwm.nix
index 88e13f4dbfb0..3e97d28d83b5 100644
--- a/nixpkgs/nixos/modules/services/x11/window-managers/exwm.nix
+++ b/nixpkgs/nixos/modules/services/x11/window-managers/exwm.nix
@@ -48,7 +48,7 @@ in
         description = ''
           Extra packages available to Emacs. The value must be a
           function which receives the attrset defined in
-          <varname>emacsPackages</varname> as the sole argument.
+          <varname>emacs.pkgs</varname> as the sole argument.
         '';
       };
     };
diff --git a/nixpkgs/nixos/modules/system/activation/top-level.nix b/nixpkgs/nixos/modules/system/activation/top-level.nix
index 03d7e7493230..b0f77ca3fb8d 100644
--- a/nixpkgs/nixos/modules/system/activation/top-level.nix
+++ b/nixpkgs/nixos/modules/system/activation/top-level.nix
@@ -190,7 +190,7 @@ in
 
     system.boot.loader.kernelFile = mkOption {
       internal = true;
-      default = pkgs.stdenv.hostPlatform.platform.kernelTarget;
+      default = pkgs.stdenv.hostPlatform.linux-kernel.target;
       type = types.str;
       description = ''
         Name of the kernel file to be passed to the bootloader.
diff --git a/nixpkgs/nixos/modules/system/boot/binfmt.nix b/nixpkgs/nixos/modules/system/boot/binfmt.nix
index 9eeae0c3ef44..5bcc95be324a 100644
--- a/nixpkgs/nixos/modules/system/boot/binfmt.nix
+++ b/nixpkgs/nixos/modules/system/boot/binfmt.nix
@@ -20,8 +20,14 @@ let
                  optionalString fixBinary "F";
   in ":${name}:${type}:${offset'}:${magicOrExtension}:${mask'}:${interpreter}:${flags}";
 
-  activationSnippet = name: { interpreter, ... }:
-    "ln -sf ${interpreter} /run/binfmt/${name}";
+  activationSnippet = name: { interpreter, ... }: ''
+    rm -f /run/binfmt/${name}
+    cat > /run/binfmt/${name} << 'EOF'
+    #!/usr/bin/env sh
+    exec -- ${interpreter} "$@"
+    EOF
+    chmod +x /run/binfmt/${name}
+  '';
 
   getEmulator = system: (lib.systems.elaborate { inherit system; }).emulator pkgs;
 
diff --git a/nixpkgs/nixos/modules/system/boot/loader/generations-dir/generations-dir.nix b/nixpkgs/nixos/modules/system/boot/loader/generations-dir/generations-dir.nix
index 2d27611946e2..fee567a510ba 100644
--- a/nixpkgs/nixos/modules/system/boot/loader/generations-dir/generations-dir.nix
+++ b/nixpkgs/nixos/modules/system/boot/loader/generations-dir/generations-dir.nix
@@ -59,7 +59,7 @@ in
 
     system.build.installBootLoader = generationsDirBuilder;
     system.boot.loader.id = "generationsDir";
-    system.boot.loader.kernelFile = platform.kernelTarget;
+    system.boot.loader.kernelFile = linux-kernel.target;
 
   };
 }
diff --git a/nixpkgs/nixos/modules/system/boot/loader/grub/grub.nix b/nixpkgs/nixos/modules/system/boot/loader/grub/grub.nix
index df5dfaa554bc..289c2b199862 100644
--- a/nixpkgs/nixos/modules/system/boot/loader/grub/grub.nix
+++ b/nixpkgs/nixos/modules/system/boot/loader/grub/grub.nix
@@ -327,6 +327,26 @@ in
         '';
       };
 
+      extraInstallCommands = mkOption {
+        default = "";
+        example = literalExample ''
+          # the example below generates detached signatures that GRUB can verify
+          # https://www.gnu.org/software/grub/manual/grub/grub.html#Using-digital-signatures
+          ''${pkgs.findutils}/bin/find /boot -not -path "/boot/efi/*" -type f -name '*.sig' -delete
+          old_gpg_home=$GNUPGHOME
+          export GNUPGHOME="$(mktemp -d)"
+          ''${pkgs.gnupg}/bin/gpg --import ''${priv_key} > /dev/null 2>&1
+          ''${pkgs.findutils}/bin/find /boot -not -path "/boot/efi/*" -type f -exec ''${pkgs.gnupg}/bin/gpg --detach-sign "{}" \; > /dev/null 2>&1
+          rm -rf $GNUPGHOME
+          export GNUPGHOME=$old_gpg_home
+        '';
+        type = types.lines;
+        description = ''
+          Additional shell commands inserted in the bootloader installer
+          script after generating menu entries.
+        '';
+      };
+
       extraPerEntryConfig = mkOption {
         default = "";
         example = "root (hd0)";
@@ -715,7 +735,7 @@ in
         ${optionalString cfg.enableCryptodisk "export GRUB_ENABLE_CRYPTODISK=y"}
       '' + flip concatMapStrings cfg.mirroredBoots (args: ''
         ${pkgs.perl}/bin/perl ${install-grub-pl} ${grubConfig args} $@
-      ''));
+      '') + cfg.extraInstallCommands);
 
       system.build.grub = grub;
 
diff --git a/nixpkgs/nixos/modules/system/boot/loader/raspberrypi/raspberrypi.nix b/nixpkgs/nixos/modules/system/boot/loader/raspberrypi/raspberrypi.nix
index 337afe9ef628..061f2967350e 100644
--- a/nixpkgs/nixos/modules/system/boot/loader/raspberrypi/raspberrypi.nix
+++ b/nixpkgs/nixos/modules/system/boot/loader/raspberrypi/raspberrypi.nix
@@ -20,7 +20,7 @@ let
   timeoutStr = if blCfg.timeout == null then "-1" else toString blCfg.timeout;
 
   isAarch64 = pkgs.stdenv.hostPlatform.isAarch64;
-  optional = pkgs.stdenv.lib.optionalString;
+  optional = pkgs.lib.optionalString;
 
   configTxt =
     pkgs.writeText "config.txt" (''
@@ -60,8 +60,7 @@ in
       version = mkOption {
         default = 2;
         type = types.enum [ 0 1 2 3 4 ];
-        description = ''
-        '';
+        description = "";
       };
 
       uboot = {
@@ -103,6 +102,6 @@ in
 
     system.build.installBootLoader = builder;
     system.boot.loader.id = "raspberrypi";
-    system.boot.loader.kernelFile = platform.kernelTarget;
+    system.boot.loader.kernelFile = linux-kernel.target;
   };
 }
diff --git a/nixpkgs/nixos/modules/system/boot/plymouth.nix b/nixpkgs/nixos/modules/system/boot/plymouth.nix
index ddf5ef8a0a6a..662576888fc2 100644
--- a/nixpkgs/nixos/modules/system/boot/plymouth.nix
+++ b/nixpkgs/nixos/modules/system/boot/plymouth.nix
@@ -9,7 +9,7 @@ let
 
   cfg = config.boot.plymouth;
 
-  nixosBreezePlymouth = pkgs.plasma5.breeze-plymouth.override {
+  nixosBreezePlymouth = pkgs.plasma5Packages.breeze-plymouth.override {
     logoFile = cfg.logo;
     logoName = "nixos";
     osName = "NixOS";
diff --git a/nixpkgs/nixos/modules/system/boot/stage-1.nix b/nixpkgs/nixos/modules/system/boot/stage-1.nix
index 86bfde6349c3..cb9735ae04f7 100644
--- a/nixpkgs/nixos/modules/system/boot/stage-1.nix
+++ b/nixpkgs/nixos/modules/system/boot/stage-1.nix
@@ -22,7 +22,7 @@ let
     rootModules = config.boot.initrd.availableKernelModules ++ config.boot.initrd.kernelModules;
     kernel = modulesTree;
     firmware = firmware;
-    allowMissing = true;
+    allowMissing = false;
   };
 
 
@@ -513,7 +513,12 @@ in
     };
 
     boot.initrd.compressor = mkOption {
-      default = "gzip";
+      default = (
+        if lib.versionAtLeast config.boot.kernelPackages.kernel.version "5.9"
+        then "zstd"
+        else "gzip"
+      );
+      defaultText = "zstd if the kernel supports it (5.9+), gzip if not.";
       type = types.unspecified; # We don't have a function type...
       description = ''
         The compressor to use on the initrd image. May be any of:
diff --git a/nixpkgs/nixos/modules/system/boot/systemd.nix b/nixpkgs/nixos/modules/system/boot/systemd.nix
index 080a018047fe..f5e6bd2903d0 100644
--- a/nixpkgs/nixos/modules/system/boot/systemd.nix
+++ b/nixpkgs/nixos/modules/system/boot/systemd.nix
@@ -263,7 +263,7 @@ let
         }
         (mkIf (config.preStart != "")
           { serviceConfig.ExecStartPre =
-              makeJobScript "${name}-pre-start" config.preStart;
+              [ (makeJobScript "${name}-pre-start" config.preStart) ];
           })
         (mkIf (config.script != "")
           { serviceConfig.ExecStart =
@@ -271,7 +271,7 @@ let
           })
         (mkIf (config.postStart != "")
           { serviceConfig.ExecStartPost =
-              makeJobScript "${name}-post-start" config.postStart;
+              [ (makeJobScript "${name}-post-start" config.postStart) ];
           })
         (mkIf (config.reload != "")
           { serviceConfig.ExecReload =
diff --git a/nixpkgs/nixos/modules/system/boot/timesyncd.nix b/nixpkgs/nixos/modules/system/boot/timesyncd.nix
index 35fb5578b070..692315dbe99c 100644
--- a/nixpkgs/nixos/modules/system/boot/timesyncd.nix
+++ b/nixpkgs/nixos/modules/system/boot/timesyncd.nix
@@ -16,6 +16,7 @@ with lib;
       };
       servers = mkOption {
         default = config.networking.timeServers;
+        type = types.listOf types.str;
         description = ''
           The set of NTP servers from which to synchronise.
         '';
diff --git a/nixpkgs/nixos/modules/system/boot/tmp.nix b/nixpkgs/nixos/modules/system/boot/tmp.nix
index 26eb172210e7..5bb299adb15f 100644
--- a/nixpkgs/nixos/modules/system/boot/tmp.nix
+++ b/nixpkgs/nixos/modules/system/boot/tmp.nix
@@ -30,7 +30,14 @@ with lib;
 
   config = {
 
-    systemd.additionalUpstreamSystemUnits = optional config.boot.tmpOnTmpfs "tmp.mount";
+    systemd.mounts = mkIf config.boot.tmpOnTmpfs [
+      {
+        what = "tmpfs";
+        where = "/tmp";
+        type = "tmpfs";
+        mountConfig.Options = [ "mode=1777" "strictatime" "rw" "nosuid" "nodev" "size=50%" ];
+      }
+    ];
 
     systemd.tmpfiles.rules = optional config.boot.cleanTmpDir "D! /tmp 1777 root root";
 
diff --git a/nixpkgs/nixos/modules/tasks/filesystems/zfs.nix b/nixpkgs/nixos/modules/tasks/filesystems/zfs.nix
index 6becc6962735..16ba0b746789 100644
--- a/nixpkgs/nixos/modules/tasks/filesystems/zfs.nix
+++ b/nixpkgs/nixos/modules/tasks/filesystems/zfs.nix
@@ -662,8 +662,10 @@ in
         # - HDDs are mixed with SSDs
         # - There is a SSDs in a pool that is currently trimmed.
         # - There are only HDDs and we would set the system in a degraded state
-        serviceConfig.ExecStart = ''${pkgs.runtimeShell} -c 'for pool in $(zpool list -H -o name); do zpool trim $pool;  done || true' '';
+        serviceConfig.ExecStart = "${pkgs.runtimeShell} -c 'for pool in $(zpool list -H -o name); do zpool trim $pool;  done || true' ";
       };
+
+      systemd.timers.zpool-trim.timerConfig.Persistent = "yes";
     })
   ];
 }
diff --git a/nixpkgs/nixos/modules/virtualisation/azure-agent.nix b/nixpkgs/nixos/modules/virtualisation/azure-agent.nix
index 81413792eda0..41f3fa0e6642 100644
--- a/nixpkgs/nixos/modules/virtualisation/azure-agent.nix
+++ b/nixpkgs/nixos/modules/virtualisation/azure-agent.nix
@@ -146,7 +146,7 @@ in
 
     services.logrotate = {
       enable = true;
-      config = ''
+      extraConfig = ''
         /var/log/waagent.log {
             compress
             monthly
diff --git a/nixpkgs/nixos/modules/virtualisation/docker.nix b/nixpkgs/nixos/modules/virtualisation/docker.nix
index ec257801b330..689f664b676d 100644
--- a/nixpkgs/nixos/modules/virtualisation/docker.nix
+++ b/nixpkgs/nixos/modules/virtualisation/docker.nix
@@ -155,13 +155,11 @@ in
       users.groups.docker.gid = config.ids.gids.docker;
       systemd.packages = [ cfg.package ];
 
-      # TODO: remove once docker 20.10 is released
-      systemd.enableUnifiedCgroupHierarchy = false;
-
       systemd.services.docker = {
         wantedBy = optional cfg.enableOnBoot "multi-user.target";
         environment = proxy_env;
         serviceConfig = {
+          Type = "notify";
           ExecStart = [
             ""
             ''
@@ -215,13 +213,10 @@ in
           message = "Option enableNvidia requires 32bit support libraries";
         }];
     }
-    (mkIf cfg.enableNvidia {
-      environment.etc."nvidia-container-runtime/config.toml".source = "${pkgs.nvidia-docker}/etc/config.toml";
-    })
   ]);
 
   imports = [
-    (mkRemovedOptionModule ["virtualisation" "docker" "socketActivation"] "This option was removed in favor of starting docker at boot")
+    (mkRemovedOptionModule ["virtualisation" "docker" "socketActivation"] "This option was removed and socket activation is now always active")
   ];
 
 }
diff --git a/nixpkgs/nixos/modules/virtualisation/ec2-amis.nix b/nixpkgs/nixos/modules/virtualisation/ec2-amis.nix
index 3da63078a214..892af513b032 100644
--- a/nixpkgs/nixos/modules/virtualisation/ec2-amis.nix
+++ b/nixpkgs/nixos/modules/virtualisation/ec2-amis.nix
@@ -329,24 +329,24 @@ let self = {
   "20.03".ap-east-1.hvm-ebs = "ami-0d18fdd309cdefa86";
   "20.03".sa-east-1.hvm-ebs = "ami-09859378158ae971d";
 
-  # 20.09.1632.a6a3a368dda
-  "20.09".eu-west-1.hvm-ebs = "ami-01a79d5ce435f4db3";
-  "20.09".eu-west-2.hvm-ebs = "ami-0cbe14f32904e6331";
-  "20.09".eu-west-3.hvm-ebs = "ami-07f493412d6213de6";
-  "20.09".eu-central-1.hvm-ebs = "ami-01d4a0c2248cbfe38";
-  "20.09".eu-north-1.hvm-ebs = "ami-0003f54dd99d68e0f";
-  "20.09".us-east-1.hvm-ebs = "ami-068a62d478710462d";
-  "20.09".us-east-2.hvm-ebs = "ami-01ac677ff61399caa";
-  "20.09".us-west-1.hvm-ebs = "ami-04befdb203b4b17f6";
-  "20.09".us-west-2.hvm-ebs = "ami-0fb7bd4a43261c6b2";
-  "20.09".ca-central-1.hvm-ebs = "ami-06d5ee429f153f856";
-  "20.09".ap-southeast-1.hvm-ebs = "ami-0db0304e23c535b2a";
-  "20.09".ap-southeast-2.hvm-ebs = "ami-045983c4db7e36447";
-  "20.09".ap-northeast-1.hvm-ebs = "ami-0beb18d632cf64e5a";
-  "20.09".ap-northeast-2.hvm-ebs = "ami-0dd0316af578862db";
-  "20.09".ap-south-1.hvm-ebs = "ami-008d15ced81c88aed";
-  "20.09".ap-east-1.hvm-ebs = "ami-071f49713f86ea965";
-  "20.09".sa-east-1.hvm-ebs = "ami-05ded1ae35209b5a8";
+  # 20.09.2016.19db3e5ea27
+  "20.09".eu-west-1.hvm-ebs = "ami-0057cb7d614329fa2";
+  "20.09".eu-west-2.hvm-ebs = "ami-0d46f16e0bb0ec8fd";
+  "20.09".eu-west-3.hvm-ebs = "ami-0e8985c3ea42f87fe";
+  "20.09".eu-central-1.hvm-ebs = "ami-0eed77c38432886d2";
+  "20.09".eu-north-1.hvm-ebs = "ami-0be5bcadd632bea14";
+  "20.09".us-east-1.hvm-ebs = "ami-0a2cce52b42daccc8";
+  "20.09".us-east-2.hvm-ebs = "ami-09378bf487b07a4d8";
+  "20.09".us-west-1.hvm-ebs = "ami-09b4337b2a9e77485";
+  "20.09".us-west-2.hvm-ebs = "ami-081d3bb5fbee0a1ac";
+  "20.09".ca-central-1.hvm-ebs = "ami-020c24c6c607e7ac7";
+  "20.09".ap-southeast-1.hvm-ebs = "ami-08f648d5db009e67d";
+  "20.09".ap-southeast-2.hvm-ebs = "ami-0be390efaccbd40f9";
+  "20.09".ap-northeast-1.hvm-ebs = "ami-0c3311601cbe8f927";
+  "20.09".ap-northeast-2.hvm-ebs = "ami-0020146701f4d56cf";
+  "20.09".ap-south-1.hvm-ebs = "ami-0117e2bd876bb40d1";
+  "20.09".ap-east-1.hvm-ebs = "ami-0c42f97e5b1fda92f";
+  "20.09".sa-east-1.hvm-ebs = "ami-021637976b094959d";
 
   latest = self."20.09";
 }; in self
diff --git a/nixpkgs/nixos/modules/virtualisation/google-compute-image.nix b/nixpkgs/nixos/modules/virtualisation/google-compute-image.nix
index d172ae38fdcf..e2332df611aa 100644
--- a/nixpkgs/nixos/modules/virtualisation/google-compute-image.nix
+++ b/nixpkgs/nixos/modules/virtualisation/google-compute-image.nix
@@ -43,7 +43,7 @@ in
     system.build.googleComputeImage = import ../../lib/make-disk-image.nix {
       name = "google-compute-image";
       postVM = ''
-        PATH=$PATH:${with pkgs; stdenv.lib.makeBinPath [ gnutar gzip ]}
+        PATH=$PATH:${with pkgs; lib.makeBinPath [ gnutar gzip ]}
         pushd $out
         mv $diskImage disk.raw
         tar -Szcf nixos-image-${config.system.nixos.label}-${pkgs.stdenv.hostPlatform.system}.raw.tar.gz disk.raw
diff --git a/nixpkgs/nixos/modules/virtualisation/lxc-container.nix b/nixpkgs/nixos/modules/virtualisation/lxc-container.nix
index d49364840187..e47bd59dc016 100644
--- a/nixpkgs/nixos/modules/virtualisation/lxc-container.nix
+++ b/nixpkgs/nixos/modules/virtualisation/lxc-container.nix
@@ -11,7 +11,7 @@ with lib;
   users.users.root.initialHashedPassword = mkOverride 150 "";
 
   # Some more help text.
-  services.mingetty.helpLine =
+  services.getty.helpLine =
     ''
 
       Log in as "root" with an empty password.
diff --git a/nixpkgs/nixos/modules/virtualisation/lxd.nix b/nixpkgs/nixos/modules/virtualisation/lxd.nix
index 3958fc2c1d7c..103e689abae8 100644
--- a/nixpkgs/nixos/modules/virtualisation/lxd.nix
+++ b/nixpkgs/nixos/modules/virtualisation/lxd.nix
@@ -100,6 +100,10 @@ in
       packages = [ cfg.lxcPackage ];
     };
 
+    # TODO: remove once LXD gets proper support for cgroupsv2
+    # (currently most of the e.g. CPU accounting stuff doesn't work)
+    systemd.enableUnifiedCgroupHierarchy = false;
+
     systemd.services.lxd = {
       description = "LXD Container Management Daemon";
 
diff --git a/nixpkgs/nixos/modules/virtualisation/nixos-containers.nix b/nixpkgs/nixos/modules/virtualisation/nixos-containers.nix
index 757d73421b8f..7bec1b1ff26e 100644
--- a/nixpkgs/nixos/modules/virtualisation/nixos-containers.nix
+++ b/nixpkgs/nixos/modules/virtualisation/nixos-containers.nix
@@ -170,7 +170,7 @@ let
 
       ${concatStringsSep "\n" (
         mapAttrsToList (name: cfg:
-          ''ip link del dev ${name} 2> /dev/null || true ''
+          "ip link del dev ${name} 2> /dev/null || true "
         ) cfg.extraVeths
       )}
    '';
@@ -185,7 +185,7 @@ let
             fi
           ''
         else
-          ''${ipcmd} add ${cfg.${attribute}} dev $ifaceHost'';
+          "${ipcmd} add ${cfg.${attribute}} dev $ifaceHost";
       renderExtraVeth = name: cfg:
         if cfg.hostBridge != null then
           ''
diff --git a/nixpkgs/nixos/modules/virtualisation/podman.nix b/nixpkgs/nixos/modules/virtualisation/podman.nix
index f554aeffb451..98da5a096d91 100644
--- a/nixpkgs/nixos/modules/virtualisation/podman.nix
+++ b/nixpkgs/nixos/modules/virtualisation/podman.nix
@@ -1,6 +1,7 @@
 { config, lib, pkgs, utils, ... }:
 let
   cfg = config.virtualisation.podman;
+  toml = pkgs.formats.toml { };
 
   inherit (lib) mkOption types;
 
@@ -53,6 +54,14 @@ in
       '';
     };
 
+    enableNvidia = mkOption {
+      type = types.bool;
+      default = false;
+      description = ''
+        Enable use of NVidia GPUs from within podman containers.
+      '';
+    };
+
     extraPackages = mkOption {
       type = with types; listOf package;
       default = [ ];
@@ -78,21 +87,30 @@ in
 
   };
 
-  config = lib.mkIf cfg.enable {
-
-    environment.systemPackages = [ cfg.package ]
-      ++ lib.optional cfg.dockerCompat dockerCompat;
-
-    environment.etc."cni/net.d/87-podman-bridge.conflist".source = utils.copyFile "${pkgs.podman-unwrapped.src}/cni/87-podman-bridge.conflist";
-
-    # Enable common /etc/containers configuration
-    virtualisation.containers.enable = true;
-
-    assertions = [{
-      assertion = cfg.dockerCompat -> !config.virtualisation.docker.enable;
-      message = "Option dockerCompat conflicts with docker";
-    }];
-
-  };
+  config = lib.mkIf cfg.enable (lib.mkMerge [
+    {
+      environment.systemPackages = [ cfg.package ]
+        ++ lib.optional cfg.dockerCompat dockerCompat;
+
+      environment.etc."cni/net.d/87-podman-bridge.conflist".source = utils.copyFile "${pkgs.podman-unwrapped.src}/cni/87-podman-bridge.conflist";
+
+      virtualisation.containers = {
+        enable = true; # Enable common /etc/containers configuration
+        containersConf.extraConfig = lib.optionalString cfg.enableNvidia
+          (builtins.readFile (toml.generate "podman.nvidia.containers.conf" {
+            engine = {
+              conmon_env_vars = [ "PATH=${lib.makeBinPath [ pkgs.nvidia-podman ]}" ];
+              runtimes.nvidia = [ "${pkgs.nvidia-podman}/bin/nvidia-container-runtime" ];
+            };
+          }));
+      };
 
+      assertions = [
+        {
+          assertion = cfg.dockerCompat -> !config.virtualisation.docker.enable;
+          message = "Option dockerCompat conflicts with docker";
+        }
+      ];
+    }
+  ]);
 }
diff --git a/nixpkgs/nixos/modules/virtualisation/qemu-vm.nix b/nixpkgs/nixos/modules/virtualisation/qemu-vm.nix
index 447d1f091c8c..bf3615f2fe71 100644
--- a/nixpkgs/nixos/modules/virtualisation/qemu-vm.nix
+++ b/nixpkgs/nixos/modules/virtualisation/qemu-vm.nix
@@ -136,10 +136,8 @@ let
             cp ${bootDisk}/efi-vars.fd "$NIX_EFI_VARS" || exit 1
             chmod 0644 "$NIX_EFI_VARS" || exit 1
           fi
-        '' else ''
-        ''}
-      '' else ''
-      ''}
+        '' else ""}
+      '' else ""}
 
       cd $TMPDIR
       idx=0
@@ -187,8 +185,7 @@ let
                 efiVars=$out/efi-vars.fd
                 cp ${efiVarsDefault} $efiVars
                 chmod 0644 $efiVars
-              '' else ''
-              ''}
+              '' else ""}
             '';
           buildInputs = [ pkgs.util-linux ];
           QEMU_OPTS = "-nographic -serial stdio -monitor none"
diff --git a/nixpkgs/nixos/modules/virtualisation/railcar.nix b/nixpkgs/nixos/modules/virtualisation/railcar.nix
index 10464f628984..b603effef6e0 100644
--- a/nixpkgs/nixos/modules/virtualisation/railcar.nix
+++ b/nixpkgs/nixos/modules/virtualisation/railcar.nix
@@ -105,7 +105,7 @@ in
 
     stateDir = mkOption {
       type = types.path;
-      default = ''/var/railcar'';
+      default = "/var/railcar";
       description = "Railcar persistent state directory";
     };