about summary refs log tree commit diff
path: root/nixos
diff options
context:
space:
mode:
Diffstat (limited to 'nixos')
-rw-r--r--nixos/modules/config/swap.nix7
-rw-r--r--nixos/modules/installer/tools/nixos-generate-config.pl8
-rw-r--r--nixos/modules/misc/locate.nix4
-rw-r--r--nixos/modules/module-list.nix2
-rw-r--r--nixos/modules/profiles/base.nix1
-rw-r--r--nixos/modules/profiles/minimal.nix2
-rw-r--r--nixos/modules/security/pam.nix334
-rw-r--r--nixos/modules/services/databases/hbase.nix38
-rw-r--r--nixos/modules/services/logging/logstash.nix13
-rw-r--r--nixos/modules/services/matrix/mjolnir.nix2
-rw-r--r--nixos/modules/services/misc/plex.nix2
-rw-r--r--nixos/modules/services/misc/xmrig.nix10
-rw-r--r--nixos/modules/services/monitoring/cadvisor.nix2
-rw-r--r--nixos/modules/services/monitoring/prometheus/exporters/nginx.nix2
-rw-r--r--nixos/modules/services/monitoring/zabbix-server.nix7
-rw-r--r--nixos/modules/services/network-filesystems/webdav.nix107
-rw-r--r--nixos/modules/services/ttys/getty.nix15
-rw-r--r--nixos/modules/services/web-servers/nginx/default.nix2
-rw-r--r--nixos/modules/services/x11/display-managers/startx.nix3
-rw-r--r--nixos/modules/services/x11/display-managers/sx.nix5
-rw-r--r--nixos/modules/services/x11/hardware/libinput.nix15
-rw-r--r--nixos/modules/services/x11/xserver.nix24
-rw-r--r--nixos/modules/system/boot/networkd.nix44
-rw-r--r--nixos/modules/tasks/auto-upgrade.nix1
-rw-r--r--nixos/modules/virtualisation/qemu-vm.nix2
-rw-r--r--nixos/tests/all-tests.nix4
-rw-r--r--nixos/tests/libinput.nix38
-rw-r--r--nixos/tests/libresprite.nix30
28 files changed, 523 insertions, 201 deletions
diff --git a/nixos/modules/config/swap.nix b/nixos/modules/config/swap.nix
index 9b005021086be..2b94b954cb80f 100644
--- a/nixos/modules/config/swap.nix
+++ b/nixos/modules/config/swap.nix
@@ -203,7 +203,6 @@ in
     ];
 
     # Create missing swapfiles.
-    # FIXME: support changing the size of existing swapfiles.
     systemd.services =
       let
 
@@ -223,11 +222,7 @@ in
                 ${optionalString (sw.size != null) ''
                   currentSize=$(( $(stat -c "%s" "${sw.device}" 2>/dev/null || echo 0) / 1024 / 1024 ))
                   if [ "${toString sw.size}" != "$currentSize" ]; then
-                    fallocate -l ${toString sw.size}M "${sw.device}" ||
-                      dd if=/dev/zero of="${sw.device}" bs=1M count=${toString sw.size}
-                    if [ "${toString sw.size}" -lt "$currentSize" ]; then
-                      truncate --size "${toString sw.size}M" "${sw.device}"
-                    fi
+                    dd if=/dev/zero of="${sw.device}" bs=1M count=${toString sw.size}
                     chmod 0600 ${sw.device}
                     ${optionalString (!sw.randomEncryption.enable) "mkswap ${sw.realDevice}"}
                   fi
diff --git a/nixos/modules/installer/tools/nixos-generate-config.pl b/nixos/modules/installer/tools/nixos-generate-config.pl
index 7bc55e67134b6..fe8c4fb1a6b5f 100644
--- a/nixos/modules/installer/tools/nixos-generate-config.pl
+++ b/nixos/modules/installer/tools/nixos-generate-config.pl
@@ -91,6 +91,11 @@ sub hasCPUFeature {
 }
 
 
+sub cpuManufacturer {
+    my $id = shift;
+    return $cpuinfo =~ /^vendor_id\s*:.* $id$/m;
+}
+
 
 # Determine CPU governor to use
 if (-e "/sys/devices/system/cpu/cpu0/cpufreq/scaling_available_governors") {
@@ -111,6 +116,9 @@ if (-e "/sys/devices/system/cpu/cpu0/cpufreq/scaling_available_governors") {
 push @kernelModules, "kvm-intel" if hasCPUFeature "vmx";
 push @kernelModules, "kvm-amd" if hasCPUFeature "svm";
 
+push @attrs, "hardware.cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;" if cpuManufacturer "AuthenticAMD";
+push @attrs, "hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;" if cpuManufacturer "GenuineIntel";
+
 
 # Look at the PCI devices and add necessary modules.  Note that most
 # modules are auto-detected so we don't need to list them here.
diff --git a/nixos/modules/misc/locate.nix b/nixos/modules/misc/locate.nix
index 2f2986c2fec5a..3638bebed931b 100644
--- a/nixos/modules/misc/locate.nix
+++ b/nixos/modules/misc/locate.nix
@@ -149,7 +149,7 @@ in {
 
     prunePaths = mkOption {
       type = listOf path;
-      default = ["/tmp" "/var/tmp" "/var/cache" "/var/lock" "/var/run" "/var/spool" "/nix/store"];
+      default = [ "/tmp" "/var/tmp" "/var/cache" "/var/lock" "/var/run" "/var/spool" "/nix/store" "/nix/var/log/nix" ];
       description = ''
         Which paths to exclude from indexing
       '';
@@ -157,7 +157,7 @@ in {
 
     pruneNames = mkOption {
       type = listOf str;
-      default = [];
+      default = [ ".bzr" ".cache" ".git" ".hg" ".svn" ];
       description = ''
         Directory components which should exclude paths containing them from indexing
       '';
diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix
index 4ee79b4396026..9eca0b8d65f23 100644
--- a/nixos/modules/module-list.nix
+++ b/nixos/modules/module-list.nix
@@ -611,6 +611,7 @@
   ./services/misc/uhub.nix
   ./services/misc/weechat.nix
   ./services/misc/xmr-stak.nix
+  ./services/misc/xmrig.nix
   ./services/misc/zigbee2mqtt.nix
   ./services/misc/zoneminder.nix
   ./services/misc/zookeeper.nix
@@ -683,6 +684,7 @@
   ./services/network-filesystems/tahoe.nix
   ./services/network-filesystems/diod.nix
   ./services/network-filesystems/u9fs.nix
+  ./services/network-filesystems/webdav.nix
   ./services/network-filesystems/yandex-disk.nix
   ./services/network-filesystems/xtreemfs.nix
   ./services/network-filesystems/ceph.nix
diff --git a/nixos/modules/profiles/base.nix b/nixos/modules/profiles/base.nix
index 3b67d628f9fd7..33dd80d7c5abd 100644
--- a/nixos/modules/profiles/base.nix
+++ b/nixos/modules/profiles/base.nix
@@ -40,6 +40,7 @@
     # Tools to create / manipulate filesystems.
     pkgs.ntfsprogs # for resizing NTFS partitions
     pkgs.dosfstools
+    pkgs.mtools
     pkgs.xfsprogs.bin
     pkgs.jfsutils
     pkgs.f2fs-tools
diff --git a/nixos/modules/profiles/minimal.nix b/nixos/modules/profiles/minimal.nix
index f044e6f39ea5a..e79b927238419 100644
--- a/nixos/modules/profiles/minimal.nix
+++ b/nixos/modules/profiles/minimal.nix
@@ -14,4 +14,6 @@ with lib;
   documentation.enable = mkDefault false;
 
   documentation.nixos.enable = mkDefault false;
+
+  programs.command-not-found.enable = mkDefault false;
 }
diff --git a/nixos/modules/security/pam.nix b/nixos/modules/security/pam.nix
index 40df6c67ef842..70bce783a90b6 100644
--- a/nixos/modules/security/pam.nix
+++ b/nixos/modules/security/pam.nix
@@ -410,46 +410,64 @@ let
       # Samba stuff to the Samba module.  This requires that the PAM
       # module provides the right hooks.
       text = mkDefault
-        (''
-          # Account management.
-          account required pam_unix.so
-          ${optionalString use_ldap
-              "account sufficient ${pam_ldap}/lib/security/pam_ldap.so"}
-          ${optionalString (config.services.sssd.enable && cfg.sssdStrictAccess==false)
-              "account sufficient ${pkgs.sssd}/lib/security/pam_sss.so"}
-          ${optionalString (config.services.sssd.enable && cfg.sssdStrictAccess)
-              "account [default=bad success=ok user_unknown=ignore] ${pkgs.sssd}/lib/security/pam_sss.so"}
-          ${optionalString config.krb5.enable
-              "account sufficient ${pam_krb5}/lib/security/pam_krb5.so"}
-          ${optionalString cfg.googleOsLoginAccountVerification ''
+        (
+          ''
+            # Account management.
+            account required pam_unix.so
+          '' +
+          optionalString use_ldap ''
+            account sufficient ${pam_ldap}/lib/security/pam_ldap.so
+          '' +
+          optionalString (config.services.sssd.enable && cfg.sssdStrictAccess==false) ''
+            account sufficient ${pkgs.sssd}/lib/security/pam_sss.so
+          '' +
+          optionalString (config.services.sssd.enable && cfg.sssdStrictAccess) ''
+            account [default=bad success=ok user_unknown=ignore] ${pkgs.sssd}/lib/security/pam_sss.so
+          '' +
+          optionalString config.krb5.enable ''
+            account sufficient ${pam_krb5}/lib/security/pam_krb5.so
+          '' +
+          optionalString cfg.googleOsLoginAccountVerification ''
             account [success=ok ignore=ignore default=die] ${pkgs.google-compute-engine-oslogin}/lib/pam_oslogin_login.so
             account [success=ok default=ignore] ${pkgs.google-compute-engine-oslogin}/lib/pam_oslogin_admin.so
-          ''}
-
-          # Authentication management.
-          ${optionalString cfg.googleOsLoginAuthentication
-              "auth [success=done perm_denied=bad default=ignore] ${pkgs.google-compute-engine-oslogin}/lib/pam_oslogin_login.so"}
-          ${optionalString cfg.rootOK
-              "auth sufficient pam_rootok.so"}
-          ${optionalString cfg.requireWheel
-              "auth required pam_wheel.so use_uid"}
-          ${optionalString cfg.logFailures
-              "auth required pam_faillock.so"}
-          ${optionalString (config.security.pam.enableSSHAgentAuth && cfg.sshAgentAuth)
-              "auth sufficient ${pkgs.pam_ssh_agent_auth}/libexec/pam_ssh_agent_auth.so file=${lib.concatStringsSep ":" config.services.openssh.authorizedKeysFiles}"}
-          ${let p11 = config.security.pam.p11; in optionalString cfg.p11Auth
-              "auth ${p11.control} ${pkgs.pam_p11}/lib/security/pam_p11.so ${pkgs.opensc}/lib/opensc-pkcs11.so"}
-          ${let u2f = config.security.pam.u2f; in optionalString cfg.u2fAuth
-              "auth ${u2f.control} ${pkgs.pam_u2f}/lib/security/pam_u2f.so ${optionalString u2f.debug "debug"} ${optionalString (u2f.authFile != null) "authfile=${u2f.authFile}"} ${optionalString u2f.interactive "interactive"} ${optionalString u2f.cue "cue"} ${optionalString (u2f.appId != null) "appid=${u2f.appId}"}"}
-          ${optionalString cfg.usbAuth
-              "auth sufficient ${pkgs.pam_usb}/lib/security/pam_usb.so"}
-          ${let oath = config.security.pam.oath; in optionalString cfg.oathAuth
-              "auth requisite ${pkgs.oathToolkit}/lib/security/pam_oath.so window=${toString oath.window} usersfile=${toString oath.usersFile} digits=${toString oath.digits}"}
-          ${let yubi = config.security.pam.yubico; in optionalString cfg.yubicoAuth
-              "auth ${yubi.control} ${pkgs.yubico-pam}/lib/security/pam_yubico.so mode=${toString yubi.mode} ${optionalString (yubi.challengeResponsePath != null) "chalresp_path=${yubi.challengeResponsePath}"} ${optionalString (yubi.mode == "client") "id=${toString yubi.id}"} ${optionalString yubi.debug "debug"}"}
-          ${optionalString cfg.fprintAuth
-              "auth sufficient ${pkgs.fprintd}/lib/security/pam_fprintd.so"}
-        '' +
+          '' +
+          ''
+
+            # Authentication management.
+          '' +
+          optionalString cfg.googleOsLoginAuthentication ''
+            auth [success=done perm_denied=bad default=ignore] ${pkgs.google-compute-engine-oslogin}/lib/pam_oslogin_login.so
+          '' +
+          optionalString cfg.rootOK ''
+            auth sufficient pam_rootok.so
+          '' +
+          optionalString cfg.requireWheel ''
+            auth required pam_wheel.so use_uid
+          '' +
+          optionalString cfg.logFailures ''
+            auth required pam_faillock.so
+          '' +
+          optionalString (config.security.pam.enableSSHAgentAuth && cfg.sshAgentAuth) ''
+            auth sufficient ${pkgs.pam_ssh_agent_auth}/libexec/pam_ssh_agent_auth.so file=${lib.concatStringsSep ":" config.services.openssh.authorizedKeysFiles}
+          '' +
+          (let p11 = config.security.pam.p11; in optionalString cfg.p11Auth ''
+            auth ${p11.control} ${pkgs.pam_p11}/lib/security/pam_p11.so ${pkgs.opensc}/lib/opensc-pkcs11.so
+          '') +
+          (let u2f = config.security.pam.u2f; in optionalString cfg.u2fAuth ''
+            auth ${u2f.control} ${pkgs.pam_u2f}/lib/security/pam_u2f.so ${optionalString u2f.debug "debug"} ${optionalString (u2f.authFile != null) "authfile=${u2f.authFile}"} ${optionalString u2f.interactive "interactive"} ${optionalString u2f.cue "cue"} ${optionalString (u2f.appId != null) "appid=${u2f.appId}"}
+          '') +
+          optionalString cfg.usbAuth ''
+            auth sufficient ${pkgs.pam_usb}/lib/security/pam_usb.so
+          '' +
+          (let oath = config.security.pam.oath; in optionalString cfg.oathAuth ''
+            auth requisite ${pkgs.oathToolkit}/lib/security/pam_oath.so window=${toString oath.window} usersfile=${toString oath.usersFile} digits=${toString oath.digits}
+          '') +
+          (let yubi = config.security.pam.yubico; in optionalString cfg.yubicoAuth ''
+            auth ${yubi.control} ${pkgs.yubico-pam}/lib/security/pam_yubico.so mode=${toString yubi.mode} ${optionalString (yubi.challengeResponsePath != null) "chalresp_path=${yubi.challengeResponsePath}"} ${optionalString (yubi.mode == "client") "id=${toString yubi.id}"} ${optionalString yubi.debug "debug"}
+          '') +
+          optionalString cfg.fprintAuth ''
+            auth sufficient ${pkgs.fprintd}/lib/security/pam_fprintd.so
+          '' +
           # Modules in this block require having the password set in PAM_AUTHTOK.
           # pam_unix is marked as 'sufficient' on NixOS which means nothing will run
           # after it succeeds. Certain modules need to run after pam_unix
@@ -457,115 +475,151 @@ let
           # earlier point and it will run again with 'sufficient' further down.
           # We use try_first_pass the second time to avoid prompting password twice
           (optionalString (cfg.unixAuth &&
-          (config.security.pam.enableEcryptfs
-            || cfg.pamMount
-            || cfg.enableKwallet
-            || cfg.enableGnomeKeyring
-            || cfg.googleAuthenticator.enable
-            || cfg.gnupg.enable
-            || cfg.duoSecurity.enable)) ''
-              auth required pam_unix.so ${optionalString cfg.allowNullPassword "nullok"} ${optionalString cfg.nodelay "nodelay"} likeauth
-              ${optionalString config.security.pam.enableEcryptfs
-                "auth optional ${pkgs.ecryptfs}/lib/security/pam_ecryptfs.so unwrap"}
-              ${optionalString cfg.pamMount
-                "auth optional ${pkgs.pam_mount}/lib/security/pam_mount.so disable_interactive"}
-              ${optionalString cfg.enableKwallet
-                ("auth optional ${pkgs.plasma5Packages.kwallet-pam}/lib/security/pam_kwallet5.so" +
-                 " kwalletd=${pkgs.plasma5Packages.kwallet.bin}/bin/kwalletd5")}
-              ${optionalString cfg.enableGnomeKeyring
-                "auth optional ${pkgs.gnome.gnome-keyring}/lib/security/pam_gnome_keyring.so"}
-              ${optionalString cfg.gnupg.enable
-                "auth optional ${pkgs.pam_gnupg}/lib/security/pam_gnupg.so"
-                + optionalString cfg.gnupg.storeOnly " store-only"
-               }
-              ${optionalString cfg.googleAuthenticator.enable
-                "auth required ${pkgs.googleAuthenticator}/lib/security/pam_google_authenticator.so no_increment_hotp"}
-              ${optionalString cfg.duoSecurity.enable
-                "auth required ${pkgs.duo-unix}/lib/security/pam_duo.so"}
-            '') + ''
-          ${optionalString cfg.unixAuth
-              "auth sufficient pam_unix.so ${optionalString cfg.allowNullPassword "nullok"} ${optionalString cfg.nodelay "nodelay"} likeauth try_first_pass"}
-          ${optionalString cfg.otpwAuth
-              "auth sufficient ${pkgs.otpw}/lib/security/pam_otpw.so"}
-          ${optionalString use_ldap
-              "auth sufficient ${pam_ldap}/lib/security/pam_ldap.so use_first_pass"}
-          ${optionalString config.services.sssd.enable
-              "auth sufficient ${pkgs.sssd}/lib/security/pam_sss.so use_first_pass"}
-          ${optionalString config.krb5.enable ''
+            (config.security.pam.enableEcryptfs
+              || cfg.pamMount
+              || cfg.enableKwallet
+              || cfg.enableGnomeKeyring
+              || cfg.googleAuthenticator.enable
+              || cfg.gnupg.enable
+              || cfg.duoSecurity.enable))
+            (
+              ''
+                auth required pam_unix.so ${optionalString cfg.allowNullPassword "nullok"} ${optionalString cfg.nodelay "nodelay"} likeauth
+              '' +
+              optionalString config.security.pam.enableEcryptfs ''
+                auth optional ${pkgs.ecryptfs}/lib/security/pam_ecryptfs.so unwrap
+              '' +
+              optionalString cfg.pamMount ''
+                auth optional ${pkgs.pam_mount}/lib/security/pam_mount.so disable_interactive
+              '' +
+              optionalString cfg.enableKwallet ''
+               auth optional ${pkgs.plasma5Packages.kwallet-pam}/lib/security/pam_kwallet5.so kwalletd=${pkgs.plasma5Packages.kwallet.bin}/bin/kwalletd5
+              '' +
+              optionalString cfg.enableGnomeKeyring ''
+                auth optional ${pkgs.gnome.gnome-keyring}/lib/security/pam_gnome_keyring.so
+              '' +
+              optionalString cfg.gnupg.enable ''
+                auth optional ${pkgs.pam_gnupg}/lib/security/pam_gnupg.so ${optionalString cfg.gnupg.storeOnly " store-only"}
+              '' +
+              optionalString cfg.googleAuthenticator.enable ''
+                auth required ${pkgs.googleAuthenticator}/lib/security/pam_google_authenticator.so no_increment_hotp
+              '' +
+              optionalString cfg.duoSecurity.enable ''
+                auth required ${pkgs.duo-unix}/lib/security/pam_duo.so
+              ''
+            )) +
+          optionalString cfg.unixAuth ''
+            auth sufficient pam_unix.so ${optionalString cfg.allowNullPassword "nullok"} ${optionalString cfg.nodelay "nodelay"} likeauth try_first_pass
+          '' +
+          optionalString cfg.otpwAuth ''
+            auth sufficient ${pkgs.otpw}/lib/security/pam_otpw.so
+          '' +
+          optionalString use_ldap ''
+            auth sufficient ${pam_ldap}/lib/security/pam_ldap.so use_first_pass
+          '' +
+          optionalString config.services.sssd.enable ''
+            auth sufficient ${pkgs.sssd}/lib/security/pam_sss.so use_first_pass
+          '' +
+          optionalString config.krb5.enable ''
             auth [default=ignore success=1 service_err=reset] ${pam_krb5}/lib/security/pam_krb5.so use_first_pass
             auth [default=die success=done] ${pam_ccreds}/lib/security/pam_ccreds.so action=validate use_first_pass
             auth sufficient ${pam_ccreds}/lib/security/pam_ccreds.so action=store use_first_pass
-          ''}
-          auth required pam_deny.so
-
-          # Password management.
-          password sufficient pam_unix.so nullok sha512
-          ${optionalString config.security.pam.enableEcryptfs
-              "password optional ${pkgs.ecryptfs}/lib/security/pam_ecryptfs.so"}
-          ${optionalString cfg.pamMount
-              "password optional ${pkgs.pam_mount}/lib/security/pam_mount.so"}
-          ${optionalString use_ldap
-              "password sufficient ${pam_ldap}/lib/security/pam_ldap.so"}
-          ${optionalString config.services.sssd.enable
-              "password sufficient ${pkgs.sssd}/lib/security/pam_sss.so use_authtok"}
-          ${optionalString config.krb5.enable
-              "password sufficient ${pam_krb5}/lib/security/pam_krb5.so use_first_pass"}
-          ${optionalString cfg.enableGnomeKeyring
-              "password optional ${pkgs.gnome.gnome-keyring}/lib/security/pam_gnome_keyring.so use_authtok"}
-
-          # Session management.
-          ${optionalString cfg.setEnvironment ''
+          '' +
+          ''
+            auth required pam_deny.so
+
+            # Password management.
+            password sufficient pam_unix.so nullok sha512
+          '' +
+          optionalString config.security.pam.enableEcryptfs ''
+            password optional ${pkgs.ecryptfs}/lib/security/pam_ecryptfs.so
+          '' +
+          optionalString cfg.pamMount ''
+            password optional ${pkgs.pam_mount}/lib/security/pam_mount.so
+          '' +
+          optionalString use_ldap ''
+            password sufficient ${pam_ldap}/lib/security/pam_ldap.so
+          '' +
+          optionalString config.services.sssd.enable ''
+            password sufficient ${pkgs.sssd}/lib/security/pam_sss.so use_authtok
+          '' +
+          optionalString config.krb5.enable ''
+            password sufficient ${pam_krb5}/lib/security/pam_krb5.so use_first_pass
+          '' +
+          optionalString cfg.enableGnomeKeyring ''
+            password optional ${pkgs.gnome.gnome-keyring}/lib/security/pam_gnome_keyring.so use_authtok
+          '' +
+          ''
+
+            # Session management.
+          '' +
+          optionalString cfg.setEnvironment ''
             session required pam_env.so conffile=/etc/pam/environment readenv=0
-          ''}
-          session required pam_unix.so
-          ${optionalString cfg.setLoginUid
-              "session ${
-                if config.boot.isContainer then "optional" else "required"
-              } pam_loginuid.so"}
-          ${optionalString cfg.ttyAudit.enable
-              "session required ${pkgs.pam}/lib/security/pam_tty_audit.so
+          '' +
+          ''
+            session required pam_unix.so
+          '' +
+          optionalString cfg.setLoginUid ''
+            session ${if config.boot.isContainer then "optional" else "required"} pam_loginuid.so
+          '' +
+          optionalString cfg.ttyAudit.enable ''
+            session required ${pkgs.pam}/lib/security/pam_tty_audit.so
                 open_only=${toString cfg.ttyAudit.openOnly}
                 ${optionalString (cfg.ttyAudit.enablePattern != null) "enable=${cfg.ttyAudit.enablePattern}"}
                 ${optionalString (cfg.ttyAudit.disablePattern != null) "disable=${cfg.ttyAudit.disablePattern}"}
-              "}
-          ${optionalString cfg.makeHomeDir
-              "session required ${pkgs.pam}/lib/security/pam_mkhomedir.so silent skel=${config.security.pam.makeHomeDir.skelDirectory} umask=0077"}
-          ${optionalString cfg.updateWtmp
-              "session required ${pkgs.pam}/lib/security/pam_lastlog.so silent"}
-          ${optionalString config.security.pam.enableEcryptfs
-              "session optional ${pkgs.ecryptfs}/lib/security/pam_ecryptfs.so"}
-          ${optionalString cfg.pamMount
-              "session optional ${pkgs.pam_mount}/lib/security/pam_mount.so disable_interactive"}
-          ${optionalString use_ldap
-              "session optional ${pam_ldap}/lib/security/pam_ldap.so"}
-          ${optionalString config.services.sssd.enable
-              "session optional ${pkgs.sssd}/lib/security/pam_sss.so"}
-          ${optionalString config.krb5.enable
-              "session optional ${pam_krb5}/lib/security/pam_krb5.so"}
-          ${optionalString cfg.otpwAuth
-              "session optional ${pkgs.otpw}/lib/security/pam_otpw.so"}
-          ${optionalString cfg.startSession
-              "session optional ${pkgs.systemd}/lib/security/pam_systemd.so"}
-          ${optionalString cfg.forwardXAuth
-              "session optional pam_xauth.so xauthpath=${pkgs.xorg.xauth}/bin/xauth systemuser=99"}
-          ${optionalString (cfg.limits != [])
-              "session required ${pkgs.pam}/lib/security/pam_limits.so conf=${makeLimitsConf cfg.limits}"}
-          ${optionalString (cfg.showMotd && config.users.motd != null)
-              "session optional ${pkgs.pam}/lib/security/pam_motd.so motd=${motd}"}
-          ${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.plasma5Packages.kwallet-pam}/lib/security/pam_kwallet5.so" +
-               " kwalletd=${pkgs.plasma5Packages.kwallet.bin}/bin/kwalletd5")}
-          ${optionalString (cfg.enableGnomeKeyring)
-              "session optional ${pkgs.gnome.gnome-keyring}/lib/security/pam_gnome_keyring.so auto_start"}
-          ${optionalString cfg.gnupg.enable
-              "session optional ${pkgs.pam_gnupg}/lib/security/pam_gnupg.so"
-              + optionalString cfg.gnupg.noAutostart " no-autostart"
-           }
-          ${optionalString (config.virtualisation.lxc.lxcfs.enable)
-               "session optional ${pkgs.lxc}/lib/security/pam_cgfs.so -c all"}
-        '');
+          '' +
+          optionalString cfg.makeHomeDir ''
+            session required ${pkgs.pam}/lib/security/pam_mkhomedir.so silent skel=${config.security.pam.makeHomeDir.skelDirectory} umask=0077
+          '' +
+          optionalString cfg.updateWtmp ''
+            session required ${pkgs.pam}/lib/security/pam_lastlog.so silent
+          '' +
+          optionalString config.security.pam.enableEcryptfs ''
+            session optional ${pkgs.ecryptfs}/lib/security/pam_ecryptfs.so
+          '' +
+          optionalString cfg.pamMount ''
+            session optional ${pkgs.pam_mount}/lib/security/pam_mount.so disable_interactive
+          '' +
+          optionalString use_ldap ''
+            session optional ${pam_ldap}/lib/security/pam_ldap.so
+          '' +
+          optionalString config.services.sssd.enable ''
+            session optional ${pkgs.sssd}/lib/security/pam_sss.so
+          '' +
+          optionalString config.krb5.enable ''
+            session optional ${pam_krb5}/lib/security/pam_krb5.so
+          '' +
+          optionalString cfg.otpwAuth ''
+            session optional ${pkgs.otpw}/lib/security/pam_otpw.so
+          '' +
+          optionalString cfg.startSession ''
+            session optional ${pkgs.systemd}/lib/security/pam_systemd.so
+          '' +
+          optionalString cfg.forwardXAuth ''
+            session optional pam_xauth.so xauthpath=${pkgs.xorg.xauth}/bin/xauth systemuser=99
+          '' +
+          optionalString (cfg.limits != []) ''
+            session required ${pkgs.pam}/lib/security/pam_limits.so conf=${makeLimitsConf cfg.limits}
+          '' +
+          optionalString (cfg.showMotd && config.users.motd != null) ''
+            session optional ${pkgs.pam}/lib/security/pam_motd.so motd=${motd}
+          '' +
+          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.plasma5Packages.kwallet-pam}/lib/security/pam_kwallet5.so kwalletd=${pkgs.plasma5Packages.kwallet.bin}/bin/kwalletd5
+          '' +
+          optionalString (cfg.enableGnomeKeyring) ''
+            session optional ${pkgs.gnome.gnome-keyring}/lib/security/pam_gnome_keyring.so auto_start
+          '' +
+          optionalString cfg.gnupg.enable ''
+            session optional ${pkgs.pam_gnupg}/lib/security/pam_gnupg.so ${optionalString cfg.gnupg.noAutostart " no-autostart"}
+          '' +
+          optionalString (config.virtualisation.lxc.lxcfs.enable) ''
+            session optional ${pkgs.lxc}/lib/security/pam_cgfs.so -c all
+          ''
+        );
     };
 
   };
diff --git a/nixos/modules/services/databases/hbase.nix b/nixos/modules/services/databases/hbase.nix
index ff01a1bcd98b9..183c8a2f46d53 100644
--- a/nixos/modules/services/databases/hbase.nix
+++ b/nixos/modules/services/databases/hbase.nix
@@ -5,18 +5,24 @@ with lib;
 let
   cfg = config.services.hbase;
 
-  configFile = pkgs.writeText "hbase-site.xml" ''
-    <configuration>
-      <property>
-        <name>hbase.rootdir</name>
-        <value>file://${cfg.dataDir}/hbase</value>
-      </property>
-      <property>
-        <name>hbase.zookeeper.property.dataDir</name>
-        <value>${cfg.dataDir}/zookeeper</value>
-      </property>
-    </configuration>
-  '';
+  defaultConfig = {
+    "hbase.rootdir" = "file://${cfg.dataDir}/hbase";
+    "hbase.zookeeper.property.dataDir" = "${cfg.dataDir}/zookeeper";
+  };
+
+  buildProperty = configAttr:
+    (builtins.concatStringsSep "\n"
+      (lib.mapAttrsToList
+        (name: value: ''
+          <property>
+            <name>${name}</name>
+            <value>${builtins.toString value}</value>
+          </property>
+        '')
+        configAttr));
+
+  configFile = pkgs.writeText "hbase-site.xml"
+    (buildProperty (defaultConfig // cfg.settings));
 
   configDir = pkgs.runCommand "hbase-config-dir" { preferLocalBuild = true; } ''
     mkdir -p $out
@@ -85,6 +91,14 @@ in {
         '';
       };
 
+      settings = mkOption {
+        type = with lib.types; attrsOf (oneOf [ str int bool ]);
+        default = defaultConfig;
+        description = ''
+          configurations in hbase-site.xml, see <link xlink:href="https://github.com/apache/hbase/blob/master/hbase-server/src/test/resources/hbase-site.xml"/> for details.
+        '';
+      };
+
     };
 
   };
diff --git a/nixos/modules/services/logging/logstash.nix b/nixos/modules/services/logging/logstash.nix
index 044d5330231ec..a08203dffe789 100644
--- a/nixos/modules/services/logging/logstash.nix
+++ b/nixos/modules/services/logging/logstash.nix
@@ -23,12 +23,16 @@ let
 
   logstashSettingsYml = pkgs.writeText "logstash.yml" cfg.extraSettings;
 
+  logstashJvmOptionsFile = pkgs.writeText "jvm.options" cfg.extraJvmOptions;
+
   logstashSettingsDir = pkgs.runCommand "logstash-settings" {
+      inherit logstashJvmOptionsFile;
       inherit logstashSettingsYml;
       preferLocalBuild = true;
     } ''
     mkdir -p $out
     ln -s $logstashSettingsYml $out/logstash.yml
+    ln -s $logstashJvmOptionsFile $out/jvm.options
   '';
 in
 
@@ -152,6 +156,15 @@ in
         '';
       };
 
+      extraJvmOptions = mkOption {
+        type = types.lines;
+        default = "";
+        description = "Extra JVM options, one per line (jvm.options format).";
+        example = ''
+          -Xms2g
+          -Xmx2g
+        '';
+      };
 
     };
   };
diff --git a/nixos/modules/services/matrix/mjolnir.nix b/nixos/modules/services/matrix/mjolnir.nix
index 8a54f93d98d8f..278924b05cf28 100644
--- a/nixos/modules/services/matrix/mjolnir.nix
+++ b/nixos/modules/services/matrix/mjolnir.nix
@@ -14,6 +14,8 @@ let
       else
         cfg.homeserverUrl;
 
+    rawHomeserverUrl = cfg.homeserverUrl;
+
     pantalaimon = {
       inherit (cfg.pantalaimon) username;
 
diff --git a/nixos/modules/services/misc/plex.nix b/nixos/modules/services/misc/plex.nix
index 7c97069aaf750..2ae4e80d5c3fd 100644
--- a/nixos/modules/services/misc/plex.nix
+++ b/nixos/modules/services/misc/plex.nix
@@ -76,7 +76,7 @@ in
           in Plex's scanners directory will be cleared and this module will
           symlink all of the paths specified here to that directory.
         '';
-        example = literalExample ''
+        example = literalExpression ''
           [
             (fetchFromGitHub {
               owner = "ZeroQI";
diff --git a/nixos/modules/services/misc/xmrig.nix b/nixos/modules/services/misc/xmrig.nix
index 15c7d2a7b14ca..cf01bb119e894 100644
--- a/nixos/modules/services/misc/xmrig.nix
+++ b/nixos/modules/services/misc/xmrig.nix
@@ -51,6 +51,8 @@ with lib;
   };
 
   config = mkIf cfg.enable {
+    boot.kernelModules = [ "msr" ];
+
     systemd.services.xmrig = {
       wantedBy = [ "multi-user.target" ];
       after = [ "network.target" ];
@@ -58,14 +60,16 @@ with lib;
       serviceConfig = {
         ExecStartPre = "${cfg.package}/bin/xmrig --config=${configFile} --dry-run";
         ExecStart = "${cfg.package}/bin/xmrig --config=${configFile}";
-        DynamicUser = true;
+        # https://xmrig.com/docs/miner/randomx-optimization-guide/msr
+        # If you use recent XMRig with root privileges (Linux) or admin
+        # privileges (Windows) the miner configure all MSR registers
+        # automatically.
+        DynamicUser = lib.mkDefault false;
       };
     };
   };
 
   meta = with lib; {
-    description = "XMRig Mining Software Service";
-    license = licenses.gpl3Only;
     maintainers = with maintainers; [ ratsclub ];
   };
 }
diff --git a/nixos/modules/services/monitoring/cadvisor.nix b/nixos/modules/services/monitoring/cadvisor.nix
index da051dbe4655b..dfbf07efcaea9 100644
--- a/nixos/modules/services/monitoring/cadvisor.nix
+++ b/nixos/modules/services/monitoring/cadvisor.nix
@@ -111,6 +111,8 @@ in {
         wantedBy = [ "multi-user.target" ];
         after = [ "network.target" "docker.service" "influxdb.service" ];
 
+        path = optionals config.boot.zfs.enabled [ pkgs.zfs ];
+
         postStart = mkBefore ''
           until ${pkgs.curl.bin}/bin/curl -s -o /dev/null 'http://${cfg.listenAddress}:${toString cfg.port}/containers/'; do
             sleep 1;
diff --git a/nixos/modules/services/monitoring/prometheus/exporters/nginx.nix b/nixos/modules/services/monitoring/prometheus/exporters/nginx.nix
index 5ee8c346be1dc..3cdd7866bd4db 100644
--- a/nixos/modules/services/monitoring/prometheus/exporters/nginx.nix
+++ b/nixos/modules/services/monitoring/prometheus/exporters/nginx.nix
@@ -47,7 +47,7 @@ in
       ExecStart = ''
         ${pkgs.prometheus-nginx-exporter}/bin/nginx-prometheus-exporter \
           --nginx.scrape-uri '${cfg.scrapeUri}' \
-          --nginx.ssl-verify ${toString cfg.sslVerify} \
+          --nginx.ssl-verify ${boolToString cfg.sslVerify} \
           --web.listen-address ${cfg.listenAddress}:${toString cfg.port} \
           --web.telemetry-path ${cfg.telemetryPath} \
           --prometheus.const-labels ${concatStringsSep "," cfg.constLabels} \
diff --git a/nixos/modules/services/monitoring/zabbix-server.nix b/nixos/modules/services/monitoring/zabbix-server.nix
index 9b0fd9dbff13e..0141c073da25d 100644
--- a/nixos/modules/services/monitoring/zabbix-server.nix
+++ b/nixos/modules/services/monitoring/zabbix-server.nix
@@ -250,7 +250,12 @@ in
     };
 
     security.wrappers = {
-      fping.source = "${pkgs.fping}/bin/fping";
+      fping =
+        { setuid = true;
+          owner = "root";
+          group = "root";
+          source = "${pkgs.fping}/bin/fping";
+        };
     };
 
     systemd.services.zabbix-server = {
diff --git a/nixos/modules/services/network-filesystems/webdav.nix b/nixos/modules/services/network-filesystems/webdav.nix
new file mode 100644
index 0000000000000..4086a0f5d5620
--- /dev/null
+++ b/nixos/modules/services/network-filesystems/webdav.nix
@@ -0,0 +1,107 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+let
+  cfg = config.services.webdav;
+  format = pkgs.formats.yaml { };
+in
+{
+  options = {
+    services.webdav = {
+      enable = mkEnableOption "WebDAV server";
+
+      user = mkOption {
+        type = types.str;
+        default = "webdav";
+        description = "User account under which WebDAV runs.";
+      };
+
+      group = mkOption {
+        type = types.str;
+        default = "webdav";
+        description = "Group under which WebDAV runs.";
+      };
+
+      settings = mkOption {
+        type = format.type;
+        default = { };
+        description = ''
+          Attrset that is converted and passed as config file. Available options
+          can be found at
+          <link xlink:href="https://github.com/hacdias/webdav">here</link>.
+
+          This program supports reading username and password configuration
+          from environment variables, so it's strongly recommended to store
+          username and password in a separate
+          <link xlink:href="https://www.freedesktop.org/software/systemd/man/systemd.exec.html#EnvironmentFile=">EnvironmentFile</link>.
+          This prevents adding secrets to the world-readable Nix store.
+        '';
+        example = literalExpression ''
+          {
+              address = "0.0.0.0";
+              port = 8080;
+              scope = "/srv/public";
+              modify = true;
+              auth = true;
+              users = [
+                {
+                  username = "{env}ENV_USERNAME";
+                  password = "{env}ENV_PASSWORD";
+                }
+              ];
+          }
+        '';
+      };
+
+      configFile = mkOption {
+        type = types.path;
+        default = format.generate "webdav.yaml" cfg.settings;
+        defaultText = "Config file generated from services.webdav.settings";
+        description = ''
+          Path to config file. If this option is set, it will override any
+          configuration done in options.services.webdav.settings.
+        '';
+        example = "/etc/webdav/config.yaml";
+      };
+
+      environmentFile = mkOption {
+        type = types.nullOr types.path;
+        default = null;
+        description = ''
+          Environment file as defined in <citerefentry>
+          <refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum>
+          </citerefentry>.
+        '';
+      };
+    };
+  };
+
+  config = mkIf cfg.enable {
+    users.users = mkIf (cfg.user == "webdav") {
+      webdav = {
+        description = "WebDAV daemon user";
+        isSystemUser = true;
+        group = cfg.group;
+      };
+    };
+
+    users.groups = mkIf (cfg.group == "webdav") {
+      webdav = { };
+    };
+
+    systemd.services.webdav = {
+      description = "WebDAV server";
+      after = [ "network.target" ];
+      wantedBy = [ "multi-user.target" ];
+      serviceConfig = {
+        ExecStart = "${pkgs.webdav}/bin/webdav -c ${cfg.configFile}";
+        Restart = "on-failure";
+        User = cfg.user;
+        Group = cfg.group;
+        EnvironmentFile = mkIf (cfg.environmentFile != null) [ cfg.environmentFile ];
+      };
+    };
+  };
+
+  meta.maintainers = with maintainers; [ pengmeiyu ];
+}
diff --git a/nixos/modules/services/ttys/getty.nix b/nixos/modules/services/ttys/getty.nix
index 8c5b6e5e0cbc1..7021a2c80f857 100644
--- a/nixos/modules/services/ttys/getty.nix
+++ b/nixos/modules/services/ttys/getty.nix
@@ -24,6 +24,7 @@ in
 
   imports = [
     (mkRenamedOptionModule [ "services" "mingetty" ] [ "services" "getty" ])
+    (mkRemovedOptionModule [ "services" "getty" "serialSpeed" ] ''set non-standard baudrates with `boot.kernelParams` i.e. boot.kernelParams = ["console=ttyS2,1500000"];'')
   ];
 
   options = {
@@ -92,17 +93,6 @@ in
         '';
       };
 
-      serialSpeed = mkOption {
-        type = types.listOf types.int;
-        default = [ 115200 57600 38400 9600 ];
-        example = [ 38400 9600 ];
-        description = ''
-            Bitrates to allow for agetty's listening on serial ports. Listing more
-            bitrates gives more interoperability but at the cost of long delays
-            for getting a sync on the line.
-        '';
-      };
-
     };
 
   };
@@ -124,10 +114,9 @@ in
       };
 
     systemd.services."serial-getty@" =
-      let speeds = concatStringsSep "," (map toString config.services.getty.serialSpeed); in
       { serviceConfig.ExecStart = [
           "" # override upstream default with an empty ExecStart
-          (gettyCmd "%I --keep-baud ${speeds} $TERM")
+          (gettyCmd "%I --keep-baud $TERM")
         ];
         restartIfChanged = false;
       };
diff --git a/nixos/modules/services/web-servers/nginx/default.nix b/nixos/modules/services/web-servers/nginx/default.nix
index be589e42ddd6a..5717b86b3bea6 100644
--- a/nixos/modules/services/web-servers/nginx/default.nix
+++ b/nixos/modules/services/web-servers/nginx/default.nix
@@ -896,7 +896,7 @@ in
         PrivateMounts = true;
         # System Call Filtering
         SystemCallArchitectures = "native";
-        SystemCallFilter = "~@cpu-emulation @debug @keyring @ipc @mount @obsolete @privileged @setuid";
+        SystemCallFilter = "~@cpu-emulation @debug @keyring @ipc @mount @obsolete @privileged @setuid @mincore";
       };
     };
 
diff --git a/nixos/modules/services/x11/display-managers/startx.nix b/nixos/modules/services/x11/display-managers/startx.nix
index 6cd46cdf96498..a48566ae06841 100644
--- a/nixos/modules/services/x11/display-managers/startx.nix
+++ b/nixos/modules/services/x11/display-managers/startx.nix
@@ -35,10 +35,7 @@ in
   config = mkIf cfg.enable {
     services.xserver = {
       exportConfiguration = true;
-      displayManager.job.execCmd = "";
-      displayManager.lightdm.enable = lib.mkForce false;
     };
-    systemd.services.display-manager.enable = false;
 
     # Other displayManagers log to /dev/null because they're services and put
     # Xorg's stdout in the journal
diff --git a/nixos/modules/services/x11/display-managers/sx.nix b/nixos/modules/services/x11/display-managers/sx.nix
index 73d27390a5803..e309773643009 100644
--- a/nixos/modules/services/x11/display-managers/sx.nix
+++ b/nixos/modules/services/x11/display-managers/sx.nix
@@ -26,13 +26,8 @@ in {
     environment.systemPackages = [ pkgs.sx ];
     services.xserver = {
       exportConfiguration = true;
-      displayManager = {
-        job.execCmd = "";
-        lightdm.enable = mkForce false;
-      };
       logFile = mkDefault null;
     };
-    systemd.services.display-manager.enable = false;
   };
 
   meta.maintainers = with maintainers; [ figsoda ];
diff --git a/nixos/modules/services/x11/hardware/libinput.nix b/nixos/modules/services/x11/hardware/libinput.nix
index e2fb7d0918e36..efdb7c61dfaeb 100644
--- a/nixos/modules/services/x11/hardware/libinput.nix
+++ b/nixos/modules/services/x11/hardware/libinput.nix
@@ -13,7 +13,7 @@ let cfg = config.services.xserver.libinput;
         example = "/dev/input/event0";
         description =
           ''
-            Path for ${deviceType} device.  Set to null to apply to any
+            Path for ${deviceType} device.  Set to <literal>null</literal> to apply to any
             auto-detected ${deviceType}.
           '';
       };
@@ -24,8 +24,8 @@ let cfg = config.services.xserver.libinput;
         example = "flat";
         description =
           ''
-            Sets  the pointer acceleration profile to the given profile.
-            Permitted values are adaptive, flat.
+            Sets the pointer acceleration profile to the given profile.
+            Permitted values are <literal>adaptive</literal>, <literal>flat</literal>.
             Not all devices support this option or all profiles.
             If a profile is unsupported, the default profile for this is used.
             <literal>flat</literal>: Pointer motion is accelerated by a constant
@@ -38,12 +38,14 @@ let cfg = config.services.xserver.libinput;
       accelSpeed = mkOption {
         type = types.nullOr types.str;
         default = null;
+        example = "-0.5";
         description = "Cursor acceleration (how fast speed increases from minSpeed to maxSpeed).";
       };
 
       buttonMapping = mkOption {
         type = types.nullOr types.str;
         default = null;
+        example = "1 6 3 4 5 0 7";
         description =
           ''
             Sets the logical button mapping for this device, see XSetPointerMapping(3). The string  must
@@ -58,9 +60,10 @@ let cfg = config.services.xserver.libinput;
       calibrationMatrix = mkOption {
         type = types.nullOr types.str;
         default = null;
+        example = "0.5 0 0 0 0.8 0.1 0 0 1";
         description =
           ''
-            A  string  of  9 space-separated floating point numbers.  Sets the calibration matrix to the
+            A string of 9 space-separated floating point numbers. Sets the calibration matrix to the
             3x3 matrix where the first row is (abc), the second row is (def) and the third row is (ghi).
           '';
       };
@@ -68,6 +71,7 @@ let cfg = config.services.xserver.libinput;
       clickMethod = mkOption {
         type = types.nullOr (types.enum [ "none" "buttonareas" "clickfinger" ]);
         default = null;
+        example = "buttonareas";
         description =
           ''
             Enables a click method. Permitted values are <literal>none</literal>,
@@ -166,8 +170,9 @@ let cfg = config.services.xserver.libinput;
       transformationMatrix = mkOption {
         type = types.nullOr types.str;
         default = null;
+        example = "0.5 0 0 0 0.8 0.1 0 0 1";
         description = ''
-          A  string  of  9 space-separated floating point numbers.  Sets the transformation matrix to
+          A string of 9 space-separated floating point numbers. Sets the transformation matrix to
           the 3x3 matrix where the first row is (abc), the second row is (def) and the third row is (ghi).
         '';
       };
diff --git a/nixos/modules/services/x11/xserver.nix b/nixos/modules/services/x11/xserver.nix
index cb620f10b13fc..24d9257344235 100644
--- a/nixos/modules/services/x11/xserver.nix
+++ b/nixos/modules/services/x11/xserver.nix
@@ -588,11 +588,22 @@ in
   config = mkIf cfg.enable {
 
     services.xserver.displayManager.lightdm.enable =
-      let dmconf = cfg.displayManager;
-          default = !(dmconf.gdm.enable
-                    || dmconf.sddm.enable
-                    || dmconf.xpra.enable );
-      in mkIf (default) true;
+      let dmConf = cfg.displayManager;
+          default = !(dmConf.gdm.enable
+                    || dmConf.sddm.enable
+                    || dmConf.xpra.enable
+                    || dmConf.sx.enable
+                    || dmConf.startx.enable);
+      in mkIf (default) (mkDefault true);
+
+    # so that the service won't be enabled when only startx is used
+    systemd.services.display-manager.enable  =
+      let dmConf = cfg.displayManager;
+          noDmUsed = !(dmConf.gdm.enable
+                    || dmConf.sddm.enable
+                    || dmConf.xpra.enable
+                    || dmConf.lightdm.enable);
+      in mkIf (noDmUsed) (mkDefault false);
 
     hardware.opengl.enable = mkDefault true;
 
@@ -702,7 +713,8 @@ in
             rm -f /tmp/.X0-lock
           '';
 
-        script = "${cfg.displayManager.job.execCmd}";
+        # TODO: move declaring the systemd service to its own mkIf
+        script = mkIf (config.systemd.services.display-manager.enable == true) "${cfg.displayManager.job.execCmd}";
 
         # Stop restarting if the display manager stops (crashes) 2 times
         # in one minute. Starting X typically takes 3-4s.
diff --git a/nixos/modules/system/boot/networkd.nix b/nixos/modules/system/boot/networkd.nix
index 662dfe2db9895..2e17bdf6bb659 100644
--- a/nixos/modules/system/boot/networkd.nix
+++ b/nixos/modules/system/boot/networkd.nix
@@ -131,6 +131,7 @@ let
           "fou"
           "xfrm"
           "ifb"
+          "batadv"
         ])
         (assertByteFormat "MTUBytes")
         (assertMacAddress "MACAddress")
@@ -381,6 +382,29 @@ let
         (assertInt "Table")
         (assertMinimum "Table" 0)
       ];
+
+      sectionBatmanAdvanced = checkUnitConfig "BatmanAdvanced" [
+        (assertOnlyFields [
+          "GatewayMode"
+          "Aggregation"
+          "BridgeLoopAvoidance"
+          "DistributedArpTable"
+          "Fragmentation"
+          "HopPenalty"
+          "OriginatorIntervalSec"
+          "GatewayBandwithDown"
+          "GatewayBandwithUp"
+          "RoutingAlgorithm"
+        ])
+        (assertValueOneOf "GatewayMode" ["off" "client" "server"])
+        (assertValueOneOf "Aggregation" boolValues)
+        (assertValueOneOf "BridgeLoopAvoidance" boolValues)
+        (assertValueOneOf "DistributedArpTable" boolValues)
+        (assertValueOneOf "Fragmentation" boolValues)
+        (assertInt "HopPenalty")
+        (assertRange "HopPenalty" 0 255)
+        (assertValueOneOf "RoutingAlgorithm" ["batman-v" "batman-iv"])
+      ];
     };
 
     network = {
@@ -473,6 +497,7 @@ let
           "IgnoreCarrierLoss"
           "Xfrm"
           "KeepConfiguration"
+          "BatmanAdvanced"
         ])
         # Note: For DHCP the values both, none, v4, v6 are deprecated
         (assertValueOneOf "DHCP" ["yes" "no" "ipv4" "ipv6"])
@@ -1056,6 +1081,21 @@ let
       '';
     };
 
+    batmanAdvancedConfig = mkOption {
+      default = {};
+      example = {
+        GatewayMode = "server";
+        RoutingAlgorithm = "batman-v";
+      };
+      type = types.addCheck (types.attrsOf unitOption) check.netdev.sectionBatmanAdvanced;
+      description = ''
+        Each attribute in this set specifies an option in the
+        <literal>[BatmanAdvanced]</literal> section of the unit. See
+        <citerefentry><refentrytitle>systemd.netdev</refentrytitle>
+        <manvolnum>5</manvolnum></citerefentry> for details.
+      '';
+    };
+
   };
 
   addressOptions = {
@@ -1507,6 +1547,10 @@ let
           [VRF]
           ${attrsToSection def.vrfConfig}
         ''
+        + optionalString (def.batmanAdvancedConfig != { }) ''
+          [BatmanAdvanced]
+          ${attrsToSection def.batmanAdvancedConfig}
+        ''
         + def.extraConfig;
     };
 
diff --git a/nixos/modules/tasks/auto-upgrade.nix b/nixos/modules/tasks/auto-upgrade.nix
index b19b688a1fb8a..b931b27ad8170 100644
--- a/nixos/modules/tasks/auto-upgrade.nix
+++ b/nixos/modules/tasks/auto-upgrade.nix
@@ -139,6 +139,7 @@ in {
         gzip
         gitMinimal
         config.nix.package.out
+        config.programs.ssh.package
       ];
 
       script = let
diff --git a/nixos/modules/virtualisation/qemu-vm.nix b/nixos/modules/virtualisation/qemu-vm.nix
index 1d8973385b54b..0c2782d3e0274 100644
--- a/nixos/modules/virtualisation/qemu-vm.nix
+++ b/nixos/modules/virtualisation/qemu-vm.nix
@@ -306,7 +306,7 @@ in
     virtualisation.msize =
       mkOption {
         type = types.ints.positive;
-        default = 16384;
+        default = pkgs.vmTools.default9PMsizeBytes;
         description =
           ''
             The msize (maximum packet size) option passed to 9p file systems, in
diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix
index 985dbd3b6767b..cd13183ed0a32 100644
--- a/nixos/tests/all-tests.nix
+++ b/nixos/tests/all-tests.nix
@@ -228,9 +228,11 @@ in
   kubernetes = handleTestOn ["x86_64-linux"] ./kubernetes {};
   latestKernel.login = handleTest ./login.nix { latestKernel = true; };
   leaps = handleTest ./leaps.nix {};
+  libinput = handleTest ./libinput.nix {};
   libreddit = handleTest ./libreddit.nix {};
-  lidarr = handleTest ./lidarr.nix {};
+  libresprite = handleTest ./libresprite.nix {};
   libreswan = handleTest ./libreswan.nix {};
+  lidarr = handleTest ./lidarr.nix {};
   lightdm = handleTest ./lightdm.nix {};
   limesurvey = handleTest ./limesurvey.nix {};
   litestream = handleTest ./litestream.nix {};
diff --git a/nixos/tests/libinput.nix b/nixos/tests/libinput.nix
new file mode 100644
index 0000000000000..2f84aaadcd0be
--- /dev/null
+++ b/nixos/tests/libinput.nix
@@ -0,0 +1,38 @@
+import ./make-test-python.nix ({ ... }:
+
+{
+  name = "libinput";
+
+  machine = { ... }:
+    {
+      imports = [
+        ./common/x11.nix
+        ./common/user-account.nix
+      ];
+
+      test-support.displayManager.auto.user = "alice";
+
+      services.xserver.libinput = {
+        enable = true;
+        mouse = {
+          naturalScrolling = true;
+          leftHanded = true;
+          middleEmulation = false;
+          horizontalScrolling = false;
+        };
+      };
+    };
+
+  testScript = ''
+    def expect_xserver_option(option, value):
+        machine.succeed(f"""cat /var/log/X.0.log | grep -F 'Option "{option}" "{value}"'""")
+
+    machine.start()
+    machine.wait_for_x()
+    machine.succeed("""cat /var/log/X.0.log | grep -F "Using input driver 'libinput'" """)
+    expect_xserver_option("NaturalScrolling", "on")
+    expect_xserver_option("LeftHanded", "on")
+    expect_xserver_option("MiddleEmulation", "off")
+    expect_xserver_option("HorizontalScrolling", "off")
+  '';
+})
diff --git a/nixos/tests/libresprite.nix b/nixos/tests/libresprite.nix
new file mode 100644
index 0000000000000..1a6210e3671ae
--- /dev/null
+++ b/nixos/tests/libresprite.nix
@@ -0,0 +1,30 @@
+import ./make-test-python.nix ({ pkgs, ... }: {
+  name = "libresprite";
+  meta = with pkgs.lib.maintainers; {
+    maintainers = [ fgaz ];
+  };
+
+  machine = { config, pkgs, ... }: {
+    imports = [
+      ./common/x11.nix
+    ];
+
+    services.xserver.enable = true;
+    environment.systemPackages = [
+      pkgs.imagemagick
+      pkgs.libresprite
+    ];
+  };
+
+  enableOCR = true;
+
+  testScript =
+    ''
+      machine.wait_for_x()
+      machine.succeed("convert -font DejaVu-Sans +antialias label:'IT WORKS' image.png")
+      machine.execute("libresprite image.png >&2 &")
+      machine.wait_for_window("LibreSprite v${pkgs.libresprite.version}")
+      machine.wait_for_text("IT WORKS")
+      machine.screenshot("screen")
+    '';
+})