about summary refs log tree commit diff
path: root/nixos
diff options
context:
space:
mode:
Diffstat (limited to 'nixos')
-rw-r--r--nixos/doc/manual/development/option-declarations.section.md2
-rw-r--r--nixos/doc/manual/development/settings-options.section.md21
-rw-r--r--nixos/doc/manual/installation/installing-from-other-distro.section.md4
-rw-r--r--nixos/doc/manual/installation/installing-virtualbox-guest.section.md4
-rw-r--r--nixos/doc/manual/installation/upgrading.chapter.md4
-rw-r--r--nixos/doc/manual/release-notes/release-notes.md1
-rw-r--r--nixos/doc/manual/release-notes/rl-2111.section.md2
-rw-r--r--nixos/doc/manual/release-notes/rl-2405.section.md861
-rw-r--r--nixos/doc/manual/release-notes/rl-2411.section.md23
-rw-r--r--nixos/lib/test-driver/default.nix3
-rw-r--r--nixos/lib/test-driver/pyproject.toml8
-rwxr-xr-xnixos/lib/test-driver/test_driver/__init__.py30
-rw-r--r--nixos/lib/test-driver/test_driver/driver.py44
-rw-r--r--nixos/lib/test-driver/test_driver/logger.py249
-rw-r--r--nixos/lib/test-driver/test_driver/machine.py16
-rw-r--r--nixos/lib/test-driver/test_driver/polling_condition.py11
-rw-r--r--nixos/lib/test-driver/test_driver/vlan.py15
-rw-r--r--nixos/lib/test-script-prepend.py4
-rw-r--r--nixos/lib/testing/driver.nix2
-rw-r--r--nixos/modules/config/nsswitch.nix26
-rw-r--r--nixos/modules/hardware/video/nvidia.nix871
-rw-r--r--nixos/modules/misc/version.nix2
-rw-r--r--nixos/modules/module-list.nix16
-rw-r--r--nixos/modules/programs/_1password-gui.nix16
-rw-r--r--nixos/modules/programs/_1password.nix10
-rw-r--r--nixos/modules/programs/adb.nix10
-rw-r--r--nixos/modules/programs/alvr.nix16
-rw-r--r--nixos/modules/programs/appgate-sdp.nix6
-rw-r--r--nixos/modules/programs/atop.nix50
-rw-r--r--nixos/modules/programs/ausweisapp.nix8
-rw-r--r--nixos/modules/programs/autojump.nix12
-rw-r--r--nixos/modules/programs/bandwhich.nix10
-rw-r--r--nixos/modules/programs/bash-my-aws.nix6
-rw-r--r--nixos/modules/programs/bash/bash-completion.nix6
-rw-r--r--nixos/modules/programs/bash/bash.nix48
-rw-r--r--nixos/modules/programs/bash/blesh.nix9
-rw-r--r--nixos/modules/programs/bash/ls-colors.nix6
-rw-r--r--nixos/modules/programs/bash/undistract-me.nix16
-rw-r--r--nixos/modules/programs/benchexec.nix98
-rw-r--r--nixos/modules/programs/browserpass.nix6
-rw-r--r--nixos/modules/programs/calls.nix6
-rw-r--r--nixos/modules/programs/cdemu.nix24
-rw-r--r--nixos/modules/programs/cfs-zen-tweaks.nix8
-rw-r--r--nixos/modules/programs/chromium.nix44
-rw-r--r--nixos/modules/programs/cnping.nix6
-rw-r--r--nixos/modules/programs/command-not-found/command-not-found.nix12
-rw-r--r--nixos/modules/programs/cpu-energy-meter.nix27
-rw-r--r--nixos/modules/programs/criu.nix8
-rw-r--r--nixos/modules/programs/digitalbitbox/default.nix10
-rw-r--r--nixos/modules/programs/dmrconfig.nix12
-rw-r--r--nixos/modules/programs/droidcam.nix4
-rw-r--r--nixos/modules/programs/dublin-traceroute.nix10
-rw-r--r--nixos/modules/programs/ecryptfs.nix6
-rw-r--r--nixos/modules/programs/environment.nix10
-rw-r--r--nixos/modules/programs/extra-container.nix5
-rw-r--r--nixos/modules/programs/feedbackd.nix8
-rw-r--r--nixos/modules/programs/firefox.nix52
-rw-r--r--nixos/modules/programs/firejail.nix40
-rw-r--r--nixos/modules/programs/fish.nix78
-rw-r--r--nixos/modules/programs/flashrom.nix10
-rw-r--r--nixos/modules/programs/flexoptix-app.nix8
-rw-r--r--nixos/modules/programs/freetds.nix12
-rw-r--r--nixos/modules/programs/fuse.nix16
-rw-r--r--nixos/modules/programs/gamemode.nix20
-rw-r--r--nixos/modules/programs/gamescope.nix36
-rw-r--r--nixos/modules/programs/geary.nix8
-rw-r--r--nixos/modules/programs/git.nix34
-rw-r--r--nixos/modules/programs/gnupg.nix16
-rw-r--r--nixos/modules/programs/gphoto2.nix10
-rw-r--r--nixos/modules/programs/haguichi.nix6
-rw-r--r--nixos/modules/programs/hamster.nix4
-rw-r--r--nixos/modules/programs/htop.nix24
-rw-r--r--nixos/modules/programs/i3lock.nix14
-rw-r--r--nixos/modules/programs/iftop.nix6
-rw-r--r--nixos/modules/programs/iotop.nix6
-rw-r--r--nixos/modules/programs/java.nix12
-rw-r--r--nixos/modules/programs/joycond-cemuhook.nix3
-rw-r--r--nixos/modules/programs/k3b.nix8
-rw-r--r--nixos/modules/programs/k40-whisperer.nix12
-rw-r--r--nixos/modules/programs/kbdlight.nix6
-rw-r--r--nixos/modules/programs/kclock.nix5
-rw-r--r--nixos/modules/programs/kdeconnect.nix8
-rw-r--r--nixos/modules/programs/less.nix64
-rw-r--r--nixos/modules/programs/liboping.nix8
-rw-r--r--nixos/modules/programs/light.nix20
-rw-r--r--nixos/modules/programs/mdevctl.nix5
-rw-r--r--nixos/modules/programs/mepo.nix17
-rw-r--r--nixos/modules/programs/mininet.nix6
-rw-r--r--nixos/modules/programs/msmtp.nix32
-rw-r--r--nixos/modules/programs/mtr.nix12
-rw-r--r--nixos/modules/programs/nbd.nix6
-rw-r--r--nixos/modules/programs/neovim.nix76
-rw-r--r--nixos/modules/programs/nethoscope.nix10
-rw-r--r--nixos/modules/programs/nncp.nix23
-rw-r--r--nixos/modules/programs/noisetorch.nix8
-rw-r--r--nixos/modules/programs/npm.nix8
-rw-r--r--nixos/modules/programs/oblogout.nix4
-rw-r--r--nixos/modules/programs/openvpn3.nix12
-rw-r--r--nixos/modules/programs/pantheon-tweaks.nix19
-rw-r--r--nixos/modules/programs/plotinus.nix8
-rw-r--r--nixos/modules/programs/pqos-wrapper.nix27
-rw-r--r--nixos/modules/programs/proxychains.nix71
-rw-r--r--nixos/modules/programs/qt5ct.nix4
-rw-r--r--nixos/modules/programs/rust-motd.nix34
-rw-r--r--nixos/modules/programs/screen.nix37
-rw-r--r--nixos/modules/programs/sedutil.nix6
-rw-r--r--nixos/modules/programs/shadow.nix53
-rw-r--r--nixos/modules/programs/sharing.nix5
-rw-r--r--nixos/modules/programs/singularity.nix35
-rw-r--r--nixos/modules/programs/slock.nix10
-rw-r--r--nixos/modules/programs/soundmodem.nix10
-rw-r--r--nixos/modules/programs/spacefm.nix16
-rw-r--r--nixos/modules/programs/ssh.nix136
-rw-r--r--nixos/modules/programs/steam.nix82
-rw-r--r--nixos/modules/programs/streamdeck-ui.nix18
-rw-r--r--nixos/modules/programs/sysdig.nix6
-rw-r--r--nixos/modules/programs/system-config-printer.nix6
-rw-r--r--nixos/modules/programs/systemtap.nix8
-rw-r--r--nixos/modules/programs/thefuck.nix14
-rw-r--r--nixos/modules/programs/thunar.nix14
-rw-r--r--nixos/modules/programs/traceroute.nix8
-rw-r--r--nixos/modules/programs/turbovnc.nix8
-rw-r--r--nixos/modules/programs/udevil.nix6
-rw-r--r--nixos/modules/programs/usbtop.nix6
-rw-r--r--nixos/modules/programs/vim.nix12
-rw-r--r--nixos/modules/programs/virt-manager.nix18
-rw-r--r--nixos/modules/programs/wavemon.nix8
-rw-r--r--nixos/modules/programs/wayland/hyprland.nix42
-rw-r--r--nixos/modules/programs/wayland/river.nix22
-rw-r--r--nixos/modules/programs/wayland/sway.nix50
-rw-r--r--nixos/modules/programs/wayland/waybar.nix10
-rw-r--r--nixos/modules/programs/wayland/wayland-session.nix12
-rw-r--r--nixos/modules/programs/weylus.nix16
-rw-r--r--nixos/modules/programs/wireshark.nix10
-rw-r--r--nixos/modules/programs/xastir.nix8
-rw-r--r--nixos/modules/programs/xfconf.nix8
-rw-r--r--nixos/modules/programs/xfs_quota.nix48
-rw-r--r--nixos/modules/programs/xonsh.nix14
-rw-r--r--nixos/modules/programs/xss-lock.nix29
-rw-r--r--nixos/modules/programs/xwayland.nix20
-rw-r--r--nixos/modules/programs/yabar.nix60
-rw-r--r--nixos/modules/programs/yazi.nix63
-rw-r--r--nixos/modules/programs/ydotool.nix83
-rw-r--r--nixos/modules/programs/zmap.nix6
-rw-r--r--nixos/modules/programs/zsh/oh-my-zsh.nix52
-rw-r--r--nixos/modules/programs/zsh/zsh-autoenv.nix8
-rw-r--r--nixos/modules/programs/zsh/zsh-autosuggestions.nix32
-rw-r--r--nixos/modules/programs/zsh/zsh-syntax-highlighting.nix50
-rw-r--r--nixos/modules/programs/zsh/zsh.nix86
-rw-r--r--nixos/modules/rename.nix8
-rw-r--r--nixos/modules/security/systemd-confinement.nix36
-rw-r--r--nixos/modules/services/admin/pgadmin.nix10
-rw-r--r--nixos/modules/services/audio/navidrome.nix191
-rw-r--r--nixos/modules/services/backup/borgbackup.nix34
-rw-r--r--nixos/modules/services/cluster/k3s/default.nix44
-rw-r--r--nixos/modules/services/continuous-integration/hydra/default.nix2
-rw-r--r--nixos/modules/services/desktop-managers/lomiri.nix5
-rw-r--r--nixos/modules/services/desktop-managers/plasma6.nix49
-rw-r--r--nixos/modules/services/desktops/espanso.nix12
-rw-r--r--nixos/modules/services/display-managers/default.nix4
-rw-r--r--nixos/modules/services/display-managers/greetd.nix14
-rw-r--r--nixos/modules/services/display-managers/sddm.nix15
-rw-r--r--nixos/modules/services/games/archisteamfarm.nix7
-rw-r--r--nixos/modules/services/hardware/kanata.nix23
-rw-r--r--nixos/modules/services/hardware/thermald.nix13
-rw-r--r--nixos/modules/services/home-automation/wyoming/faster-whisper.nix3
-rw-r--r--nixos/modules/services/home-automation/wyoming/openwakeword.nix3
-rw-r--r--nixos/modules/services/home-automation/wyoming/piper.nix3
-rw-r--r--nixos/modules/services/mail/stalwart-mail.nix36
-rw-r--r--nixos/modules/services/misc/bcg.nix6
-rw-r--r--nixos/modules/services/misc/devpi-server.nix128
-rw-r--r--nixos/modules/services/misc/llama-cpp.nix1
-rw-r--r--nixos/modules/services/misc/plex.nix29
-rw-r--r--nixos/modules/services/misc/portunus.nix4
-rw-r--r--nixos/modules/services/misc/private-gpt.nix121
-rw-r--r--nixos/modules/services/misc/snapper.nix21
-rw-r--r--nixos/modules/services/misc/tzupdate.nix2
-rw-r--r--nixos/modules/services/monitoring/arbtt.nix2
-rw-r--r--nixos/modules/services/monitoring/loki.nix14
-rw-r--r--nixos/modules/services/networking/hostapd.nix17
-rw-r--r--nixos/modules/services/networking/kea.nix3
-rw-r--r--nixos/modules/services/networking/oink.nix84
-rw-r--r--nixos/modules/services/networking/pixiecore.nix4
-rw-r--r--nixos/modules/services/networking/radvd.nix13
-rw-r--r--nixos/modules/services/networking/rosenpass.nix6
-rw-r--r--nixos/modules/services/networking/smokeping.nix63
-rw-r--r--nixos/modules/services/networking/tayga.nix26
-rw-r--r--nixos/modules/services/networking/vsftpd.nix2
-rw-r--r--nixos/modules/services/networking/wireguard.nix10
-rw-r--r--nixos/modules/services/security/bitwarden-directory-connector-cli.nix1
-rw-r--r--nixos/modules/services/security/oauth2-proxy-nginx.nix24
-rw-r--r--nixos/modules/services/security/oauth2-proxy.nix30
-rw-r--r--nixos/modules/services/system/dbus.nix8
-rw-r--r--nixos/modules/services/video/frigate.nix4
-rw-r--r--nixos/modules/services/web-apps/artalk.nix131
-rw-r--r--nixos/modules/services/web-apps/commafeed.nix114
-rw-r--r--nixos/modules/services/web-apps/filesender.md49
-rw-r--r--nixos/modules/services/web-apps/filesender.nix253
-rw-r--r--nixos/modules/services/web-apps/flarum.nix210
-rw-r--r--nixos/modules/services/web-apps/keycloak.nix5
-rw-r--r--nixos/modules/services/web-apps/miniflux.nix15
-rw-r--r--nixos/modules/services/web-apps/nextcloud.nix2
-rw-r--r--nixos/modules/services/web-apps/nextjs-ollama-llm-ui.nix87
-rw-r--r--nixos/modules/services/web-apps/pretalx.nix84
-rw-r--r--nixos/modules/services/web-apps/pretix.nix12
-rw-r--r--nixos/modules/services/web-apps/simplesamlphp.nix128
-rw-r--r--nixos/modules/services/web-apps/your_spotify.nix191
-rw-r--r--nixos/modules/services/web-servers/bluemap.nix311
-rw-r--r--nixos/modules/services/web-servers/caddy/default.nix2
-rw-r--r--nixos/modules/services/web-servers/garage.nix58
-rw-r--r--nixos/modules/services/web-servers/nginx/default.nix11
-rw-r--r--nixos/modules/services/x11/desktop-managers/mate.nix1
-rw-r--r--nixos/modules/services/x11/window-managers/qtile.nix14
-rw-r--r--nixos/modules/services/x11/xserver.nix3
-rw-r--r--nixos/modules/system/activation/switchable-system.nix109
-rw-r--r--nixos/modules/system/boot/binfmt.nix2
-rw-r--r--nixos/modules/system/boot/resolved.nix143
-rw-r--r--nixos/modules/system/boot/systemd/initrd.nix4
-rw-r--r--nixos/modules/tasks/filesystems/zfs.nix34
-rw-r--r--nixos/modules/testing/test-instrumentation.nix2
-rw-r--r--nixos/modules/virtualisation/lxc-image-metadata.nix4
-rw-r--r--nixos/modules/virtualisation/qemu-vm.nix2
-rw-r--r--nixos/release-combined.nix6
-rw-r--r--nixos/release-small.nix4
-rw-r--r--nixos/tests/acme.nix32
-rw-r--r--nixos/tests/all-tests.nix22
-rw-r--r--nixos/tests/artalk.nix28
-rw-r--r--nixos/tests/avahi.nix2
-rw-r--r--nixos/tests/ayatana-indicators.nix7
-rw-r--r--nixos/tests/benchexec.nix54
-rw-r--r--nixos/tests/bittorrent.nix2
-rw-r--r--nixos/tests/castopod.nix3
-rw-r--r--nixos/tests/commafeed.nix21
-rw-r--r--nixos/tests/containers-bridge.nix2
-rw-r--r--nixos/tests/containers-imperative.nix2
-rw-r--r--nixos/tests/containers-ip.nix2
-rw-r--r--nixos/tests/containers-portforward.nix2
-rw-r--r--nixos/tests/devpi-server.nix35
-rw-r--r--nixos/tests/elk.nix2
-rw-r--r--nixos/tests/fcitx5/default.nix3
-rw-r--r--nixos/tests/filesender.nix137
-rw-r--r--nixos/tests/firefox.nix6
-rw-r--r--nixos/tests/firewall.nix2
-rw-r--r--nixos/tests/garage/default.nix1
-rw-r--r--nixos/tests/garage/with-3node-replication.nix8
-rw-r--r--nixos/tests/incus/container.nix7
-rw-r--r--nixos/tests/incus/default.nix21
-rw-r--r--nixos/tests/incus/incusd-options.nix8
-rw-r--r--nixos/tests/incus/lxd-to-incus.nix12
-rw-r--r--nixos/tests/incus/openvswitch.nix8
-rw-r--r--nixos/tests/incus/socket-activated.nix9
-rw-r--r--nixos/tests/incus/storage.nix12
-rw-r--r--nixos/tests/incus/ui.nix7
-rw-r--r--nixos/tests/incus/virtual-machine.nix7
-rw-r--r--nixos/tests/initrd-network.nix2
-rw-r--r--nixos/tests/installer-systemd-stage-1.nix2
-rw-r--r--nixos/tests/installer.nix14
-rw-r--r--nixos/tests/ipv6.nix2
-rw-r--r--nixos/tests/jenkins.nix2
-rw-r--r--nixos/tests/k3s/default.nix18
-rw-r--r--nixos/tests/k3s/etcd.nix200
-rw-r--r--nixos/tests/k3s/multi-node.nix226
-rw-r--r--nixos/tests/k3s/single-node.nix139
-rw-r--r--nixos/tests/keepalived.nix4
-rw-r--r--nixos/tests/kernel-generic.nix2
-rw-r--r--nixos/tests/knot.nix4
-rw-r--r--nixos/tests/login.nix2
-rw-r--r--nixos/tests/logrotate.nix90
-rw-r--r--nixos/tests/lomiri.nix143
-rw-r--r--nixos/tests/mediamtx.nix95
-rw-r--r--nixos/tests/misc.nix343
-rw-r--r--nixos/tests/mumble.nix2
-rw-r--r--nixos/tests/munin.nix2
-rw-r--r--nixos/tests/mysql/common.nix2
-rw-r--r--nixos/tests/mysql/mysql.nix2
-rw-r--r--nixos/tests/nat.nix2
-rw-r--r--nixos/tests/nfs/simple.nix2
-rw-r--r--nixos/tests/openssh.nix2
-rw-r--r--nixos/tests/pgvecto-rs.nix2
-rw-r--r--nixos/tests/printing.nix2
-rw-r--r--nixos/tests/private-gpt.nix27
-rw-r--r--nixos/tests/proxy.nix2
-rw-r--r--nixos/tests/quake3.nix2
-rw-r--r--nixos/tests/rabbitmq.nix2
-rw-r--r--nixos/tests/samba.nix2
-rw-r--r--nixos/tests/simple.nix2
-rw-r--r--nixos/tests/smokeping.nix14
-rw-r--r--nixos/tests/stalwart-mail.nix239
-rw-r--r--nixos/tests/step-ca.nix23
-rw-r--r--nixos/tests/stub-ld.nix4
-rw-r--r--nixos/tests/switch-test.nix7
-rw-r--r--nixos/tests/systemd-confinement.nix184
-rw-r--r--nixos/tests/systemd-confinement/checkperms.py187
-rw-r--r--nixos/tests/systemd-confinement/default.nix274
-rw-r--r--nixos/tests/systemd-initrd-luks-fido2.nix1
-rw-r--r--nixos/tests/systemd-initrd-modprobe.nix12
-rw-r--r--nixos/tests/systemd-resolved.nix75
-rw-r--r--nixos/tests/tayga.nix19
-rw-r--r--nixos/tests/tigervnc.nix8
-rw-r--r--nixos/tests/udisks2.nix3
-rw-r--r--nixos/tests/vector.nix37
-rw-r--r--nixos/tests/vector/api.nix39
-rw-r--r--nixos/tests/vector/default.nix11
-rw-r--r--nixos/tests/vector/dnstap.nix118
-rw-r--r--nixos/tests/vector/file-sink.nix49
-rw-r--r--nixos/tests/vector/nginx-clickhouse.nix168
-rw-r--r--nixos/tests/virtualbox.nix1
-rw-r--r--nixos/tests/web-apps/nextjs-ollama-llm-ui.nix22
-rw-r--r--nixos/tests/web-apps/pretalx.nix9
-rw-r--r--nixos/tests/ydotool.nix115
-rw-r--r--nixos/tests/your_spotify.nix33
311 files changed, 7924 insertions, 3592 deletions
diff --git a/nixos/doc/manual/development/option-declarations.section.md b/nixos/doc/manual/development/option-declarations.section.md
index 325f4d11cb083..ee4540d0cf6fd 100644
--- a/nixos/doc/manual/development/option-declarations.section.md
+++ b/nixos/doc/manual/development/option-declarations.section.md
@@ -173,7 +173,7 @@ lib.mkOption {
 
 ## Extensible Option Types {#sec-option-declarations-eot}
 
-Extensible option types is a feature that allow to extend certain types
+Extensible option types is a feature that allows to extend certain types
 declaration through multiple module files. This feature only work with a
 restricted set of types, namely `enum` and `submodules` and any composed
 forms of them.
diff --git a/nixos/doc/manual/development/settings-options.section.md b/nixos/doc/manual/development/settings-options.section.md
index 806eee5637907..cedc82d32f89a 100644
--- a/nixos/doc/manual/development/settings-options.section.md
+++ b/nixos/doc/manual/development/settings-options.section.md
@@ -146,6 +146,27 @@ have a predefined type and string generator already declared under
     :   Outputs the given attribute set as an Elixir map, instead of the
         default Elixir keyword list
 
+`pkgs.formats.php { finalVariable }` []{#pkgs-formats-php}
+
+:   A function taking an attribute set with values
+
+    `finalVariable`
+
+    :   The variable that will store generated expression (usually `config`). If set to `null`, generated expression will contain `return`.
+
+    It returns a set with PHP-Config-specific attributes `type`, `lib`, and
+    `generate` as specified [below](#pkgs-formats-result).
+
+    The `lib` attribute contains functions to be used in settings, for
+    generating special PHP values:
+
+    `mkRaw phpCode`
+
+    :   Outputs the given string as raw PHP code
+
+    `mkMixedArray list set`
+
+    :   Creates PHP array that contains both indexed and associative values. For example, `lib.mkMixedArray [ "hello" "world" ] { "nix" = "is-great"; }` returns `['hello', 'world', 'nix' => 'is-great']`
 
 []{#pkgs-formats-result}
 These functions all return an attribute set with these values:
diff --git a/nixos/doc/manual/installation/installing-from-other-distro.section.md b/nixos/doc/manual/installation/installing-from-other-distro.section.md
index 10ac2be4e161f..38f0e5301472b 100644
--- a/nixos/doc/manual/installation/installing-from-other-distro.section.md
+++ b/nixos/doc/manual/installation/installing-from-other-distro.section.md
@@ -42,9 +42,11 @@ The first steps to all these are the same:
     will be safer to use the `nixos-*` channels instead:
 
     ```ShellSession
-    $ nix-channel --add https://nixos.org/channels/nixos-version nixpkgs
+    $ nix-channel --add https://nixos.org/channels/nixos-<version> nixpkgs
     ```
 
+    Where `<version>` corresponds to the latest version available on [channels.nixos.org](https://channels.nixos.org/).
+
     You may want to throw in a `nix-channel --update` for good measure.
 
 1.  Install the NixOS installation tools:
diff --git a/nixos/doc/manual/installation/installing-virtualbox-guest.section.md b/nixos/doc/manual/installation/installing-virtualbox-guest.section.md
index 4b9ae0a9c55f0..415119bd8c898 100644
--- a/nixos/doc/manual/installation/installing-virtualbox-guest.section.md
+++ b/nixos/doc/manual/installation/installing-virtualbox-guest.section.md
@@ -3,8 +3,8 @@
 Installing NixOS into a VirtualBox guest is convenient for users who
 want to try NixOS without installing it on bare metal. If you want to
 use a pre-made VirtualBox appliance, it is available at [the downloads
-page](https://nixos.org/nixos/download.html). If you want to set up a
-VirtualBox guest manually, follow these instructions:
+page](https://nixos.org/download/#nixos-virtualbox). If you want to set
+up a VirtualBox guest manually, follow these instructions:
 
 1.  Add a New Machine in VirtualBox with OS Type "Linux / Other Linux"
 
diff --git a/nixos/doc/manual/installation/upgrading.chapter.md b/nixos/doc/manual/installation/upgrading.chapter.md
index 09338bf8723d2..11fc65502f953 100644
--- a/nixos/doc/manual/installation/upgrading.chapter.md
+++ b/nixos/doc/manual/installation/upgrading.chapter.md
@@ -33,8 +33,8 @@ To see what channels are available, go to <https://channels.nixos.org>.
 contains the channel's latest version and includes ISO images and
 VirtualBox appliances.) Please note that during the release process,
 channels that are not yet released will be present here as well. See the
-Getting NixOS page <https://nixos.org/nixos/download.html> to find the
-newest supported stable release.
+Getting NixOS page <https://nixos.org/download/> to find the newest
+supported stable release.
 
 When you first install NixOS, you're automatically subscribed to the
 NixOS channel that corresponds to your installation source. For
diff --git a/nixos/doc/manual/release-notes/release-notes.md b/nixos/doc/manual/release-notes/release-notes.md
index 0514a1b0044af..24494ed95ca88 100644
--- a/nixos/doc/manual/release-notes/release-notes.md
+++ b/nixos/doc/manual/release-notes/release-notes.md
@@ -3,6 +3,7 @@
 This section lists the release notes for each stable version of NixOS and current unstable revision.
 
 ```{=include=} sections
+rl-2411.section.md
 rl-2405.section.md
 rl-2311.section.md
 rl-2305.section.md
diff --git a/nixos/doc/manual/release-notes/rl-2111.section.md b/nixos/doc/manual/release-notes/rl-2111.section.md
index 8edf4fd35e4fb..4143f440f2890 100644
--- a/nixos/doc/manual/release-notes/rl-2111.section.md
+++ b/nixos/doc/manual/release-notes/rl-2111.section.md
@@ -146,7 +146,7 @@ In addition to numerous new and upgraded packages, this release has the followin
 
 - [touchegg](https://github.com/JoseExposito/touchegg), a multi-touch gesture recognizer. Available as [services.touchegg](#opt-services.touchegg.enable).
 
-- [pantheon-tweaks](https://github.com/pantheon-tweaks/pantheon-tweaks), an unofficial system settings panel for Pantheon. Available as [programs.pantheon-tweaks](#opt-programs.pantheon-tweaks.enable).
+- [pantheon-tweaks](https://github.com/pantheon-tweaks/pantheon-tweaks), an unofficial system settings panel for Pantheon. Available as `programs.pantheon-tweaks`.
 
 - [joycond](https://github.com/DanielOgorchock/joycond), a service that uses `hid-nintendo` to provide nintendo joycond pairing and better nintendo switch pro controller support.
 
diff --git a/nixos/doc/manual/release-notes/rl-2405.section.md b/nixos/doc/manual/release-notes/rl-2405.section.md
index 4058f4e504418..4187d4a58afec 100644
--- a/nixos/doc/manual/release-notes/rl-2405.section.md
+++ b/nixos/doc/manual/release-notes/rl-2405.section.md
@@ -6,21 +6,17 @@ Support is planned until the end of December 2024, handing over to 24.11.
 
 In addition to numerous new and upgraded packages, this release has the following highlights:
 
-<!-- To avoid merge conflicts, consider adding your item at an arbitrary place in the list instead. -->
-
-- `cryptsetup` has been upgraded from 2.6.1 to 2.7.0. Cryptsetup is a critical component enabling LUKS-based (but not only) full disk encryption.
-  Take the time to review [the release notes](https://gitlab.com/cryptsetup/cryptsetup/-/raw/v2.7.0/docs/v2.7.0-ReleaseNotes).
-  One of the highlights is that it is now possible to use hardware OPAL-based encryption of your disk with `cryptsetup`. It has a lot of caveats, see the above notes for the full details.
+<!-- Please keep entries alphabetically sorted. -->
 
-- `screen`'s module has been cleaned, and will now require you to set `programs.screen.enable` in order to populate `screenrc` and add the program to the environment.
+- The default kernel package has been updated from 6.1 to 6.6. All supported kernels remain available.
 
-- `linuxPackages_testing_bcachefs` is now fully deprecated by `linuxPackages_latest`, and is therefore no longer available.
-
-- (TODO not sure what path to use here) The default kernel package has been updated from 6.1 to 6.6. All supported kernels remain available.
+- For each supporting version of the Linux kernel, firmware blobs
+  are compressed with zstd. For firmware blobs this means an increase of 4.4% in size, however
+  a significantly higher decompression speed.
 
 - NixOS now installs a stub ELF loader that prints an informative error message when users attempt to run binaries not made for NixOS.
-   - This can be disabled through the `environment.stub-ld.enable` option.
-   - If you use `programs.nix-ld.enable`, no changes are needed. The stub will be disabled automatically.
+  - This can be disabled through the `environment.stub-ld.enable` option.
+  - If you use `programs.nix-ld.enable`, no changes are needed. The stub will be disabled automatically.
 
 - On flake-based NixOS configurations using `nixpkgs.lib.nixosSystem`, NixOS will automatically set `NIX_PATH` and the system-wide flake registry (`/etc/nix/registry.json`) to point `<nixpkgs>` and the unqualified flake path `nixpkgs` to the version of nixpkgs used to build the system.
 
@@ -30,33 +26,6 @@ In addition to numerous new and upgraded packages, this release has the followin
 
   To disable this, set [nixpkgs.flake.setNixPath](#opt-nixpkgs.flake.setNixPath) and [nixpkgs.flake.setFlakeRegistry](#opt-nixpkgs.flake.setFlakeRegistry) to false.
 
-- `nixVersions.unstable` was removed. Instead the following attributes are provided:
-  - `nixVersions.git` which tracks the latest Nix master and is roughly updated once a week. This is intended to enable people to easily test unreleased changes of Nix to catch regressions earlier.
-  - `nixVersions.latest` which points to the latest Nix version packaged in nixpkgs.
-
-- `julia` environments can now be built with arbitrary packages from the ecosystem using the `.withPackages` function. For example: `julia.withPackages ["Plots"]`.
-
-- `pipewire` and `wireplumber` modules have removed support for using
-`environment.etc."pipewire/..."` and `environment.etc."wireplumber/..."`.
-Use `services.pipewire.extraConfig` or `services.pipewire.configPackages` for PipeWire and
-`services.pipewire.wireplumber.configPackages` for WirePlumber instead."
-
-- `teleport` has been upgraded from major version 14 to major version 15.
-  Refer to upstream [upgrade instructions](https://goteleport.com/docs/management/operations/upgrading/)
-  and release notes for [v15](https://goteleport.com/docs/changelog/#1500-013124).
-
-- `systemd.sysusers.enable` option was added. If enabled, users and
-  groups are created with systemd-sysusers instead of with a custom perl script.
-
-- `virtualisation.docker.enableNvidia` and `virtualisation.podman.enableNvidia` options are deprecated. `hardware.nvidia-container-toolkit.enable` should be used instead. This option will expose GPUs on containers with the `--device` CLI option. This is supported by Docker 25, Podman 3.2.0 and Singularity 4. Any container runtime that supports the CDI specification will take advantage of this feature.
-
-- `system.etc.overlay.enable` option was added. If enabled, `/etc` is
-  mounted via an overlayfs instead of being created by a custom perl script.
-
-- For each supporting version of the Linux kernel firmware blobs
-  are compressed with zstd. For firmware blobs this means an increase of 4.4% in size, however
-  a significantly higher decompression speed.
-
 - NixOS AMIs are now uploaded regularly to a new AWS Account.
   Instructions on how to use them can be found on <https://nixos.github.io/amis>.
   We are working on integration the data into the NixOS homepage.
@@ -73,263 +42,310 @@ Use `services.pipewire.extraConfig` or `services.pipewire.configPackages` for Pi
   }
   ```
 
-- `virtialisation.incus` now defaults to the newly-added `incus-lts` release (v6.0.x). Users who wish to continue using the non-LTS release will need to set `virtualisation.incus.package = pkgs.incus`. Stable release users are encouraged to stay on the LTS release as non-LTS releases will by default not be backported.
+- Lomiri (formerly known as Unity8) desktop mode, using Mir 2.x to function as a Wayland compositor, is now available and can be installed with `services.desktopManager.lomiri.enable = true`. Note that some core applications, services and indicators have yet to be packaged, and some functions may remain incomplete, but the base experience should be there.
 
-- Canonical `lxd` has been upgraded to v5.21.x, an LTS release. The LTS release is now the only supported LXD release. Users are encouraged to [migrate to Incus](https://linuxcontainers.org/incus/docs/main/howto/server_migrate_lxd/) for better support on NixOS.
+- MATE has been updated to 1.28.
+  - To properly support panel plugins built with Wayland (in-process) support, we are introducing `services.xserver.desktopManager.mate.extraPanelApplets` option, please use that for installing panel applets.
+  - Similarly, please use `services.xserver.desktopManager.mate.extraCajaExtensions` option for installing Caja extensions.
+  - To use the Wayland session, enable `services.xserver.desktopManager.mate.enableWaylandSession`. This is opt-in for now as it is in early stage and introduces a new set of Wayfire closure. Due to [known issues with LightDM](https://github.com/canonical/lightdm/issues/63), we suggest using SDDM for display manager.
 
-- `lua` interpreters default LUA_PATH and LUA_CPATH are not overriden by nixpkgs
-  anymore, we patch LUA_ROOT instead which is more respectful to upstream.
+- Plasma 6 is now available and can be installed with `services.xserver.desktopManager.plasma6.enable = true;`. Plasma 5 will likely be deprecated in the next release (24.11). Note that Plasma 6 runs as Wayland by default, and the X11 session needs to be explicitly selected if necessary.
 
-- `plasma6` is now available and can be installed with `services.xserver.desktopManager.plasma6.enable = true;`. Plasma 5 will likely be deprecated in the next release (24.11). Note that Plasma 6 runs as Wayland by default, and the X11 session needs to be explicitly selected if necessary.
+## New Services {#sec-release-24.05-new-services}
 
-- `lomiri` (formerly known as Unity8) desktop mode, using Mir 2.x to function as a Wayland compositor, is now available and can be installed with `services.desktopManager.lomiri.enable = true`. Note that some core applications, services and indicators have yet to be packaged, and some functions may remain incomplete, but the base experience should be there.
+<!-- Please keep entries alphabetically sorted. -->
 
-## New Services {#sec-release-24.05-new-services}
+- [Anki Sync Server](https://docs.ankiweb.net/sync-server.html), the official sync server built into recent versions of Anki. Available as [services.anki-sync-server](#opt-services.anki-sync-server.enable).
+The pre-existing [services.ankisyncd](#opt-services.ankisyncd.enable) has been marked deprecated and will be dropped after 24.05 due to lack of maintenance of the anki-sync-server software.
 
-<!-- To avoid merge conflicts, consider adding your item at an arbitrary place in the list instead. -->
+- [ALVR](https://github.com/alvr-org/alvr), a VR desktop streamer. Available as [programs.alvr](#opt-programs.alvr.enable).
 
-- [ownCloud Infinite Scale Stack](https://owncloud.com/infinite-scale-4-0/), a modern and scalable rewrite of ownCloud.
+- [AppImage](https://appimage.org/), a tool to package desktop applications, now has a `binfmt` option to support running AppImages seamlessly on NixOS. Available as [programs.appimage.binfmt](#opt-programs.appimage.binfmt).
 
-- [Handheld Daemon](https://github.com/hhd-dev/hhd), support for gaming handhelds like the Legion Go, ROG Ally, and GPD Win. Available as [services.handheld-daemon](#opt-services.handheld-daemon.enable).
+- [armagetronad](https://wiki.armagetronad.org), a mid-2000s 3D lightcycle game widely played at iD Tech Camps. You can define multiple servers using `services.armagetronad.<server>.enable`.
 
-- [Guix](https://guix.gnu.org), a functional package manager inspired by Nix. Available as [services.guix](#opt-services.guix.enable).
+- [BenchExec](https://github.com/sosy-lab/benchexec), a framework for reliable benchmarking and resource measurement, available as [programs.benchexec](#opt-programs.benchexec.enable),
+  As well as related programs
+  [CPU Energy Meter](https://github.com/sosy-lab/cpu-energy-meter), available as [programs.cpu-energy-meter](#opt-programs.cpu-energy-meter.enable), and
+  [PQoS Wrapper](https://gitlab.com/sosy-lab/software/pqos-wrapper), available as [programs.pqos-wrapper](#opt-programs.pqos-wrapper.enable).
 
-- [PhotonVision](https://photonvision.org/), a free, fast, and easy-to-use computer vision solution for the FIRST® Robotics Competition.
+- [Bluemap](https://bluemap.bluecolored.de/), a 3D minecraft map renderer. Available as [services.bluemap](#opt-services.bluemap.enable).
 
 - [clatd](https://github.com/toreanderson/clatd), a CLAT / SIIT-DC Edge Relay implementation for Linux.
 
-- [pyLoad](https://pyload.net/), a FOSS download manager written in Python. Available as [services.pyload](#opt-services.pyload.enable)
-
-- [maubot](https://github.com/maubot/maubot), a plugin-based Matrix bot framework. Available as [services.maubot](#opt-services.maubot.enable).
+- [Clevis](https://github.com/latchset/clevis), a pluggable framework for automated decryption, used to unlock encrypted devices in initrd. Available as [boot.initrd.clevis.enable](#opt-boot.initrd.clevis.enable).
 
-- [ryzen-monitor-ng](https://github.com/mann1x/ryzen_monitor_ng), a desktop AMD CPU power monitor and controller, similar to Ryzen Master but for Linux. Available as [programs.ryzen-monitor-ng](#opt-programs.ryzen-monitor-ng.enable)
+- [CommaFeed](https://github.com/Athou/commafeed), a Google Reader-inspired self-hosted RSS reader. Available as [services.commafeed](#opt-services.commafeed.enable).
 
-- [ryzen-smu](https://gitlab.com/leogx9r/ryzen_smu), Linux kernel driver to expose the SMU (System Management Unit) for certain AMD Ryzen Processors. Includes the userspace program `monitor_cpu`. Available at [hardward.cpu.amd.ryzen-smu](#opt-hardware.cpu.amd.ryzen-smu.enable)
+- [davis](https://github.com/tchapi/davis), a simple CardDav and CalDav server inspired by Baïkal. Available as [services.davis](#opt-services.davis.enable).
 
-- `systemd`'s `gateway`, `upload`, and `remote` services, which provide ways of sending journals across the network. Enable using [services.journald.gateway](#opt-services.journald.gateway.enable), [services.journald.upload](#opt-services.journald.upload.enable), and [services.journald.remote](#opt-services.journald.remote.enable).
+- [db-rest](https://github.com/derhuerst/db-rest), a wrapper around Deutsche Bahn's internal API for public transport data. Available as [services.db-rest](#opt-services.db-rest.enable).
 
-- [GNS3](https://www.gns3.com/), a network software emulator. Available as [services.gns3-server](#opt-services.gns3-server.enable).
+- [dnsproxy](https://github.com/AdguardTeam/dnsproxy), a simple DNS proxy with DoH, DoT, DoQ and DNSCrypt support. Available as [services.dnsproxy](#opt-services.dnsproxy.enable).
 
-- [pretalx](https://github.com/pretalx/pretalx), a conference planning tool. Available as [services.pretalx](#opt-services.pretalx.enable).
+- [FCast Receiver](https://fcast.org), an open-source alternative to Chromecast and AirPlay. Available as [programs.fcast-receiver](#opt-programs.fcast-receiver.enable).
 
-- [dnsproxy](https://github.com/AdguardTeam/dnsproxy), a simple DNS proxy with DoH, DoT, DoQ and DNSCrypt support. Available as [services.dnsproxy](#opt-services.dnsproxy.enable).
+- [FileSender](https://filesender.org/), a file sharing software. Available as [services.filesender](#opt-services.filesender.enable).
 
-- [manticoresearch](https://manticoresearch.com), easy to use open source fast database for search. Available as [services.manticore](#opt-services.manticore.enable).
+- [Firefly-iii](https://www.firefly-iii.org), a free and open source personal finance manager. Available as [services.firefly-iii](#opt-services.firefly-iii.enable).
 
-- [rspamd-trainer](https://gitlab.com/onlime/rspamd-trainer), script triggered by a helper which reads mails from a specific mail inbox and feeds them into rspamd for spam/ham training.
+- [Flarum](https://flarum.org/), a delightfully simple discussion platform for your website. Available as [services.flarum](#opt-services.flarum.enable).
 
-- [ollama](https://ollama.ai), server for running large language models locally.
+- [fritz-exporter](https://github.com/pdreker/fritz_exporter), a Prometheus exporter for extracting metrics from [FRITZ!](https://avm.de/produkte/) devices. Available as [services.prometheus.exporters.fritz](#opt-services.prometheus.exporters.fritz.enable).
 
-- [Mihomo](https://github.com/MetaCubeX/mihomo/tree/Alpha), a rule-based proxy in Go. Available as [services.mihomo.enable](#opt-services.mihomo.enable).
+- [GNS3](https://www.gns3.com/), a network software emulator. Available as [services.gns3-server](#opt-services.gns3-server.enable).
 
-- [hebbot](https://github.com/haecker-felix/hebbot), a Matrix bot to generate "This Week in X" like blog posts. Available as [services.hebbot](#opt-services.hebbot.enable).
+- [go-camo](https://github.com/cactus/go-camo), a secure image proxy server. Available as [services.go-camo](#opt-services.go-camo.enable).
 
-- [Workout-tracker](https://github.com/jovandeginste/workout-tracker), a workout tracking web application for personal use.
+- [Guix](https://guix.gnu.org), a functional package manager inspired by Nix. Available as [services.guix](#opt-services.guix.enable).
 
-- [Python Matter Server](https://github.com/home-assistant-libs/python-matter-server), a
-  Matter Controller Server exposing websocket connections for use with other services, notably Home Assistant.
-  Available as [services.matter-server](#opt-services.matter-server.enable)
+- [Handheld Daemon](https://github.com/hhd-dev/hhd), support for gaming handhelds like the Legion Go, ROG Ally, and GPD Win. Available as [services.handheld-daemon](#opt-services.handheld-daemon.enable).
 
-- [db-rest](https://github.com/derhuerst/db-rest), a wrapper around Deutsche Bahn's internal API for public transport data. Available as [services.db-rest](#opt-services.db-rest.enable).
+- [hebbot](https://github.com/haecker-felix/hebbot), a Matrix bot to generate "This Week in X" like blog posts. Available as [services.hebbot](#opt-services.hebbot.enable).
 
-- [mautrix-signal](https://github.com/mautrix/signal), a Matrix-Signal puppeting bridge. Available as [services.mautrix-signal](#opt-services.mautrix-signal.enable).
+- [inadyn](https://github.com/troglobit/inadyn), a Dynamic DNS client with built-in support for multiple providers. Available as [services.inadyn](#opt-services.inadyn.enable).
 
-- [Anki Sync Server](https://docs.ankiweb.net/sync-server.html), the official sync server built into recent versions of Anki. Available as [services.anki-sync-server](#opt-services.anki-sync-server.enable).
-The pre-existing [services.ankisyncd](#opt-services.ankisyncd.enable) has been marked deprecated and will be dropped after 24.05 due to lack of maintenance of the anki-sync-server software.
+- [intel-gpu-tools](https://drm.pages.freedesktop.org/igt-gpu-tools), tools for development and testing of the Intel DRM driver. Available as [hardware.intel-gpu-tools](#opt-hardware.intel-gpu-tools.enable).
 
-- [mautrix-meta](https://github.com/mautrix/meta), a Matrix <-> Facebook and Matrix <-> Instagram hybrid puppeting/relaybot bridge. Available as services.mautrix-meta
+- [isolate](https://github.com/ioi/isolate), a sandbox for securely executing untrusted programs. Available as [security.isolate](#opt-security.isolate.enable).
 
 - [Jottacloud Command-line Tool](https://docs.jottacloud.com/en/articles/1436834-jottacloud-command-line-tool), a CLI for the [Jottacloud](https://jottacloud.com/) cloud storage provider. Available as [services.jotta-cli](#opt-services.jotta-cli.enable).
 
-- [transfer-sh](https://github.com/dutchcoders/transfer.sh), a tool that supports easy and fast file sharing from the command-line. Available as [services.transfer-sh](#opt-services.transfer-sh.enable).
+- [keto](https://www.ory.sh/keto/), a permission & access control server, the first open source implementation of ["Zanzibar: Google's Consistent, Global Authorization System"](https://research.google/pubs/zanzibar-googles-consistent-global-authorization-system/).
 
-- [FCast Receiver](https://fcast.org), an open-source alternative to Chromecast and AirPlay. Available as [programs.fcast-receiver](#opt-programs.fcast-receiver.enable).
+- [manticoresearch](https://manticoresearch.com), easy to use open source fast database for search. Available as [services.manticore](#opt-services.manticore.enable).
 
-- [MollySocket](https://github.com/mollyim/mollysocket) which allows getting Signal notifications via UnifiedPush.
+- [maubot](https://github.com/maubot/maubot), a plugin-based Matrix bot framework. Available as [services.maubot](#opt-services.maubot.enable).
 
-- [Suwayomi Server](https://github.com/Suwayomi/Suwayomi-Server), a free and open source manga reader server that runs extensions built for [Tachiyomi](https://tachiyomi.org). Available as [services.suwayomi-server](#opt-services.suwayomi-server.enable).
+- [mautrix-meta](https://github.com/mautrix/meta), a Matrix <-> Facebook and Matrix <-> Instagram hybrid puppeting/relaybot bridge. Available as services.mautrix-meta.
 
-- [Netbird](https://netbird.io), an open-source VPN management platform, now has a self-hosted management server. Available as [services.netbird.server](#opt-services.netbird.server.enable).
+- [mautrix-signal](https://github.com/mautrix/signal), a Matrix-Signal puppeting bridge. Available as [services.mautrix-signal](#opt-services.mautrix-signal.enable).
 
-- [ping_exporter](https://github.com/czerwonk/ping_exporter), a Prometheus exporter for ICMP echo requests. Available as [services.prometheus.exporters.ping](#opt-services.prometheus.exporters.ping.enable).
+- [Mealie](https://nightly.mealie.io/), a self-hosted recipe manager and meal planner with a RestAPI backend and a reactive frontend application built in NuxtJS for a pleasant user experience for the whole family. Available as [services.mealie](#opt-services.mealie.enable).
 
-- [Prometheus DNSSEC Exporter](https://github.com/chrj/prometheus-dnssec-exporter), check for validity and expiration in DNSSEC signatures and expose metrics for Prometheus. Available as [services.prometheus.exporters.dnssec](#opt-services.prometheus.exporters.dnssec.enable).
+- [MollySocket](https://github.com/mollyim/mollysocket) which allows getting Signal notifications via UnifiedPush.
 
-- [TigerBeetle](https://tigerbeetle.com/), a distributed financial accounting database designed for mission critical safety and performance. Available as [services.tigerbeetle](#opt-services.tigerbeetle.enable).
+- [microsocks](https://github.com/rofl0r/microsocks), a tiny, portable SOCKS5 server with very moderate resource usage. Available as [services.microsocks](#opt-services.microsocks.enable).
 
-- [go-camo](https://github.com/cactus/go-camo), a secure image proxy server. Available as [services.go-camo](#opt-services.go-camo.enable).
+- [Mihomo](https://github.com/MetaCubeX/mihomo/tree/Alpha), a rule-based proxy in Go. Available as [services.mihomo.enable](#opt-services.mihomo.enable).
 
 - [Monado](https://monado.freedesktop.org/), an open source XR runtime. Available as [services.monado](#opt-services.monado.enable).
 
-- [intel-gpu-tools](https://drm.pages.freedesktop.org/igt-gpu-tools), tools for development and testing of the Intel DRM driver. Available as [hardware.intel-gpu-tools](#opt-hardware.intel-gpu-tools.enable)
+- [Netbird](https://netbird.io), an open-source VPN management platform, now has a self-hosted management server. Available as [services.netbird.server](#opt-services.netbird.server.enable).
 
-- [Pretix](https://pretix.eu/about/en/), an open source ticketing software for events. Available as [services.pretix](#opt-services.pretix.enable).
+- [nh](https://github.com/viperML/nh), yet another Nix CLI helper. Available as [programs.nh](#opt-programs.nh.enable).
 
-- [microsocks](https://github.com/rofl0r/microsocks), a tiny, portable SOCKS5 server with very moderate resource usage. Available as [services.microsocks](#opt-services.microsocks.enable).
+- [oink](https://github.com/rlado/oink), a dynamic DNS client for Porkbun. Available as [services.oink](#opt-services.oink.enable).
 
-- [inadyn](https://github.com/troglobit/inadyn), a Dynamic DNS client with built-in support for multiple providers. Available as [services.inadyn](#opt-services.inadyn.enable).
+- [ollama](https://ollama.ai), server for running large language models locally.
 
-- [Clevis](https://github.com/latchset/clevis), a pluggable framework for automated decryption, used to unlock encrypted devices in initrd. Available as [boot.initrd.clevis.enable](#opt-boot.initrd.clevis.enable).
+- [nextjs-ollama-llm-ui](https://github.com/jakobhoeg/nextjs-ollama-llm-ui), light-weight frontend server to chat with Ollama models through a web app.
 
-- [fritz-exporter](https://github.com/pdreker/fritz_exporter), a Prometheus exporter for extracting metrics from [FRITZ!](https://avm.de/produkte/) devices. Available as [services.prometheus.exporters.fritz](#opt-services.prometheus.exporters.fritz.enable).
+- [ownCloud Infinite Scale Stack](https://owncloud.com/infinite-scale-4-0/), a modern and scalable rewrite of ownCloud.
 
-- [armagetronad](https://wiki.armagetronad.org), a mid-2000s 3D lightcycle game widely played at iD Tech Camps. You can define multiple servers using `services.armagetronad.<server>.enable`.
+- [PhotonVision](https://photonvision.org/), a free, fast, and easy-to-use computer vision solution for the FIRST® Robotics Competition.
 
-- [wyoming-satellite](https://github.com/rhasspy/wyoming-satellite), a voice assistant satellite for Home Assistant using the Wyoming protocol. Available as [services.wyoming.satellite](#opt-services.wyoming.satellite.enable).
+- [ping_exporter](https://github.com/czerwonk/ping_exporter), a Prometheus exporter for ICMP echo requests. Available as [services.prometheus.exporters.ping](#opt-services.prometheus.exporters.ping.enable).
 
-- [TuxClocker](https://github.com/Lurkki14/tuxclocker), a hardware control and monitoring program. Available as [programs.tuxclocker](#opt-programs.tuxclocker.enable).
+- [Pretix](https://pretix.eu/about/en/), an open source ticketing software for events. Available as [services.pretix](#opt-services.pretix.enable).
 
-- [AppImage](https://appimage.org/), a tool to package desktop applications, now has a `binfmt` option to support running AppImages seamlessly on NixOS. Available as [programs.appimage.binfmt](#opt-programs.appimage.binfmt).
+- [pretalx](https://github.com/pretalx/pretalx), a conference planning tool. Available as [services.pretalx](#opt-services.pretalx.enable).
 
-- [nh](https://github.com/viperML/nh), yet another Nix CLI helper. Available as [programs.nh](#opt-programs.nh.enable).
+- [private-gpt](https://github.com/zylon-ai/private-gpt), a service to interact with your documents using the power of LLMs, 100% privately, no data leaks. Available as [services.private-gpt](#opt-services.private-gpt.enable).
 
-- [ALVR](https://github.com/alvr-org/alvr), a VR desktop streamer. Available as [programs.alvr](#opt-programs.alvr.enable)
+- [Prometheus DNSSEC Exporter](https://github.com/chrj/prometheus-dnssec-exporter), check for validity and expiration in DNSSEC signatures and expose metrics for Prometheus. Available as [services.prometheus.exporters.dnssec](#opt-services.prometheus.exporters.dnssec.enable).
 
-- [xdg-terminal-exec](https://github.com/Vladimir-csp/xdg-terminal-exec), the proposed Default Terminal Execution Specification.
+- [prometheus-nats-exporter](https://github.com/nats-io/prometheus-nats-exporter), a Prometheus exporter for NATS. Available as [services.prometheus.exporters.nats](#opt-services.prometheus.exporters.nats.enable).
+
+- [pyLoad](https://pyload.net/), a FOSS download manager written in Python. Available as [services.pyload](#opt-services.pyload.enable).
+
+- [Python Matter Server](https://github.com/home-assistant-libs/python-matter-server), a
+  Matter Controller Server exposing websocket connections for use with other services, notably Home Assistant.
+  Available as [services.matter-server](#opt-services.matter-server.enable).
 
 - [RustDesk](https://rustdesk.com), a full-featured open source remote control alternative for self-hosting and security with minimal configuration. Alternative to TeamViewer. Available as [services.rustdesk-server](#opt-services.rustdesk-server.enable).
 
+- [ryzen-monitor-ng](https://github.com/mann1x/ryzen_monitor_ng), a desktop AMD CPU power monitor and controller, similar to Ryzen Master but for Linux. Available as [programs.ryzen-monitor-ng](#opt-programs.ryzen-monitor-ng.enable).
+
+- [ryzen-smu](https://gitlab.com/leogx9r/ryzen_smu), Linux kernel driver to expose the SMU (System Management Unit) for certain AMD Ryzen Processors. Includes the userspace program `monitor_cpu`. Available at [hardward.cpu.amd.ryzen-smu](#opt-hardware.cpu.amd.ryzen-smu.enable).
+
 - [Scrutiny](https://github.com/AnalogJ/scrutiny), a S.M.A.R.T monitoring tool for hard disks with a web frontend. Available as [services.scrutiny](#opt-services.scrutiny.enable).
 
-- [davis](https://github.com/tchapi/davis), a simple CardDav and CalDav server inspired by Baïkal. Available as [services.davis](#opt-services.davis.enable).
+- [SimpleSAMLphp](https://simplesamlphp.org/), an application written in native PHP that deals with authentication (SQL, .htpasswd, YubiKey, LDAP, PAPI, Radius). Available as [services.simplesamlphp](#opt-services.simplesamlphp).
 
-- [Firefly-iii](https://www.firefly-iii.org), a free and open source personal finance manager. Available as [services.firefly-iii](#opt-services.firefly-iii.enable)
+- `systemd`'s `gateway`, `upload`, and `remote` services, which provide ways of sending journals across the network. Enable using [services.journald.gateway](#opt-services.journald.gateway.enable), [services.journald.upload](#opt-services.journald.upload.enable), and [services.journald.remote](#opt-services.journald.remote.enable).
 
 - [systemd-lock-handler](https://git.sr.ht/~whynothugo/systemd-lock-handler/), a bridge between logind D-Bus events and systemd targets. Available as [services.systemd-lock-handler.enable](#opt-services.systemd-lock-handler.enable).
 
+- [rspamd-trainer](https://gitlab.com/onlime/rspamd-trainer), script triggered by a helper which reads mails from a specific mail inbox and feeds them into rspamd for spam/ham training.
+
+- [Sunshine](https://app.lizardbyte.dev/Sunshine), a self-hosted game stream host for Moonlight. Available as [services.sunshine](#opt-services.sunshine.enable).
+
+- [Suwayomi Server](https://github.com/Suwayomi/Suwayomi-Server), a free and open source manga reader server that runs extensions built for [Tachiyomi](https://tachiyomi.org). Available as [services.suwayomi-server](#opt-services.suwayomi-server.enable).
+
+- [TigerBeetle](https://tigerbeetle.com/), a distributed financial accounting database designed for mission critical safety and performance. Available as [services.tigerbeetle](#opt-services.tigerbeetle.enable).
+
+- [transfer-sh](https://github.com/dutchcoders/transfer.sh), a tool that supports easy and fast file sharing from the command-line. Available as [services.transfer-sh](#opt-services.transfer-sh.enable).
+
+- [TuxClocker](https://github.com/Lurkki14/tuxclocker), a hardware control and monitoring program. Available as [programs.tuxclocker](#opt-programs.tuxclocker.enable).
+
+- [Uni-Sync](https://github.com/EightB1ts/uni-sync), a synchronization tool for Lian Li Uni Controllers. Available as [hardware.uni-sync](#opt-hardware.uni-sync.enable).
+
 - [wastebin](https://github.com/matze/wastebin), a pastebin server written in rust. Available as [services.wastebin](#opt-services.wastebin.enable).
 
-- [Mealie](https://nightly.mealie.io/), a self-hosted recipe manager and meal planner with a RestAPI backend and a reactive frontend application built in NuxtJS for a pleasant user experience for the whole family. Available as [services.mealie](#opt-services.mealie.enable)
+- [watchdogd](https://troglobit.com/projects/watchdogd/), a system and process supervisor using watchdog timers. Available as [services.watchdogd](#opt-services.watchdogd.enable).
 
-- [Sunshine](https://app.lizardbyte.dev/Sunshine), a self-hosted game stream host for Moonlight. Available as [services.sunshine](#opt-services.sunshine.enable).
+- [Workout-tracker](https://github.com/jovandeginste/workout-tracker), a workout tracking web application for personal use.
 
-- [Uni-Sync](https://github.com/EightB1ts/uni-sync), a synchronization tool for Lian Li Uni Controllers. Available as [hardware.uni-sync](#opt-hardware.uni-sync.enable)
+- [wyoming-satellite](https://github.com/rhasspy/wyoming-satellite), a voice assistant satellite for Home Assistant using the Wyoming protocol. Available as [services.wyoming.satellite](#opt-services.wyoming.satellite.enable).
 
-- [prometheus-nats-exporter](https://github.com/nats-io/prometheus-nats-exporter), a Prometheus exporter for NATS. Available as [services.prometheus.exporters.nats](#opt-services.prometheus.exporters.nats.enable).
+- [xdg-terminal-exec](https://github.com/Vladimir-csp/xdg-terminal-exec), the proposed Default Terminal Execution Specification.
 
-- [isolate](https://github.com/ioi/isolate), a sandbox for securely executing untrusted programs. Available as [security.isolate](#opt-security.isolate.enable).
+- [ydotool](https://github.com/ReimuNotMoe/ydotool), a generic command-line automation tool now has a module. Available as [programs.ydotool](#opt-programs.ydotool.enable).
+
+- [your_spotify](https://github.com/Yooooomi/your_spotify), a self hosted Spotify tracking dashboard. Available as [services.your_spotify](#opt-services.your_spotify.enable)
 
 ## Backward Incompatibilities {#sec-release-24.05-incompatibilities}
 
 <!-- To avoid merge conflicts, consider adding your item at an arbitrary place in the list instead. -->
 
-- `k3s`: was updated to version [v1.29](https://github.com/k3s-io/k3s/releases/tag/v1.29.1%2Bk3s2), all previous versions (k3s_1_26, k3s_1_27, k3s_1_28) will be removed. See [changelog and upgrade notes](https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG/CHANGELOG-1.29.md#urgent-upgrade-notes) for more information.
+- `akkoma` now requires explicitly setting the base URL for uploaded media (`settings."Pleroma.Upload".base_url`), as well as for the media proxy if enabled (`settings."Media"`).
+  This is recommended to be a separate (sub)domain to the one Akkoma is hosted at.
+  See [here](https://meta.akkoma.dev/t/akkoma-stable-2024-03-securer-i-barely-know-her/681#explicit-upload-and-media-proxy-domains-5) for more details.
 
-- `himalaya` was updated to v1.0.0-beta.4, which introduces breaking changes. Check out the [release note](https://github.com/soywod/himalaya/releases/tag/v1.0.0-beta.4) for details.
+- `appimageTools.wrapAppImage` now creates the binary at `$out/bin/${pname}` rather than `$out/bin/${pname}-${version}`, which will break downstream workarounds.
 
-- `security.pam.enableSSHAgentAuth` was replaced by the `sshAgentAuth` attrset, and **only**
-  `authorized_keys` files listed in [`sshAgentAuth.authorizedKeysFiles`] are trusted,
-  defaulting to `/etc/ssh/authorized_keys.d/%u`.
-  ::: {.warning}
-  Users of {manpage}`pam_ssh_agent_auth(8)` must take care that the pubkeys they use (for instance with `sudo`)
-  are listed in [`sshAgentAuth.authorizedKeysFiles`].
-  :::
-  ::: {.note}
-  Previously, all `services.openssh.authorizedKeysFiles` were trusted, including `~/.ssh/authorized_keys`,
-  which results in an **insecure** configuration; see [#31611](https://github.com/NixOS/nixpkgs/issues/31611).
-  :::
+- `azure-cli` now has extension support. For example, to install the `aks-preview` extension, use
 
-[`sshAgentAuth.authorizedKeysFiles`]: #opt-security.pam.sshAgentAuth.authorizedKeysFiles
+  ```nix
+  environment.systemPackages = [
+    (azure-cli.withExtensions [ azure-cli.extensions.aks-preview ])
+  ];
+  ```
+  To make the `azure-cli` immutable and prevent clashes in case `azure-cli` is also installed via other package managers, some configuration files were moved into the derivation.
+  This can be disabled by overriding `withImmutableConfig = false` when building `azure-cli`.
 
-- The `power.ups` module now generates `upsd.conf`, `upsd.users` and `upsmon.conf` automatically from a set of new configuration options. This breaks compatibility with existing `power.ups` setups where these files were created manually. Back up these files before upgrading NixOS.
+- `boot.supportedFilesystems` and `boot.initrd.supportedFilesystems` are now attribute sets instead of lists. Assignment from lists as done previously is still supported, but checking whether a filesystem is enabled must now by done using `supportedFilesystems.fs or false` instead of using `lib.elem "fs" supportedFilesystems` as was done previously.
 
-- `programs.nix-ld.libraries` no longer sets `baseLibraries` via the option's default but in config and now merges any additional libraries with the default ones.
-  This means that `lib.mkForce` must be used to clear the list of default libraries.
+- `buildGoModule` now throws an error when `vendorHash` is not specified. `vendorSha256`, deprecated in Nixpkgs 23.11, is now ignored and is no longer a `vendorHash` alias.
+
+- `chromium` and `ungoogled-chromium` had a long-standing issue regarding Widevine DRM handling in nixpkgs fixed.
+  `chromium` now no longer automatically downloads Widevine when encountering DRM protected content.
+  To be able to play DRM protected content in `chromium` now, you have to explicitly opt-in as originally intended using `chromium.override { enableWideVine = true; }`.
+  This override was added almost 10 years ago.
+
+- `craftos-pc` package has been updated to v2.8, which includes [breaking changes](https://github.com/MCJack123/craftos2/releases/tag/v2.8).
+  - Files are now handled in binary mode; this could break programs with embedded UTF-8 characters.
+  - The ROM was updated to match ComputerCraft version v1.109.2.
+  - The bundled Lua was updated to Lua v5.2, which includes breaking changes. See the [Lua manual](https://www.lua.org/manual/5.2/manual.html#8) for more information.
+  - The WebSocket API [was rewritten](https://github.com/MCJack123/craftos2/issues/337), which introduced breaking changes.
+
+- `cryptsetup` has been upgraded from 2.6.1 to 2.7.0. Cryptsetup is a critical component enabling LUKS-based (but not only) full disk encryption.
+  Take the time to review [the release notes](https://gitlab.com/cryptsetup/cryptsetup/-/raw/v2.7.0/docs/v2.7.0-ReleaseNotes).
+  One of the highlights is that it is now possible to use hardware OPAL-based encryption of your disk with `cryptsetup`. It has a lot of caveats, see the above notes for the full details.
+
+- `crystal` package has been updated to 1.11.x, which has some breaking changes.
+  Refer to crystal's changelog for more information. ([v1.10](https://github.com/crystal-lang/crystal/blob/master/CHANGELOG.md#1100-2023-10-09), [v1.11](https://github.com/crystal-lang/crystal/blob/master/CHANGELOG.md#1110-2024-01-08))
+
+- `cudaPackages` package scope has been updated to `cudaPackages_12`.
 
 - `cudaPackages.autoAddOpenGLRunpathHook` and `cudaPackages.autoAddDriverRunpath` have been deprecated for `pkgs.autoAddDriverRunpath`. Functionality has not changed, but the setuphook has been renamed and moved to the top-level package scope.
 
-- `cudaPackages.autoFixElfFiles` has been deprecated for `pkgs.autoFixElfFiles`. Functionality has not changed, but the setuphook has been renamed and moved to the top-level package scope.
+- `cudaPackages.cudatoolkit` has been deprecated and replaced with a
+  symlink-based wrapper for the splayed redistributable CUDA packages. The
+  wrapper only includes tools and libraries necessary to build common packages
+  such as tensorflow. The original runfile-based `cudatoolkit` is still
+  available as `cudatoolkit-legacy-runfile`.
 
-- `appimageTools.wrapAppImage` now creates the binary at `$out/bin/${pname}` rather than `$out/bin/${pname}-${version}`, which will break downstream workarounds.
+- `cudaPackages.nsight_systems` now has most vendored third party-libraries removed, though we now only ship it for `cudaPackages_11_8` and later, due to outdated dependencies. Users comfortable with the vendored dependencies may use `overrideAttrs` to amend the `postPatch` phase and the `meta.broken` correspondingly. Alternatively, one could package the deprecated `boost170` locally, as required for `cudaPackages_11_4.nsight_systems`.
 
-- `pdns` was updated to version [v4.9.x](https://doc.powerdns.com/authoritative/changelog/4.9.html), which introduces breaking changes. Check out the [Upgrade Notes](https://doc.powerdns.com/authoritative/upgrading.html#to-4-9-0) for details.
+- `cudaPackages.autoFixElfFiles` has been deprecated for `pkgs.autoFixElfFiles`. Functionality has not changed, but the setuphook has been renamed and moved to the top-level package scope.
 
-- `unrar` was updated to v7. See [changelog](https://www.rarlab.com/unrar7notes.htm) for more information.
+- `davfs2`'s `services.davfs2.extraConfig` setting has been deprecated and converted to the free-form type option named `services.davfs2.settings` according to RFC42.
 
-- `git-town` was updated from version 11 to 13. See the [changelog](https://github.com/git-town/git-town/blob/main/CHANGELOG.md#1300-2024-03-22) for breaking changes.
+- `dwarf-fortress` has been updated to version 50, and its derivations continue to menace with spikes of Nix and bash [TODO what does this mean?]. Version 50 is identical to the version on Steam, but without the paid elements like tilepacks.
+  dfhack and Dwarf Therapist still work, and older versions are still packaged in case you'd like to roll back. Note that DF 50 saves will not be compatible with DF 0.47 and earlier.
+  See [Bay 12 Games](http://www.bay12games.com/dwarves/) for more details on what's new in Dwarf Fortress.
 
-- `k9s` was updated to v0.31. There have been various breaking changes in the config file format,
-  check out the changelog of [v0.29](https://github.com/derailed/k9s/releases/tag/v0.29.0),
-  [v0.30](https://github.com/derailed/k9s/releases/tag/v0.30.0) and
-  [v0.31](https://github.com/derailed/k9s/releases/tag/v0.31.0) for details. It is recommended
-  to back up your current configuration and let k9s recreate the new base configuration.
+  - Running an earlier version can be achieved through an override: `dwarf-fortress-packages.dwarf-fortress-full.override { dfVersion = "0.47.5"; }`
 
-- NixOS AMIs are now uploaded regularly to a new AWS Account.
-  Instructions on how to use them can be found on <https://nixos.github.io/amis>.
-  We are working on integration the data into the NixOS homepage.
-  The list in `nixos/modules/virtualisation/amazon-ec2-amis.nix` will stop
-  being updated and will be removed in the future.
+  - Ruby plugin support has been disabled in DFHack. Many of the Ruby plugins have been converted to Lua, and support was removed upstream due to frequent crashes.
 
-- The option `services.postgresql.ensureUsers._.ensurePermissions` has been removed as it is
-  not declarative and is broken with newer postgresql versions. Consider using
-  [](#opt-services.postgresql.ensureUsers._.ensureDBOwnership)
-  instead or a tool that is more suited for managing the data inside a postgresql database.
+- `erlang-ls` package no longer ships the `els_dap` binary as of v0.51.0.
 
-- `idris2` was updated to v0.7.0. This version introduces breaking changes. Check out the [changelog](https://github.com/idris-lang/Idris2/blob/v0.7.0/CHANGELOG.md#v070) for details.
+- `erlang_node_short_name`, `erlang_node_name`, `port` and `options` configuration parameters are gone, and have been replaced with an `environment` parameter.
+    Use the appropriate [environment variables](https://hexdocs.pm/livebook/readme.html#environment-variables) inside `environment` to configure the service instead.
 
-- `nvtop` family of packages was reorganized into nested attrset. `nvtop` has been renamed to `nvtopPackages.full`, and all `nvtop-{amd,nvidia,intel,msm}` packages are now named as `nvtopPackages.{amd,nvidia,intel,msm}`
+- `firefox-devedition`, `firefox-beta`, `firefox-esr` executable file names for now match their package names, which is consistent with the `firefox-*-bin` packages. The desktop entries are also updated so that you can have multiple editions of firefox in your app launcher.
 
-- `neo4j` has been updated to version 5. You may want to read the [release notes for Neo4j 5](https://neo4j.com/release-notes/database/neo4j-5/).
+- `gauge` now supports installing plugins using nix. For the old imperative approach, switch to `gauge-unwrapped`.
+  You can load plugins from an existing gauge manifest file using `gauge.fromManifest ./path/to/manifest.json` or
+  specify plugins in nix using `gauge.withPlugins (p: with p; [ js html-report xml-report ])`.
 
-- `services.neo4j.allowUpgrade` was removed and no longer has any effect. Neo4j 5 supports automatic rolling upgrades.
+- `gitea` has been updated to 1.21, which introduces several breaking changes, including:
+  - Custom themes and other assets that were previously stored in `custom/public/*` now belong in `custom/public/assets/*`
+  - New instances of Gitea using MySQL now ignore the `[database].CHARSET` config option and always use the `utf8mb4` charset, existing instances should migrate via the `gitea doctor convert` CLI command.
 
-- `unifiLTS`, `unifi5` and `unifi6` have been removed, as they require MongoDB versions which are end-of-life. All these versions can be upgraded to `unifi7` directly.
+- `git-town` was updated from version 11 to 13. See the [changelog](https://github.com/git-town/git-town/blob/main/CHANGELOG.md#1300-2024-03-22) for breaking changes.
 
-- `mongodb-4_4` has been removed as it has reached end of life. Consequently, `unifi7` and `unifi8` now use MongoDB 5.0 by default.
+- `gonic` has been updated to v0.16.4. Config now requires `playlists-path` to be set. See the rest of the [v0.16.0 release notes](https://github.com/sentriz/gonic/releases/tag/v0.16.0) for more details.
 
-- `mongodb-5_0` and newer requires a cpu with the avx instruction set to run.
+- `go-ethereum` has been updated to v1.14.3. Geth v1.14.0 introduced a brand new live-tracing feature,
+  which required a number of breaking internal API changes. If you had your own native tracers implemented before this change,
+  the [changelog](https://github.com/ethereum/go-ethereum/blob/master/core/tracing/CHANGELOG.md) contains the necessary steps needed to update your old code for the new APIs.
+  Geth v1.14.0 drops support for running pre-merge networks ([#29169](https://github.com/ethereum/go-ethereum/pull/29169)).
+  It also stops automatically constructing the pending block ([#28623](https://github.com/ethereum/go-ethereum/pull/28623)),
+  removes support for filtering pending logs, switched to using Go v1.22 by default (#28946), which means we've dropped support for Go v1.20.
+  See [the 1.14.0 release notes](https://github.com/ethereum/go-ethereum/releases/tag/v1.14.0) for more details.
 
-- `nitter` requires a `guest_accounts.jsonl` to be provided as a path or loaded into the default location at `/var/lib/nitter/guest_accounts.jsonl`. See [Guest Account Branch Deployment](https://github.com/zedeus/nitter/wiki/Guest-Account-Branch-Deployment) for details.
+- `grafana-loki` has been updated to 3.0.0, which includes [breaking changes](https://github.com/grafana/loki/releases/tag/v3.0.0).
 
-- `boot.supportedFilesystems` and `boot.initrd.supportedFilesystems` are now attribute sets instead of lists. Assignment from lists as done previously is still supported, but checking whether a filesystem is enabled must now by done using `supportedFilesystems.fs or false` instead of using `lib.elem "fs" supportedFilesystems` as was done previously.
+- `gtest` package has been updated past v1.13.0, which requires C++14 or higher.
 
-- `services.aria2.rpcSecret` has been replaced with `services.aria2.rpcSecretFile`.
-  This was done so that secrets aren't stored in the world-readable nix store.
-  To migrate, you will have to create a file with the same exact string, and change
-  your module options to point to that file. For example, `services.aria2.rpcSecret =
-  "mysecret"` becomes `services.aria2.rpcSecretFile = "/path/to/secret_file"`
-  where the file `secret_file` contains the string `mysecret`.
+- `hare` may now be cross-compiled. For that to work, however, `haredoc` needed to stop being built together with it. Thus, the latter is now its own package with the name of `haredoc`.
 
-- The `system.forbiddenDependenciesRegex` option has been renamed to `system.forbiddenDependenciesRegexes` and now has the type of `listOf string` instead of `string` to accept multiple regexes.
+- `himalaya` has been updated to v1.0.0-beta.4, which introduces breaking changes. Check out the [release note](https://github.com/soywod/himalaya/releases/tag/v1.0.0-beta.4) for details.
 
-- `openssh`, `openssh_hpn` and `openssh_gssapi` are now compiled without support for the DSA signature algorithm as it is being deprecated upstream. Users still relying on DSA keys should consider upgrading
-  to another signature algorithm. However, for the time being it is possible to restore DSA key support using `override` to set `dsaKeysSupport = true`.
+- `halloy` has been updated to 2024.5, which introduced a breaking change by switching the config format from YAML to TOML. See https://github.com/squidowl/halloy/releases/tag/2024.5 for details.
 
-- `buildGoModule` now throws an error when `vendorHash` is not specified. `vendorSha256`, deprecated in Nixpkgs 23.11, is now ignored and is no longer a `vendorHash` alias.
+- `hvm` was updated to version 2.
 
-- `services.invidious.settings.db.user`, the default database username has changed from `kemal` to `invidious`. Setups involving an externally-provisioned database (i.e. `services.invidious.database.createLocally == false`) should adjust their configuration accordingly. The old `kemal` user will not be removed automatically even when the database is provisioned automatically.(https://github.com/NixOS/nixpkgs/pull/265857)
+- `icu` no longer includes `install-sh` and `mkinstalldirs` in the shared folder.
 
-- `writeReferencesToFile` is deprecated in favour of the new trivial build helper `writeClosure`. The latter accepts a list of paths and has an unambiguous name and cleaner implementation.
+- `idris2` was updated to v0.7.0. This version introduces breaking changes. Check out the [changelog](https://github.com/idris-lang/Idris2/blob/v0.7.0/CHANGELOG.md#v070) for details.
 
 - `inetutils` now has a lower priority to avoid shadowing the commonly used `util-linux`. If one wishes to restore the default priority, simply use `lib.setPrio 5 inetutils` or override with `meta.priority = 5`.
 
-- `paperless`' `services.paperless.extraConfig` setting has been removed and converted to the free-form type and option named `services.paperless.settings`.
+- `jdt-language-server` package now uses upstream's provided python wrapper instead of our own custom wrapper. This results in the following breaking and notable changes:
+
+  - The main binary for the package is now named `jdtls` instead of `jdt-language-server`, equivalent to what most editors expect the binary to be named.
 
-- `davfs2`' `services.davfs2.extraConfig` setting has been deprecated and converted to the free-form type option named `services.davfs2.settings` according to RFC42.
+  - JVM arguments should now be provided with the `--jvm-arg` flag instead of setting `JAVA_OPTS`.
 
-- `services.homepage-dashboard` now takes its configuration using native Nix expressions, rather than dumping templated configurations into `/var/lib/homepage-dashboard` where they were previously managed manually. There are now new options which allow the configuration of bookmarks, services, widgets and custom CSS/JS natively in Nix.
+  - The `-data` path is no longer required to run the package, and will be set to point to a folder in `$TMP` if missing.
 
-- `hare` may now be cross-compiled. For that to work, however, `haredoc` needed to stop being built together with it. Thus, the latter is now its own package with the name of `haredoc`.
+- `julia` environments can now be built with arbitrary packages from the ecosystem using the `.withPackages` function. For example: `julia.withPackages ["Plots"]`.
 
-- `network-interfaces.target` system target was removed as it has been deprecated for a long time. Use `network.target` instead.
+- `k3s` has been updated to version [v1.30](https://github.com/k3s-io/k3s/releases/tag/v1.30.0%2Bk3s1), previous supported versions are available under release specific names (e.g. k3s_1_27, k3s_1_28, and k3s_1_29) and present to help you migrate to the latest supported version. See [changelog and upgrade notes](https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG/CHANGELOG-1.30.md#changelog-since-v1290) for more information.
 
-- `services.redis.vmOverCommit` now defaults to `true` and no longer enforces Transparent Hugepages (THP) to be disabled. Redis only works with THP configured to `madvise` which is the kernel's default.
+- `k9s` was updated to v0.31. There have been various breaking changes in the config file format,
+  check out the changelog of [v0.29](https://github.com/derailed/k9s/releases/tag/v0.29.0),
+  [v0.30](https://github.com/derailed/k9s/releases/tag/v0.30.0) and
+  [v0.31](https://github.com/derailed/k9s/releases/tag/v0.31.0) for details. It is recommended
+  to back up your current configuration and let k9s recreate the new base configuration.
 
-- `azure-cli` now has extension support. For example, to install the `aks-preview` extension, use
+- `kanata` package has been updated to v1.6.1, which includes breaking changes.  Check out the changelog of [v1.5.0](https://github.com/jtroo/kanata/releases/tag/v1.5.0) and [v1.6.0](https://github.com/jtroo/kanata/releases/tag/v1.6.0) for details.
 
-  ```nix
-  environment.systemPackages = [
-    (azure-cli.withExtensions [ azure-cli.extensions.aks-preview ])
-  ];
-  ```
-  To make the `azure-cli` immutable and prevent clashes in case `azure-cli` is also installed via other package managers, some configuration files were moved into the derivation.
-  This can be disabled by overriding `withImmutableConfig = false` when building `azure-cli`.
+- `linuxPackages_testing_bcachefs` is now fully deprecated by `linuxPackages_latest`, and is therefore no longer available.
 
-- `services.frp.settings` now generates the frp configuration file in TOML format as [recommended by upstream](https://github.com/fatedier/frp#configuration-files), instead of the legacy INI format. This has also introduced other changes in the configuration file structure and options.
-  - The `settings.common` section in the configuration is no longer valid and all the options form inside it now goes directly under `settings`.
-  - The `_` separating words in the configuration options is removed so the options are now in camel case. For example: `server_addr` becomes `serverAddr`, `server_port` becomes `serverPort` etc.
-  - Proxies are now defined with a new option `settings.proxies` which takes a list of proxies.
-  - Consult the [upstream documentation](https://github.com/fatedier/frp#example-usage) for more details on the changes.
+- `livebook` package is now built as a `mix release` instead of an `escript`.
+  This means that configuration now has to be done using [environment variables](https://hexdocs.pm/livebook/readme.html#environment-variables) instead of command line arguments.
+  This has the further implication that the `livebook` service configuration has changed.
+
+- `lua` interpreters default LUA_PATH and LUA_CPATH are not overriden by nixpkgs
+  anymore, we patch LUA_ROOT instead which is more respectful to upstream.
+
+- `luarocks-packages-updater`'s .csv format used to define lua packages to be updated, has changed: `src` (URL of a git repository) has now become `rockspec` (URL of a rockspec) to remove ambiguity regarding which rockspec to use and simplify implementation.
 
 - `mkosi` was updated to v22. Parts of the user interface have changed. Consult the
   release notes of [v19](https://github.com/systemd/mkosi/releases/tag/v19),
@@ -337,47 +353,28 @@ The pre-existing [services.ankisyncd](#opt-services.ankisyncd.enable) has been m
   [v21](https://github.com/systemd/mkosi/releases/tag/v21) and
   [v22](https://github.com/systemd/mkosi/releases/tag/v22) for a list of changes.
 
-- `gonic` has been updated to v0.16.4. Config now requires `playlists-path` to be set. See the rest of the [v0.16.0 release notes](https://github.com/sentriz/gonic/releases/tag/v0.16.0) for more details.
-
-- `services.vikunja` systemd service now uses `vikunja` as dynamic user instead of `vikunja-api`. Database users might need to be changed.
-
-- `services.vikunja.setupNginx` setting has been removed. Users now need to setup the webserver configuration on their own with a proxy pass to the vikunja service.
-
-- `services.vmagent` module deprecates `dataDir`, `group` and `user` setting in favor of systemd provided CacheDirectory and DynamicUser.
-
-- `services.vmagent.remoteWriteUrl` setting has been renamed to `services.vmagent.remoteWrite.url` and now defaults to `null`.
-
-- `woodpecker-*` packages have been updated to v2 which includes [breaking changes](https://woodpecker-ci.org/docs/next/migrations#200).
+- `mongodb-4_4` has been removed as it has reached end of life. Consequently, `unifi7` and `unifi8` now use MongoDB 5.0 by default.
 
-- `services.nginx` will no longer advertise HTTP/3 availability automatically. This must now be manually added, preferably to each location block.
-  Example:
+- `mongodb-5_0` and newer requires a cpu with the avx instruction set to run.
 
-  ```nix
-  {
-    locations."/".extraConfig = ''
-      add_header Alt-Svc 'h3=":$server_port"; ma=86400';
-    '';
-    locations."^~ /assets/".extraConfig = ''
-      add_header Alt-Svc 'h3=":$server_port"; ma=86400';
-    '';
-  }
-  ```
+- `neo4j` has been updated to version 5. You may want to read the [release notes for Neo4j 5](https://neo4j.com/release-notes/database/neo4j-5/).
 
-- `optparse-bash` is now dropped due to upstream inactivity. Alternatives available in Nixpkgs include [`argc`](https://github.com/sigoden/argc), [`argbash`](https://github.com/matejak/argbash), [`bashly`](https://github.com/DannyBen/bashly) and [`gum`](https://github.com/charmbracelet/gum), to name a few.
+- `netbox` was updated to v3.7. `services.netbox.package` still defaults
+  to v3.6 if `stateVersion` is earlier than 24.05. Refer to upstream's breaking
+  changes [for
+  v3.7.0](https://github.com/netbox-community/netbox/releases/tag/v3.7.0) and
+  upgrade NetBox by changing `services.netbox.package`. Database migrations
+  will be run automatically.
 
-- `kanata` package has been updated to v1.6.1, which includes breaking changes.  Check out the changelog of [v1.5.0](https://github.com/jtroo/kanata/releases/tag/v1.5.0) and [v1.6.0](https://github.com/jtroo/kanata/releases/tag/v1.6.0) for details.
+- `network-interfaces.target` system target was removed as it has been deprecated for a long time. Use `network.target` instead.
 
-- `craftos-pc` package has been updated to v2.8, which includes [breaking changes](https://github.com/MCJack123/craftos2/releases/tag/v2.8).
-  - Files are now handled in binary mode; this could break programs with embedded UTF-8 characters.
-  - The ROM was updated to match ComputerCraft version v1.109.2.
-  - The bundled Lua was updated to Lua v5.2, which includes breaking changes. See the [Lua manual](https://www.lua.org/manual/5.2/manual.html#8) for more information.
-  - The WebSocket API [was rewritten](https://github.com/MCJack123/craftos2/issues/337), which introduced breaking changes.
+- `networking.iproute2.enable` now does not set `environment.etc."iproute2/rt_tables".text`.
 
-- `gtest` package has been updated past v1.13.0, which requires C++14 or higher.
+  Setting `environment.etc."iproute2/{CONFIG_FILE_NAME}".text` will override the whole configuration file instead of appending it to the upstream configuration file.
 
-- Nextcloud 26 has been removed since it's not maintained anymore by upstream.
+  `CONFIG_FILE_NAME` includes `bpf_pinning`, `ematch_map`, `group`, `nl_protos`, `rt_dsfield`, `rt_protos`, `rt_realms`, `rt_scopes`, and `rt_tables`.
 
-- The latest available version of Nextcloud is v29 (available as `pkgs.nextcloud29`). The installation logic is as follows:
+- `nextcloud26` has been removed since it's not maintained anymore by upstream. The latest available version of Nextcloud is now v29 (available as `pkgs.nextcloud29`). The installation logic is as follows:
   - If [`services.nextcloud.package`](#opt-services.nextcloud.package) is specified explicitly, this package will be installed (**recommended**)
   - If [`system.stateVersion`](#opt-system.stateVersion) is >=24.05, `pkgs.nextcloud29` will be installed by default.
   - If [`system.stateVersion`](#opt-system.stateVersion) is >=23.11, `pkgs.nextcloud27` will be installed by default.
@@ -385,28 +382,82 @@ The pre-existing [services.ankisyncd](#opt-services.ankisyncd.enable) has been m
   - Known warnings after the upgrade are documented in [](#module-services-nextcloud-known-warnings) from now on.
   - The "Photos" app only displays Media from inside the `Photos` directory. This can be changed manually in the "Photos" tab below "Photos settings".
 
-- The vendored third party libraries have been mostly removed from `cudaPackages.nsight_systems`, which we now only ship for `cudaPackages_11_8` and later due to outdated dependencies. Users comfortable with the vendored dependencies may use `overrideAttrs` to amend the `postPatch` phase and the `meta.broken` correspondingly. Alternatively, one could package the deprecated `boost170` locally, as required for `cudaPackages_11_4.nsight_systems`.
+- `nitter` requires a `guest_accounts.jsonl` to be provided as a path or loaded into the default location at `/var/lib/nitter/guest_accounts.jsonl`. See [Guest Account Branch Deployment](https://github.com/zedeus/nitter/wiki/Guest-Account-Branch-Deployment) for details.
 
-- `cudaPackages` package scope has been updated to `cudaPackages_12`.
+- `nixVersions.unstable` was removed. Instead the following attributes are provided:
+  - `nixVersions.git` which tracks the latest Nix master and is roughly updated once a week. This is intended to enable people to easily test unreleased changes of Nix to catch regressions earlier.
+  - `nixVersions.latest` which points to the latest Nix version packaged in nixpkgs.
 
-- The deprecated `cudaPackages.cudatoolkit` has been replaced with a
-  symlink-based wrapper for the splayed redistributable CUDA packages. The
-  wrapper only includes tools and libraries necessary to build common packages
-  like e.g. tensorflow. The original runfile-based `cudatoolkit` is still
-  available as `cudatoolkit-legacy-runfile`.
+- `nomad` has been updated - note that HashiCorp recommends updating one minor version at a time. Please check [their upgrade guide](https://developer.hashicorp.com/nomad/docs/upgrade) for information on safely updating clusters and potential breaking changes.
 
-- `halloy` package was updated past 2024.5 which introduced a breaking change by switching the config format from YAML to TOML. See https://github.com/squidowl/halloy/releases/tag/2024.5 for details.
+  - `nomad` is now Nomad 1.7.x.
 
-- The `wpaperd` package has a breaking change moving to 1.0.1, previous version 0.3.0 had 2 different configuration files, one for wpaperd and one for the wallpapers. Remove the former and move the latter (`wallpaper.toml`) to `config.toml`.
+  - `nomad_1_4` has been removed, as it is now unsupported upstream.
 
-- Ada packages (libraries and tools) have been moved into the `gnatPackages` scope. `gnatPackages` uses the default GNAT compiler, `gnat12Packages` and `gnat13Packages` use the respective matching compiler version.
+- `nvtop` family of packages was reorganized into a nested attrset. `nvtop` has been renamed to `nvtopPackages.full`, and all `nvtop-{amd,nvidia,intel,msm}` packages are renamed to `nvtopPackages.{amd,nvidia,intel,msm}`.
 
-- Paths provided as `restartTriggers` and `reloadTriggers` for systemd units will now be copied into the nix store to make the behavior consistent.
-  Previously, `restartTriggers = [ ./config.txt ]`, if defined in a flake, would trigger a restart when any part of the flake changed; and if not defined in a flake, would never trigger a restart even if the contents of `config.txt` changed.
+- `openssh`, `openssh_hpn` and `openssh_gssapi` are now compiled without support for the DSA signature algorithm as it is being deprecated upstream. Users still relying on DSA keys should consider upgrading
+  to another signature algorithm. However, for the time being it is possible to restore DSA key support using `override` to set `dsaKeysSupport = true`.
 
-- `spark2014` has been renamed to `gnatprove`. A version of `gnatprove` matching different GNAT versions is available from the different `gnatPackages` sets.
+- `optparse-bash` is now dropped due to upstream inactivity. Alternatives available in Nixpkgs include [`argc`](https://github.com/sigoden/argc), [`argbash`](https://github.com/matejak/argbash), [`bashly`](https://github.com/DannyBen/bashly) and [`gum`](https://github.com/charmbracelet/gum), to name a few.
+
+- `paperless`' `services.paperless.extraConfig` setting has been removed and converted to the free-form type and option named `services.paperless.settings`.
+
+- `pdns` was updated to version [v4.9.x](https://doc.powerdns.com/authoritative/changelog/4.9.html), which introduces breaking changes. Check out the [Upgrade Notes](https://doc.powerdns.com/authoritative/upgrading.html#to-4-9-0) for details.
+
+- `percona-server` now follows [the same two-fold release cycle](https://www.percona.com/blog/lts-and-innovation-releases-for-percona-server-for-mysql/) as Oracle MySQL and provides a *Long-Term-Support (LTS)* in parallel with a continuous-delivery *Innovation* release. `percona-server` defaults to `percona-server_lts`, will be backed by the same release branch throughout the lifetime of this stable NixOS release, and is still available under the versioned attribute `percona-server_8_0`.
+  The `percona-server_innovation` releases however have support periods shorter than the lifetime of this NixOS release and will continuously be updated to newer Percona releases. Note that Oracle considers the *Innovation* releases to be production-grade, but each release might include backwards-incompatible changes, even in its on-disk format.
+  The same release scheme is applied to the supporting `percona-xtrabackup` tool as well.
+
+- `pipewire` and `wireplumber` modules have removed support for using
+`environment.etc."pipewire/..."` and `environment.etc."wireplumber/..."`.
+Use `services.pipewire.extraConfig` or `services.pipewire.configPackages` for PipeWire and
+`services.pipewire.wireplumber.configPackages` for WirePlumber instead."
+
+- `power.ups` now generates `upsd.conf`, `upsd.users` and `upsmon.conf` automatically from a set of new configuration options. This breaks compatibility with existing `power.ups` setups where these files were created manually. Back up these files before upgrading NixOS.
+
+- `programs.nix-ld.libraries` no longer sets `baseLibraries` via the option's default but in config and now merges any additional libraries with the default ones.
+  This means that `lib.mkForce` must be used to clear the list of default libraries.
+
+- `screen`'s module has been cleaned, and will now require you to set `programs.screen.enable` in order to populate `screenrc` and add the program to the environment.
+
+- `security.pam.enableSSHAgentAuth` now requires `services.openssh.authorizedKeysFiles` to be non-empty,
+  which is the case when `services.openssh.enable` is true. Previously, `pam_ssh_agent_auth` silently failed to work.
+
+- `security.pam.enableSSHAgentAuth` was replaced by the `sshAgentAuth` attrset, and **only**
+  `authorized_keys` files listed in [`sshAgentAuth.authorizedKeysFiles`] are trusted,
+  defaulting to `/etc/ssh/authorized_keys.d/%u`.
+  ::: {.warning}
+  Users of {manpage}`pam_ssh_agent_auth(8)` must take care that the pubkeys they use (for instance with `sudo`)
+  are listed in [`sshAgentAuth.authorizedKeysFiles`].
+  :::
+  ::: {.note}
+  Previously, all `services.openssh.authorizedKeysFiles` were trusted, including `~/.ssh/authorized_keys`,
+  which results in an **insecure** configuration; see [#31611](https://github.com/NixOS/nixpkgs/issues/31611).
+  :::
+
+[`sshAgentAuth.authorizedKeysFiles`]: #opt-security.pam.sshAgentAuth.authorizedKeysFiles
+
+- `services.archisteamfarm` no longer uses the abbreviation `asf` for its state directory (`/var/lib/asf`), user and group (both `asf`). Instead the long name `archisteamfarm` is used.
+  Configurations with `system.stateVersion` 23.11 or earlier, default to the old stateDirectory until the 24.11 release and must either set the option explicitly or move the data to the new directory.
 
-- `services.resolved.fallbackDns` can now be used to disable the upstream fallback servers entirely by setting it to an empty list. To get the previous behaviour of the upstream defaults set it to null, the new default, instead.
+- `frr` was updated to 10.0, which introduces the default of `enforce-first-as` for BGP. Please disable again if needed.
+
+- `services.aria2.rpcSecret` has been replaced with `services.aria2.rpcSecretFile`.
+  This was done so that secrets aren't stored in the world-readable nix store.
+  To migrate, you will have to create a file with the same exact string, and change
+  your module options to point to that file. For example, `services.aria2.rpcSecret =
+  "mysecret"` becomes `services.aria2.rpcSecretFile = "/path/to/secret_file"`
+  where the file `secret_file` contains the string `mysecret`.
+
+- `services.avahi.nssmdns` was split into `services.avahi.nssmdns4` and `services.avahi.nssmdns6` which enable the mDNS NSS switches for IPv4 and IPv6 respectively.
+  Since most mDNS responders only register IPv4 addresses, most users want to keep the IPv6 support disabled to avoid long timeouts.
+
+- `services.frp.settings` now generates the frp configuration file in TOML format as [recommended by upstream](https://github.com/fatedier/frp#configuration-files), instead of the legacy INI format. This has also introduced other changes in the configuration file structure and options:
+  - The `settings.common` section in the configuration is no longer valid and all the options form inside it now go directly under `settings`.
+  - Configuration option names have been changed from snake_case to camelCase. For example: `server_addr` becomes `serverAddr`, `server_port` becomes `serverPort` etc.
+  - Proxies are now defined with a new option `settings.proxies` which takes a list of proxies.
+  - Consult the [upstream documentation](https://github.com/fatedier/frp#example-usage) for more details on the changes.
 
 - `services.hledger-web.capabilities` options has been replaced by a new option `services.hledger-web.allow`.
 
@@ -415,261 +466,242 @@ The pre-existing [services.ankisyncd](#opt-services.ankisyncd.enable) has been m
   - `allow = "edit"` means `capabilities = { view = true; add = true; edit = true }`;
   - `allow = "sandstorm"` reads permissions from the `X-Sandstorm-Permissions` request header.
 
-- `xxd` has been moved from `vim` default output to its own output to reduce closure size. The canonical way to reference it across all platforms is `unixtools.xxd`.
-
-- `stalwart-mail` package has been updated to v0.5.3, which includes [breaking changes](https://github.com/stalwartlabs/mail-server/blob/v0.5.3/UPGRADING.md).
+- `services.homepage-dashboard` now takes its configuration using native Nix expressions, rather than dumping templated configurations into `/var/lib/homepage-dashboard` where they were previously managed manually. There are now new options which allow the configuration of bookmarks, services, widgets and custom CSS/JS natively in Nix.
 
-- `services.zope2` has been removed as `zope2` is unmaintained and was relying on Python2.
+- `services.invidious.settings.db.user`, the default database username has changed from `kemal` to `invidious`. Setups involving an externally-provisioned database (i.e. `services.invidious.database.createLocally == false`) should adjust their configuration accordingly. The old `kemal` user will not be removed automatically even when the database is provisioned automatically.(https://github.com/NixOS/nixpkgs/pull/265857).
 
 - `services.oauth2_proxy` was renamed to `services.oauth2-proxy`. Also the corresponding service, user and group were renamed.
 
-- `services.avahi.nssmdns` got split into `services.avahi.nssmdns4` and `services.avahi.nssmdns6` which enable the mDNS NSS switch for IPv4 and IPv6 respectively.
-  Since most mDNS responders only register IPv4 addresses, most users want to keep the IPv6 support disabled to avoid long timeouts.
-
-- A warning has been added for services that are
-  `after = [ "network-online.target" ]` but do not depend on it (e.g. using
-  `wants`), because the dependency that `multi-user.target` has on
-  `network-online.target` is planned for removal.
+- `services.smokeping` now has an option `webService`. When enabled, smokeping is now served via nginx instead of thttpd. This change brings the following consequences:
+  - The default port for smokeping is now the nginx default port 80 instead of 8081.
+  - The option `services.smokeping.port` has been removed. To customize the port, use `services.nginx.virtualHosts.smokeping.listen.*.port`.
 
-- `services.pgbouncer` now has systemd support enabled and will log to journald. The default setting for `services.pgbouncer.logFile` is now `null` to disable logging to a separate log file.
+- `services.neo4j.allowUpgrade` was removed and no longer has any effect. Neo4j 5 supports automatic rolling upgrades.
 
-- `services.archisteamfarm` no longer uses the abbreviation `asf` for its state directory (`/var/lib/asf`), user and group (both `asf`). Instead the long name `archisteamfarm` is used.
-  Configurations with `system.stateVersion` 23.11 or earlier, default to the old stateDirectory until the 24.11 release and must either set the option explicitly or move the data to the new directory.
+- `services.nextcloud` has the following options moved into [`services.nextcloud.settings`](#opt-services.nextcloud.settings) and renamed to match the name from Nextcloud's `config.php`:
+  - `logLevel` -> [`loglevel`](#opt-services.nextcloud.settings.loglevel),
+  - `logType` -> [`log_type`](#opt-services.nextcloud.settings.log_type),
+  - `defaultPhoneRegion` -> [`default_phone_region`](#opt-services.nextcloud.settings.default_phone_region),
+  - `overwriteProtocol` -> [`overwriteprotocol`](#opt-services.nextcloud.settings.overwriteprotocol),
+  - `skeletonDirectory` -> [`skeletondirectory`](#opt-services.nextcloud.settings.skeletondirectory),
+  - `globalProfiles` -> [`profile.enabled`](#opt-services.nextcloud.settings._profile.enabled_),
+  - `extraTrustedDomains` -> [`trusted_domains`](#opt-services.nextcloud.settings.trusted_domains) and
+  - `trustedProxies` -> [`trusted_proxies`](#opt-services.nextcloud.settings.trusted_proxies).
 
-- `xfsprogs` was updated to version 6.6.0, which enables reverse mapping (rmapbt) and large extent counts (nrext64) by default.
-   Support for these features was added in kernel 4.9 and 5.19 and nrext64 was deemed stable in kernel 6.5.
-   Format your filesystems with `mkfs.xfs -i nrext64=0`, if they need to be readable by GRUB2 before 2.12 or kernels older than 5.19.
+- `services.nginx` will no longer advertise HTTP/3 availability automatically. This must now be manually added, preferably to each location block.
+  Example:
 
-- `networking.iproute2.enable` now does not set `environment.etc."iproute2/rt_tables".text`.
+  ```nix
+  {
+    locations."/".extraConfig = ''
+      add_header Alt-Svc 'h3=":$server_port"; ma=86400';
+    '';
+    locations."^~ /assets/".extraConfig = ''
+      add_header Alt-Svc 'h3=":$server_port"; ma=86400';
+    '';
+  }
+  ```
 
-  Setting `environment.etc."iproute2/{CONFIG_FILE_NAME}".text` will override the whole configuration file instead of appending it to the upstream configuration file.
+- `services.pgbouncer` now has systemd support enabled and will log to journald. The default setting for `services.pgbouncer.logFile` is now `null` to disable logging to a separate log file.
 
-  `CONFIG_FILE_NAME` includes `bpf_pinning`, `ematch_map`, `group`, `nl_protos`, `rt_dsfield`, `rt_protos`, `rt_realms`, `rt_scopes`, and `rt_tables`.
+- `services.postgresql.ensureUsers._.ensurePermissions` has been removed as it is
+  not declarative and is broken with newer postgresql versions. Consider using
+  [](#opt-services.postgresql.ensureUsers._.ensureDBOwnership)
+  instead or a tool that is more suited for managing the data inside a postgresql database.
 
-- `netbox` was updated to v3.7. `services.netbox.package` still defaults
-  to v3.6 if `stateVersion` is earlier than 24.05. Refer to upstream's breaking
-  changes [for
-  v3.7.0](https://github.com/netbox-community/netbox/releases/tag/v3.7.0) and
-  upgrade NetBox by changing `services.netbox.package`. Database migrations
-  will be run automatically.
+- `services.redis.vmOverCommit` now defaults to `true` and no longer enforces Transparent Hugepages (THP) to be disabled. Redis only works with THP configured to `madvise` which is the kernel's default.
 
-- `gauge` now supports installing plugins using nix. For the old imperative approach, switch to `gauge-unwrapped`.
-  You can load plugins from an existing gauge manifest file using `gauge.fromManifest ./path/to/manifest.json` or
-  specify plugins in nix using `gauge.withPlugins (p: with p; [ js html-report xml-report ])`.
+- `services.resolved.fallbackDns`
+  - can now be used to disable the upstream fallback servers entirely by setting it to `[]`
+  - to get previous behaviour of upstream defaults, set it to `null`
+  - default value has changed from `[]` to `null`, in order to preserve default behaviour
 
-- `firefox-devedition`, `firefox-beta`, `firefox-esr` executable file names for now match their package names, which is consistent with the `firefox-*-bin` packages. The desktop entries are also updated so that you can have multiple editions of firefox in your app launcher.
+can now be used to disable the upstream fallback servers entirely by setting it to an empty list. To get the previous behaviour of the upstream defaults set it to null, the new default, instead.
 
-- switch-to-configuration does not directly call systemd-tmpfiles anymore.
-  Instead, the new artificial sysinit-reactivation.target is introduced which
-  allows to restart multiple services that are ordered before sysinit.target
-  and respect the ordering between the services.
+- `services.vikunja` systemd service now uses `vikunja` as dynamic user instead of `vikunja-api`. Database users might need to be changed.
 
-- `systemd.oomd` module behavior is changed as:
+- `services.vikunja.setupNginx` setting has been removed. Users now need to set up the webserver configuration on their own with a proxy pass to the vikunja service.
 
-  - Raise ManagedOOMMemoryPressureLimit from 50% to 80%. This should make systemd-oomd kill things less often, and fix issues like [this](https://pagure.io/fedora-workstation/issue/358).
-    Reference: [commit](https://src.fedoraproject.org/rpms/systemd/c/806c95e1c70af18f81d499b24cd7acfa4c36ffd6?branch=806c95e1c70af18f81d499b24cd7acfa4c36ffd6)
+- `services.vmagent` module deprecates `dataDir`, `group` and `user` setting in favor of systemd provided CacheDirectory and DynamicUser.
 
-  - Remove swap policy. This helps prevent killing processes when user's swap is small.
+- `services.vmagent.remoteWriteUrl` setting has been renamed to `services.vmagent.remoteWrite.url` and now defaults to `null`.
 
-  - Expand the memory pressure policy to system.slice, user-.slice, and all user owned slices. Reference: [commit](https://src.fedoraproject.org/rpms/systemd/c/7665e1796f915dedbf8e014f0a78f4f576d609bb)
+- `services.zope2` has been removed, as `zope2` is unmaintained and was relying on Python 2.
 
-  - `systemd.oomd.enableUserServices` is renamed to `systemd.oomd.enableUserSlices`.
+- `spark2014` has been renamed to `gnatprove`. A version of `gnatprove` matching different GNAT versions is available from the different `gnatPackages` sets.
 
-- `security.pam.enableSSHAgentAuth` now requires `services.openssh.authorizedKeysFiles` to be non-empty,
-  which is the case when `services.openssh.enable` is true. Previously, `pam_ssh_agent_auth` silently failed to work.
+- `stalwart-mail` has been updated to v0.5.3, which includes [breaking changes](https://github.com/stalwartlabs/mail-server/blob/v0.5.3/UPGRADING.md).
 
-- The configuration format for `services.prometheus.exporters.snmp` changed with release 0.23.0.
-  The module now includes an optional config check, that is enabled by default, to make the change obvious before any deployment.
-  More information about the configuration syntax change is available in the [upstream repository](https://github.com/prometheus/snmp_exporter/blob/b75fc6b839ee3f3ccbee68bee55f1ae99555084a/auth-split-migration.md).
+- `system.etc.overlay.enable` option was added. If enabled, `/etc` is
+  mounted via an overlayfs instead of being created by a custom perl script.
 
-- [watchdogd](https://troglobit.com/projects/watchdogd/), a system and process supervisor using watchdog timers. Available as [services.watchdogd](#opt-services.watchdogd.enable).
+- `system.forbiddenDependenciesRegex` has been renamed to `system.forbiddenDependenciesRegexes` and now has the type of `listOf string` instead of `string` to accept multiple regexes.
 
-- `jdt-language-server` package now uses upstream's provided python wrapper instead of our own custom wrapper. This results in the following breaking and notable changes:
+- `systemd.oomd` module behavior has changed:
 
-  - The main binary for the package is now named `jdtls` instead of `jdt-language-server`, equivalent to what most editors expect the binary to be named.
+  - Raise ManagedOOMMemoryPressureLimit from 50% to 80%. This should make systemd-oomd kill things less often, and fix issues like [this](https://pagure.io/fedora-workstation/issue/358).
+    Reference: [commit](https://src.fedoraproject.org/rpms/systemd/c/806c95e1c70af18f81d499b24cd7acfa4c36ffd6?branch=806c95e1c70af18f81d499b24cd7acfa4c36ffd6).
 
-  - JVM arguments should now be provided with the `--jvm-arg` flag instead of setting `JAVA_OPTS`.
+  - Remove swap policy. This helps prevent killing processes when user's swap is small.
 
-  - The `-data` path is no longer required to run the package, and will be set to point to a folder in `$TMP` if missing.
+  - Expand the memory pressure policy to `system.slice`, `user-.slice`, and all user owned slices. Reference: [commit](https://src.fedoraproject.org/rpms/systemd/c/7665e1796f915dedbf8e014f0a78f4f576d609bb).
 
-- `nomad` has been updated - note that HashiCorp recommends updating one minor version at a time. Please check [their upgrade guide](https://developer.hashicorp.com/nomad/docs/upgrade) for information on safely updating clusters and potential breaking changes.
+  - `systemd.oomd.enableUserServices` is renamed to `systemd.oomd.enableUserSlices`.
 
-  - `nomad` is now Nomad 1.7.x.
+- `systemd.sysusers.enable` option was added. If enabled, users and
+  groups are created with systemd-sysusers instead of with a custom perl script.
 
-  - `nomad_1_4` has been removed, as it is now unsupported upstream.
+- `teleport` has been upgraded from major version 14 to major version 15.
+  Refer to upstream [upgrade instructions](https://goteleport.com/docs/management/operations/upgrading/)
+  and release notes for [v15](https://goteleport.com/docs/changelog/#1500-013124).
 
-- Dwarf Fortress has been updated to version 50, and its derivations continue to menace with spikes of Nix and bash. Version 50 is identical to the version on Steam, but without the paid elements like tilepacks.
-  dfhack and Dwarf Therapist still work, and older versions are still packaged in case you'd like to roll back. Note that DF 50 saves will not be compatible with DF 0.47 and earlier.
-  See [Bay 12 Games](http://www.bay12games.com/dwarves/) for more details on what's new in Dwarf Fortress.
+- `unifiLTS`, `unifi5` and `unifi6` have been removed, as they require MongoDB versions which are end-of-life. All these versions can be upgraded to `unifi7` directly.
 
-  - Running an earlier version can be achieved through an override: `dwarf-fortress-packages.dwarf-fortress-full.override { dfVersion = "0.47.5"; }`
+- `unrar` was updated to v7. See [changelog](https://www.rarlab.com/unrar7notes.htm) for more information.
 
-  - Ruby plugin support has been disabled in DFHack. Many of the Ruby plugins have been converted to Lua, and support was removed upstream due to frequent crashes.
+- `virtualisation.docker.enableNvidia` and `virtualisation.podman.enableNvidia` options are deprecated. `hardware.nvidia-container-toolkit.enable` should be used instead. This option will expose GPUs on containers with the `--device` CLI option. This is supported by Docker 25, Podman 3.2.0 and Singularity 4. Any container runtime that supports the CDI specification will take advantage of this feature.
 
-- `livebook` package is now built as a `mix release` instead of an `escript`.
-  This means that configuration now has to be done using [environment variables](https://hexdocs.pm/livebook/readme.html#environment-variables) instead of command line arguments.
-  This has the further implication that the `livebook` service configuration has changed:
+- `virtialisation.incus` now defaults to the newly-added `incus-lts` release (v6.0.x). Users who wish to continue using the non-LTS release will need to set `virtualisation.incus.package = pkgs.incus`. Stable release users are encouraged to stay on the LTS release as non-LTS releases will by default not be backported.
 
-- `erlang_node_short_name`, `erlang_node_name`, `port` and `options` configuration parameters are gone, and have been replaced with an `environment` parameter.
-    Use the appropriate [environment variables](https://hexdocs.pm/livebook/readme.html#environment-variables) inside `environment` to configure the service instead.
+- `woodpecker-*` packages have been updated to v2 which includes [breaking changes](https://woodpecker-ci.org/docs/next/migrations#200).
 
-- `akkoma` now requires explicitly setting the base URL for uploaded media (`settings."Pleroma.Upload".base_url`), as well as for the media proxy if enabled (`settings."Media"`).
-  This is recommended to be a separate (sub)domain to the one Akkoma is hosted at.
-  See [here](https://meta.akkoma.dev/t/akkoma-stable-2024-03-securer-i-barely-know-her/681#explicit-upload-and-media-proxy-domains-5) for more details.
+- `wpaperd` has been updated to 1.0.1, which has a breaking change: previous version 0.3.0 had 2 different configuration files, one for wpaperd and one for the wallpapers. Remove the former and move the latter (`wallpaper.toml`) to `config.toml`.
 
-- `crystal` package has been updated to 1.11.x, which has some breaking changes.
-  Refer to crystal's changelog for more information. ([v1.10](https://github.com/crystal-lang/crystal/blob/master/CHANGELOG.md#1100-2023-10-09), [v1.11](https://github.com/crystal-lang/crystal/blob/master/CHANGELOG.md#1110-2024-01-08))
+- `writeReferencesToFile` is deprecated in favour of the new trivial build helper `writeClosure`. The latter accepts a list of paths and has an unambiguous name and cleaner implementation.
 
-- `erlang-ls` package no longer ships the `els_dap` binary as of v0.51.0.
+- `xfsprogs` was updated to version 6.6.0, which enables reverse mapping (rmapbt) and large extent counts (nrext64) by default.
+   Support for these features was added in kernel 4.9 and 5.19 and nrext64 was deemed stable in kernel 6.5.
+   Format your filesystems with `mkfs.xfs -i nrext64=0`, if they need to be readable by GRUB2 before 2.12 or kernels older than 5.19.
 
-- `icu` no longer includes `install-sh` and `mkinstalldirs` in the shared folder.
+- `xxd` has been moved from `vim` default output to its own output to reduce closure size. The canonical way to reference it across all platforms is `unixtools.xxd`.
 
-## Other Notable Changes {#sec-release-24.05-notable-changes}
+- `youtrack` is bumped to 2023.3. The update is not performed automatically, it requires manual interaction. See the YouTrack section in the manual for details.
 
-<!-- To avoid merge conflicts, consider adding your item at an arbitrary place in the list instead. -->
+- Ada packages (libraries and tools) have been moved into the `gnatPackages` scope. `gnatPackages` uses the default GNAT compiler, `gnat12Packages` and `gnat13Packages` use the respective matching compiler version.
 
-- `addDriverRunpath` has been added to facilitate the deprecation of the old `addOpenGLRunpath` setuphook. This change is motivated by the evolution of the setuphook to include all hardware acceleration.
+- Paths provided as `restartTriggers` and `reloadTriggers` for systemd units will now be copied into the nix store to make the behavior consistent.
+  Previously, `restartTriggers = [ ./config.txt ]`, if defined in a flake, would trigger a restart when any part of the flake changed; and if not defined in a flake, would never trigger a restart even if the contents of `config.txt` changed.
 
-- `cinnamon` has been updated to 6.0. Please beware that the [Wayland session](https://blog.linuxmint.com/?p=4591) is still experimental in this release and could potentially [affect Xorg sessions](https://blog.linuxmint.com/?p=4639). We suggest a reboot when switching between sessions.
+- A warning has been added for services that are
+  `after = [ "network-online.target" ]` but do not depend on it (e.g. using
+  `wants`), because the dependency that `multi-user.target` has on
+  `network-online.target` is planned for removal.
 
-- (TODO awaiting feedback on code-casing package names) MATE has been updated to 1.28.
-  - To properly support panel plugins built with Wayland (in-process) support, we are introducing `services.xserver.desktopManager.mate.extraPanelApplets` option, please use that for installing panel applets.
-  - Similarly, please use `services.xserver.desktopManager.mate.extraCajaExtensions` option for installing Caja extensions.
-  - To use the Wayland session, enable `services.xserver.desktopManager.mate.enableWaylandSession`. This is opt-in for now as it is in early stage and introduces a new set of Wayfire closure. Due to [known issues with LightDM](https://github.com/canonical/lightdm/issues/63), we suggest using SDDM for display manager.
+- switch-to-configuration does not directly call systemd-tmpfiles anymore.
+  Instead, the new artificial sysinit-reactivation.target is introduced which
+  allows to restart multiple services that are ordered before sysinit.target
+  and respect the ordering between the services.
 
-- `services.xserver.desktopManager.budgie` installs `gnome.gnome-terminal` by default (instead of `mate.mate-terminal`).
+- `services.prometheus.exporters.snmp`'s configuration format changed with release 0.23.0.
+  The module now includes an optional config check, that is enabled by default, to make the change obvious before any deployment.
+  More information about the configuration syntax change is available in the [upstream repository](https://github.com/prometheus/snmp_exporter/blob/b75fc6b839ee3f3ccbee68bee55f1ae99555084a/auth-split-migration.md).
 
-- New `boot.loader.systemd-boot.xbootldrMountPoint` allows setting up a separate [XBOOTLDR partition](https://uapi-group.org/specifications/specs/boot_loader_specification/) to store boot files. Useful on systems with a small EFI System partition that cannot be easily repartitioned.
+## Other Notable Changes {#sec-release-24.05-notable-changes}
 
-- `boot.loader.systemd-boot` will now verify that `efiSysMountPoint` (and `xbootldrMountPoint` if configured) are mounted partitions.
+<!-- To avoid merge conflicts, consider adding your item at an arbitrary place in the list instead. -->
 
-- `services.postgresql.extraPlugins` changed its type from just a list of packages to also a function that returns such a list.
-  For example a config line like ``services.postgresql.extraPlugins = with pkgs.postgresql_11.pkgs; [ postgis ];`` is recommended to be changed to ``services.postgresql.extraPlugins = ps: with ps; [ postgis ];``;
+- `addDriverRunpath` has been added to facilitate the deprecation of the old `addOpenGLRunpath` setuphook. This change is motivated by the evolution of the setuphook to include all hardware acceleration.
 
-- `services.openssh` now has an option `authorizedKeysInHomedir`, controlling whether `~/.ssh/authorizedKeys` is
-  added to `authorizedKeysFiles`.
-  ::: {.note}
-  This option currently defaults to `true` for NixOS 24.05, preserving the previous behaviour.
-  This is expected to change in NixOS 24.11.
-  :::
-  ::: {.warning}
-  Users should check that their SSH keys are in `users.users.*.openssh`, or that they have another way to access
-  and administer the system, before setting this option to `false`.
-  :::
+- `appimage`, `appimageTools.wrapAppImage` and `buildFHSEnvBubblewrap` now properly accept `pname` and `version`.
 
-- [`matrix-synapse`](https://element-hq.github.io/synapse/) homeserver module now supports configuring UNIX domain socket [`listeners`](#opt-services.matrix-synapse.settings.listeners) through the `path` option.
-  The default replication worker on the main instance has been migrated away from TCP sockets to UNIX domain sockets.
+- `bacula` now allows to configure `TLS` for encrypted communication.
 
 - `boot.initrd.network.ssh.authorizedKeyFiles` is a new option in the initrd ssh daemon module, for adding authorized keys via list of files.
 
-- `appimage`, `appimageTools.wrapAppImage` and `buildFHSEnvBubblewrap` now properly accepts `pname` and `version`.
+- `boot.kernel.sysctl."net.core.wmem_max"` changed from a string to an integer because of the addition of a custom merge option (taking the highest value defined to avoid conflicts between 2 services trying to set that value), just as `boot.kernel.sysctl."net.core.rmem_max"` since 22.11.
 
-- Programs written in [Nim](https://nim-lang.org/) are built with libraries selected by lockfiles.
-  The `nimPackages` and `nim2Packages` sets have been removed.
-  See https://nixos.org/manual/nixpkgs/unstable#nim for more information.
+- `boot.loader.systemd-boot.xbootldrMountPoint` is a new option for setting up a separate [XBOOTLDR partition](https://uapi-group.org/specifications/specs/boot_loader_specification/) to store boot files. Useful on systems with a small EFI System partition that cannot be easily repartitioned.
 
-- [TODO: reword to place an attribute at the front] Programs written in [D](https://dlang.org/) using the `dub` build system and package manager can now be built using `buildDubPackage` utilizing lockfiles provided by the new `dub-to-nix` helper program.
+- `boot.loader.systemd-boot` will now verify that `efiSysMountPoint` (and `xbootldrMountPoint` if configured) are mounted partitions.
+
+- `buildDubPackage` can now be used to build Programs written in [D](https://dlang.org/) using the `dub` build system and package manager.
   See the [D section](https://nixos.org/manual/nixpkgs/unstable#dlang) in the manual for more information.
 
-- [`portunus`](https://github.com/majewsky/portunus) has been updated to major version 2.
-  This version of Portunus supports strong password hashes, but the legacy hash SHA-256 is also still supported to ensure a smooth migration of existing user accounts.
-  After upgrading, follow the instructions on the [upstream release notes](https://github.com/majewsky/portunus/releases/tag/v2.0.0) to upgrade all user accounts to strong password hashes.
-  Support for weak password hashes will be removed in NixOS 24.11.
+- `castopod` has some migration actions to be taken in case of a S3 setup. Some new features may also need some manual migration actions. See [https://code.castopod.org/adaures/castopod/-/releases](https://code.castopod.org/adaures/castopod/-/releases) for more information.
 
-- A stdenv's default set of hardening flags can now be set via its `bintools-wrapper`'s `defaultHardeningFlags` argument. A convenient stdenv adapter, `withDefaultHardeningFlags`, can be used to override an existing stdenv's `defaultHardeningFlags`.
+- `cinnamon` has been updated to 6.0. Please beware that the [Wayland session](https://blog.linuxmint.com/?p=4591) is still experimental in this release and could potentially [affect Xorg sessions](https://blog.linuxmint.com/?p=4639). We suggest a reboot when switching between sessions.
 
-- `libass` now uses the native CoreText backend on Darwin, which may fix subtitle rendering issues with `mpv`, `ffmpeg`, etc.
+- `documentation.man.mandoc` now uses `MANPATH` by defaultwas to set the directories where mandoc will search for manual pages.
+  This enables mandoc to find manual pages in Nix profiles. To set the manual search paths via the `mandoc.conf` configuration file like before, use `documentation.man.mandoc.settings.manpath` instead.
 
-- [`lilypond`](https://lilypond.org/index.html) and [`denemo`](https://www.denemo.org) are now compiled with Guile 3.0.
+- `drbd` out-of-tree Linux kernel driver has been added in version 9.2.7. With it the DRBD 9.x features can be used instead of the 8.x features provided by the 8.4.11 in-tree driver.
 
 - `garage` has been updated to v1.x.x. Users should read the [upstream release notes](https://git.deuxfleurs.fr/Deuxfleurs/garage/releases/tag/v1.0.0) and follow the documentation when changing over their `services.garage.package` and performing this manual upgrade.
 
-- [TODO: reword to place an attribute at the front] The EC2 image module now enables the [Amazon SSM Agent](https://docs.aws.amazon.com/systems-manager/latest/userguide/ssm-agent.html) by default.
-
-- The following options of the Nextcloud module were moved into [`services.nextcloud.settings`](#opt-services.nextcloud.settings) and renamed to match the name from Nextcloud's `config.php`:
-  - `logLevel` -> [`loglevel`](#opt-services.nextcloud.settings.loglevel),
-  - `logType` -> [`log_type`](#opt-services.nextcloud.settings.log_type),
-  - `defaultPhoneRegion` -> [`default_phone_region`](#opt-services.nextcloud.settings.default_phone_region),
-  - `overwriteProtocol` -> [`overwriteprotocol`](#opt-services.nextcloud.settings.overwriteprotocol),
-  - `skeletonDirectory` -> [`skeletondirectory`](#opt-services.nextcloud.settings.skeletondirectory),
-  - `globalProfiles` -> [`profile.enabled`](#opt-services.nextcloud.settings._profile.enabled_),
-  - `extraTrustedDomains` -> [`trusted_domains`](#opt-services.nextcloud.settings.trusted_domains) and
-  - `trustedProxies` -> [`trusted_proxies`](#opt-services.nextcloud.settings.trusted_proxies).
+- `hardware.pulseaudio` module now sets permission of pulse user home directory to 755 when running in "systemWide" mode. It fixes [issue 114399](https://github.com/NixOS/nixpkgs/issues/114399).
 
-- `services.nextcloud.config.dbport` option of the Nextcloud module was removed to match upstream.
-  The port can be specified in [`services.nextcloud.config.dbhost`](#opt-services.nextcloud.config.dbhost).
+- `kavita` has been updated to 0.8.0, requiring a manual forced library scan on all libraries for migration. Refer to upstream's [release notes](https://github.com/Kareadita/Kavita/releases/tag/v0.8.0) for details.
 
-- A new abstraction to create both read-only as well as writable overlay file
-  systems was added. Available via
-  [fileSystems.overlay](#opt-fileSystems._name_.overlay.lowerdir). See also the
-  [NixOS docs](#sec-overlayfs).
+- `krb5` module has been rewritten and moved to `security.krb5`, moving all options but `security.krb5.enable` and `security.krb5.package` into `security.krb5.settings`.
 
-- `systemd` units can now specify the `Upholds=` and `UpheldBy=` unit dependencies via the aptly
-  named `upholds` and `upheldBy` options. These options get systemd to enforce that the
-  dependencies remain continuosly running for as long as the dependent unit is in a running state.
+- `libass` now uses the native CoreText backend on Darwin, which may fix subtitle rendering issues with `mpv`, `ffmpeg`, etc.
 
-- `stdenv`: The `--replace` flag in `substitute`, `substituteInPlace`, `substituteAll`, `substituteAllStream`, and `substituteStream` is now deprecated if favor of the new `--replace-fail`, `--replace-warn` and `--replace-quiet`. The deprecated `--replace` equates to `--replace-warn`.
+- `libjxl` version bumped from 0.8.2 to 0.9.1 [dropped support for the butteraugli API](https://github.com/libjxl/libjxl/pull/2576). You will no longer be able to set `enableButteraugli` on `libaom`.
 
-- A new hardening flag, `zerocallusedregs` was made available, corresponding to the gcc/clang option `-fzero-call-used-regs=used-gpr`.
+- [`lilypond`](https://lilypond.org/index.html) and [`denemo`](https://www.denemo.org) are now compiled with Guile 3.0.
 
-- A new hardening flag, `trivialautovarinit` was made available, corresponding to the gcc/clang option `-ftrivial-auto-var-init=pattern`.
+- `lxd` has been upgraded to v5.21.x, an LTS release. The LTS release is now the only supported LXD release. Users are encouraged to [migrate to Incus](https://linuxcontainers.org/incus/docs/main/howto/server_migrate_lxd/) for better support on NixOS.
 
-- New options were added to the dnsdist module to enable and configure a DNSCrypt endpoint (see `services.dnsdist.dnscrypt.enable`, etc.).
-  The module can generate the DNSCrypt provider key pair, certificates and also performs their rotation automatically with no downtime.
+- [`matrix-synapse`](https://element-hq.github.io/synapse/) homeserver module now supports configuring UNIX domain socket [`listeners`](#opt-services.matrix-synapse.settings.listeners) through the `path` option.
+  The default replication worker on the main instance has been migrated away from TCP sockets to UNIX domain sockets.
 
-- `sonarr` version bumped to from 3.0.10 to 4.0.3. Consequently existing config database files will be upgraded automatically, but note that some old apparently-working configs [might actually be corrupt and fail to upgrade cleanly](https://forums.sonarr.tv/t/sonarr-v4-released/33089).
+- `mockgen` has changed to the [go.uber.org/mock](https://github.com/uber-go/mock) fork because [the original repository is no longer maintained](https://github.com/golang/mock#gomock).
 
-- [TODO: reword to place an attribute at the front] The Yama LSM is now enabled by default in the kernel, which prevents ptracing
-  non-child processes. This means you will not be able to attach gdb to an
-  existing process, but will need to start that process from gdb (so it is a
-  child). Or you can set `boot.kernel.sysctl."kernel.yama.ptrace_scope"` to 0.
+- `mpich` now requires `withPm` to be a list, e.g. `"hydra:gforker"` becomes `[ "hydra" "gforker" ]`.
 
-- `netbird` module now allows running multiple tunnels in parallel through [`services.netbird.tunnels`](#opt-services.netbird.tunnels).
+- `nextcloud-setup.service` no longer changes the group of each file & directory inside `/var/lib/nextcloud/{config,data,store-apps}` if one of these directories has the wrong owner group. This was part of transitioning the group used for `/var/lib/nextcloud`, but isn't necessary anymore.
 
-- [Nginx virtual hosts](#opt-services.nginx.virtualHosts) using `forceSSL` or
-  `globalRedirect` can now have redirect codes other than 301 through `redirectCode`.
+- `oils-for-unix`, the oil shell's c++ version is now available. The python version is still available as `oil`.
 
-- `bacula` now allows to configure `TLS` for encrypted communication.
+- `pkgsExtraHardening`, a new top-level package set, was added. This is a set of packages built with stricter hardening flags - those that have not yet received enough testing to be applied universally, those that are more likely to cause build failures or those that have drawbacks to their use (e.g. performance or required hardware features).
 
-- `libjxl` version bumped from 0.8.2 to 0.9.1 [dropped support for the butteraugli API](https://github.com/libjxl/libjxl/pull/2576). You will no longer be able to set `enableButteraugli` on `libaom`.
+- [`portunus`](https://github.com/majewsky/portunus) has been updated to major version 2.
+  This version of Portunus supports strong password hashes, but the legacy hash SHA-256 is also still supported to ensure a smooth migration of existing user accounts.
+  After upgrading, follow the instructions on the [upstream release notes](https://github.com/majewsky/portunus/releases/tag/v2.0.0) to upgrade all user accounts to strong password hashes.
+  Support for weak password hashes will be removed in NixOS 24.11.
 
-- `mockgen` package source has changed to the [go.uber.org/mock](https://github.com/uber-go/mock) fork because [the original repository is no longer maintained](https://github.com/golang/mock#gomock).
+- `programs.fish.package` now allows you to override the package used in the `fish` module.
 
-- [](#opt-boot.kernel.sysctl._net.core.wmem_max_) changed from a string to an integer because of the addition of a custom merge option (taking the highest value defined to avoid conflicts between 2 services trying to set that value), just as [](#opt-boot.kernel.sysctl._net.core.rmem_max_) since 22.11.
+- `qt6.qtmultimedia` has changed its default backend to `QT_MEDIA_BACKEND=ffmpeg` (previously `gstreamer` on Linux or `darwin` on macOS).
+  The previous native backends remain available but are now minimally maintained. Refer to [upstream documentation](https://doc.qt.io/qt-6/qtmultimedia-index.html#ffmpeg-as-the-default-backend) for further details about each platform.
 
-- [TODO: reword to place an attribute at the front] A new top-level package set, `pkgsExtraHardening` is added. This is a set of packages built with stricter hardening flags - those that have not yet received enough testing to be applied universally, those that are more likely to cause build failures or those that have drawbacks to their use (e.g. performance or required hardware features).
+- `services.btrbk` now automatically selects and provides required compression
+  program depending on the configured `stream_compress` option. Since this
+  replaces the need for the `extraPackages` option, this option will be
+  deprecated in future releases.
 
-- `services.zfs.zed.enableMail` now uses the global `sendmail` wrapper defined by an email module
-  (such as msmtp or Postfix). It no longer requires using a special ZFS build with email support.
+- `services.github-runner` module has been removed. To configure a single GitHub Actions Runner refer to `services.github-runners.*`. Note that this will trigger a new runner registration.
 
-- `castopod` has some migration actions to be taken in case of a S3 setup. Some new features may also need some manual migration actions. See [https://code.castopod.org/adaures/castopod/-/releases](https://code.castopod.org/adaures/castopod/-/releases) for more informations.
+- `services.networkmanager.extraConfig` was renamed to `services.networkmanager.settings` and changed to use the ini type instead of using a multiline string.
 
-- `nextcloud-setup.service` no longer changes the group of each file & directory inside `/var/lib/nextcloud/{config,data,store-apps}` if one of these directories has the wrong owner group. This was part of transitioning the group used for `/var/lib/nextcloud`, but isn't necessary anymore.
+- `services.nextcloud.config.dbport` option of the Nextcloud module was removed to match upstream.
+  The port can be specified in [`services.nextcloud.config.dbhost`](#opt-services.nextcloud.config.dbhost).
 
 - `services.kavita` now uses the free-form option `services.kavita.settings` for the application settings file.
   The options `services.kavita.ipAdresses` and `services.kavita.port` now exist at `services.kavita.settings.IpAddresses`
   and `services.kavita.settings.IpAddresses`. The file at `services.kavita.tokenKeyFile` now needs to contain a secret with
   512+ bits instead of 128+ bits.
 
-- `kavita` has been updated to 0.8.0, requiring a manual forced library scan on all libraries for migration. Refer to upstream's [release notes](https://github.com/Kareadita/Kavita/releases/tag/v0.8.0) for details.
-
-- `krb5` module has been rewritten and moved to `security.krb5`, moving all options but `security.krb5.enable` and `security.krb5.package` into `security.krb5.settings`.
+- `services.netbird` now allows running multiple tunnels in parallel through [`services.netbird.tunnels`](#opt-services.netbird.tunnels).
 
-- `services.soju` now has a wrapper for the `sojuctl` command, pointed at the service config file. It also has the new option `adminSocket.enable`, which creates a unix admin socket at `/run/soju/admin`.
+- `services.nginx.virtualHosts` using `forceSSL` or
+  `globalRedirect` can now have redirect codes other than 301 through `redirectCode`.
 
-- `gitea` upgrade to 1.21 has several breaking changes, including:
-  - Custom themes and other assets that were previously stored in `custom/public/*` now belong in `custom/public/assets/*`
-  - New instances of Gitea using MySQL now ignore the `[database].CHARSET` config option and always use the `utf8mb4` charset, existing instances should migrate via the `gitea doctor convert` CLI command.
+- `services.openssh` now has an option `authorizedKeysInHomedir`, controlling whether `~/.ssh/authorizedKeys` is
+  added to `authorizedKeysFiles`.
+  ::: {.note}
+  This option currently defaults to `true` for NixOS 24.05, preserving the previous behaviour.
+  This is expected to change in NixOS 24.11.
+  :::
+  ::: {.warning}
+  Users should check that their SSH keys are in `users.users.*.openssh`, or that they have another way to access
+  and administer the system, before setting this option to `false`.
+  :::
 
 - `services.paperless` module no longer uses the previously downloaded NLTK data stored in `/var/cache/paperless/nltk`. This directory can be removed.
 
-- `services.teeworlds` module now has a wealth of configuration options, including a new `package` option.
-
-- `hardware.pulseaudio` module now sets permission of pulse user home directory to 755 when running in "systemWide" mode. It fixes [issue 114399](https://github.com/NixOS/nixpkgs/issues/114399).
-
-- `services.networkmanager.extraConfig` was renamed to `services.networkmanager.settings` and was changed to use the ini type instead of using a multiline string.
-
-- `services.github-runner` module has been removed. To configure a single GitHub Actions Runner refer to `services.github-runners.*`. Note that this will trigger a new runner registration.
+- `services.postgresql.extraPlugins`' type has expanded. Previously it was a list of packages, now it can also be a function that returns such a list.
+  For example a config line like ``services.postgresql.extraPlugins = with pkgs.postgresql_11.pkgs; [ postgis ];`` is recommended to be changed to ``services.postgresql.extraPlugins = ps: with ps; [ postgis ];``;
 
 - `services.slskd` has been refactored to include more configuation options in
   the free-form `services.slskd.settings` option, and some defaults (including listen ports)
@@ -677,32 +709,55 @@ The pre-existing [services.ankisyncd](#opt-services.ankisyncd.enable) has been m
   disabled by default, and the log rotation timer has been removed.
   The nginx virtualhost option is now of the `vhost-options` type.
 
-- `services.btrbk` now automatically selects and provides required compression
-  program depending on the configured `stream_compress` option. Since this
-  replaces the need for the `extraPackages` option, this option will be
-  deprecated in future releases.
+- `services.soju` now has a wrapper for the `sojuctl` command, pointed at the service config file. It also has the new option `adminSocket.enable`, which creates a unix admin socket at `/run/soju/admin`.
 
-- `mpich` package expression now requires `withPm` to be a list, e.g. `"hydra:gforker"` becomes `[ "hydra" "gforker" ]`.
+- `services.stalwart-mail` uses the legacy version 0.6.X as default because newer `stalwart-mail` versions require a [manual upgrade process](https://github.com/stalwartlabs/mail-server/blob/main/UPGRADING.md). Change [`services.stalwart-mail.package`](#opt-services.stalwart-mail.package) to `pkgs.stalwart-mail` if you wish to switch to the new version.
+
+- `services.teeworlds` module now has a wealth of configuration options, including a new `package` option.
+
+- `services.xserver.desktopManager.budgie` installs `gnome.gnome-terminal` by default (instead of `mate.mate-terminal`).
+
+- `services.zfs.zed.enableMail` now uses the global `sendmail` wrapper defined by an email module
+  (such as msmtp or Postfix). It no longer requires using a special ZFS build with email support.
+
+- `sonarr` version bumped to from 3.0.10 to 4.0.3. Consequently existing config database files will be upgraded automatically, but note that some old apparently-working configs [might actually be corrupt and fail to upgrade cleanly](https://forums.sonarr.tv/t/sonarr-v4-released/33089).
+
+- `stdenv`: The `--replace` flag in `substitute`, `substituteInPlace`, `substituteAll`, `substituteAllStream`, and `substituteStream` is now deprecated if favor of the new `--replace-fail`, `--replace-warn` and `--replace-quiet`. The deprecated `--replace` equates to `--replace-warn`.
 
 - `systemd`: when merging unit options (of type `unitOption`),
   if at least one definition is a list, all those which aren't are now lifted into a list,
   making it possible to accumulate definitions without resorting to `mkForce`,
   hence to retain the definitions not anticipating that need.
 
-- Lisp modules: previously deprecated interface based on `common-lisp.sh` has now been removed.
+- `systemd` units can now specify the `Upholds=` and `UpheldBy=` unit dependencies via the aptly
+  named `upholds` and `upheldBy` options. These options get systemd to enforce that the
+  dependencies remain continuosly running for as long as the dependent unit is in a running state.
 
-- `youtrack` is bumped to 2023.3. The update is not performed automatically, it requires manual interaction. See the YouTrack section in the manual for details.
+- A stdenv's default set of hardening flags can now be set via its `bintools-wrapper`'s `defaultHardeningFlags` argument. A convenient stdenv adapter, `withDefaultHardeningFlags`, can be used to override an existing stdenv's `defaultHardeningFlags`.
 
-- QtMultimedia has changed its default backend to `QT_MEDIA_BACKEND=ffmpeg` (previously `gstreamer` on Linux or `darwin` on MacOS).
-  The previous native backends remain available but are now minimally maintained. Refer to [upstream documentation](https://doc.qt.io/qt-6/qtmultimedia-index.html#ffmpeg-as-the-default-backend) for further details about each platform.
+- Programs written in [Nim](https://nim-lang.org/) are built with libraries selected by lockfiles.
+  The `nimPackages` and `nim2Packages` sets have been removed.
+  See https://nixos.org/manual/nixpkgs/unstable#nim for more information.
 
-- `drbd` out-of-tree Linux kernel driver has been added in version 9.2.7. With it the DRBD 9.x features can be used instead of the 8.x features provided by the 8.4.11 in-tree driver.
+- The EC2 image module now enables the [Amazon SSM Agent](https://docs.aws.amazon.com/systems-manager/latest/userguide/ssm-agent.html) by default.
 
-- [TODO: reword to place an attribute at the front] The oil shell's c++ version is now available as `oils-for-unix`. The python version is still available as `oil`
+- A new abstraction to create both read-only as well as writable overlay file
+  systems was added. Available via
+  [fileSystems.overlay](#opt-fileSystems._name_.overlay.lowerdir). See also the
+  [NixOS docs](#sec-overlayfs).
 
-- `documentation.man.mandoc` now by default uses `MANPATH` to set the directories where mandoc will search for manual pages.
-  This enables mandoc to find manual pages in Nix profiles. To set the manual search paths via the `mandoc.conf` configuration file like before, use `documentation.man.mandoc.settings.manpath` instead.
+- A new hardening flag, `zerocallusedregs` was made available, corresponding to the gcc/clang option `-fzero-call-used-regs=used-gpr`.
+
+- A new hardening flag, `trivialautovarinit` was made available, corresponding to the gcc/clang option `-ftrivial-auto-var-init=pattern`.
+
+- `dnsdist` has new options to enable and configure a DNSCrypt endpoint (see `services.dnsdist.dnscrypt.enable`, etc.).
+  The module can generate the DNSCrypt provider key pair and certificates, and also rotates them automatically with no downtime.
 
-- `grafana-loki` package was updated to 3.0.0 which includes [breaking changes](https://github.com/grafana/loki/releases/tag/v3.0.0)
+- The kernel Yama LSM is now enabled by default, which prevents ptracing
+  non-child processes. This means you will not be able to attach gdb to an
+  existing process, but will need to start that process from gdb (so it is a
+  child). Or you can set `boot.kernel.sysctl."kernel.yama.ptrace_scope"` to 0.
+
+- Lisp modules: previously deprecated interface based on `common-lisp.sh` has now been removed.
 
-- `programs.fish.package` now allows you to override the package used in the `fish` module
+- The `systemd-confinement` module extension is now compatible with `DynamicUser=true` and thus `ProtectSystem=strict` too.
diff --git a/nixos/doc/manual/release-notes/rl-2411.section.md b/nixos/doc/manual/release-notes/rl-2411.section.md
new file mode 100644
index 0000000000000..2277308d6ba2f
--- /dev/null
+++ b/nixos/doc/manual/release-notes/rl-2411.section.md
@@ -0,0 +1,23 @@
+# Release 24.11 (“Vicuña”, 2024.11/??) {#sec-release-24.11}
+
+<!-- To avoid merge conflicts, consider adding your item at an arbitrary place in the list instead. -->
+
+## Highlights {#sec-release-24.11-highlights}
+
+- Create the first release note entry in this section!
+
+## New Services {#sec-release-24.11-new-services}
+
+- Create the first release note entry in this section!
+
+## Backward Incompatibilities {#sec-release-24.11-incompatibilities}
+
+- `nvimpager` was updated to version 0.13.0, which changes the order of user and
+  nvimpager settings: user commands in `-c` and `--cmd` now override the
+  respective default settings because they are executed later.
+
+## Other Notable Changes {#sec-release-24.11-notable-changes}
+
+- Create the first release note entry in this section!
+
+<!-- To avoid merge conflicts, consider adding your item at an arbitrary place in the list instead. -->
diff --git a/nixos/lib/test-driver/default.nix b/nixos/lib/test-driver/default.nix
index 1acdaacc4e658..7a88694b3167e 100644
--- a/nixos/lib/test-driver/default.nix
+++ b/nixos/lib/test-driver/default.nix
@@ -24,6 +24,7 @@ python3Packages.buildPythonApplication {
     coreutils
     netpbm
     python3Packages.colorama
+    python3Packages.junit-xml
     python3Packages.ptpython
     qemu_pkg
     socat
@@ -46,7 +47,7 @@ python3Packages.buildPythonApplication {
     echo -e "\x1b[32m## run mypy\x1b[0m"
     mypy test_driver extract-docstrings.py
     echo -e "\x1b[32m## run ruff\x1b[0m"
-    ruff .
+    ruff check .
     echo -e "\x1b[32m## run black\x1b[0m"
     black --check --diff .
   '';
diff --git a/nixos/lib/test-driver/pyproject.toml b/nixos/lib/test-driver/pyproject.toml
index 17b7130a4bad7..714139bc1b25c 100644
--- a/nixos/lib/test-driver/pyproject.toml
+++ b/nixos/lib/test-driver/pyproject.toml
@@ -19,8 +19,8 @@ test_driver = ["py.typed"]
 [tool.ruff]
 line-length = 88
 
-select = ["E", "F", "I", "U", "N"]
-ignore = ["E501"]
+lint.select = ["E", "F", "I", "U", "N"]
+lint.ignore = ["E501"]
 
 # xxx: we can import https://pypi.org/project/types-colorama/ here
 [[tool.mypy.overrides]]
@@ -31,6 +31,10 @@ ignore_missing_imports = true
 module = "ptpython.*"
 ignore_missing_imports = true
 
+[[tool.mypy.overrides]]
+module = "junit_xml.*"
+ignore_missing_imports = true
+
 [tool.black]
 line-length = 88
 target-version = ['py39']
diff --git a/nixos/lib/test-driver/test_driver/__init__.py b/nixos/lib/test-driver/test_driver/__init__.py
index 9daae1e941a65..42b6d29b76714 100755
--- a/nixos/lib/test-driver/test_driver/__init__.py
+++ b/nixos/lib/test-driver/test_driver/__init__.py
@@ -6,7 +6,12 @@ from pathlib import Path
 import ptpython.repl
 
 from test_driver.driver import Driver
-from test_driver.logger import rootlog
+from test_driver.logger import (
+    CompositeLogger,
+    JunitXMLLogger,
+    TerminalLogger,
+    XMLLogger,
+)
 
 
 class EnvDefault(argparse.Action):
@@ -93,6 +98,11 @@ def main() -> None:
         type=writeable_dir,
     )
     arg_parser.add_argument(
+        "--junit-xml",
+        help="Enable JunitXML report generation to the given path",
+        type=Path,
+    )
+    arg_parser.add_argument(
         "testscript",
         action=EnvDefault,
         envvar="testScript",
@@ -102,14 +112,24 @@ def main() -> None:
 
     args = arg_parser.parse_args()
 
+    output_directory = args.output_directory.resolve()
+    logger = CompositeLogger([TerminalLogger()])
+
+    if "LOGFILE" in os.environ.keys():
+        logger.add_logger(XMLLogger(os.environ["LOGFILE"]))
+
+    if args.junit_xml:
+        logger.add_logger(JunitXMLLogger(output_directory / args.junit_xml))
+
     if not args.keep_vm_state:
-        rootlog.info("Machine state will be reset. To keep it, pass --keep-vm-state")
+        logger.info("Machine state will be reset. To keep it, pass --keep-vm-state")
 
     with Driver(
         args.start_scripts,
         args.vlans,
         args.testscript.read_text(),
-        args.output_directory.resolve(),
+        output_directory,
+        logger,
         args.keep_vm_state,
         args.global_timeout,
     ) as driver:
@@ -125,7 +145,7 @@ def main() -> None:
             tic = time.time()
             driver.run_tests()
             toc = time.time()
-            rootlog.info(f"test script finished in {(toc-tic):.2f}s")
+            logger.info(f"test script finished in {(toc-tic):.2f}s")
 
 
 def generate_driver_symbols() -> None:
@@ -134,7 +154,7 @@ def generate_driver_symbols() -> None:
     in user's test scripts. That list is then used by pyflakes to lint those
     scripts.
     """
-    d = Driver([], [], "", Path())
+    d = Driver([], [], "", Path(), CompositeLogger([]))
     test_symbols = d.test_symbols()
     with open("driver-symbols", "w") as fp:
         fp.write(",".join(test_symbols.keys()))
diff --git a/nixos/lib/test-driver/test_driver/driver.py b/nixos/lib/test-driver/test_driver/driver.py
index f792c04591996..10092fc966c8f 100644
--- a/nixos/lib/test-driver/test_driver/driver.py
+++ b/nixos/lib/test-driver/test_driver/driver.py
@@ -9,7 +9,7 @@ from typing import Any, Callable, ContextManager, Dict, Iterator, List, Optional
 
 from colorama import Fore, Style
 
-from test_driver.logger import rootlog
+from test_driver.logger import AbstractLogger
 from test_driver.machine import Machine, NixStartScript, retry
 from test_driver.polling_condition import PollingCondition
 from test_driver.vlan import VLan
@@ -49,6 +49,7 @@ class Driver:
     polling_conditions: List[PollingCondition]
     global_timeout: int
     race_timer: threading.Timer
+    logger: AbstractLogger
 
     def __init__(
         self,
@@ -56,6 +57,7 @@ class Driver:
         vlans: List[int],
         tests: str,
         out_dir: Path,
+        logger: AbstractLogger,
         keep_vm_state: bool = False,
         global_timeout: int = 24 * 60 * 60 * 7,
     ):
@@ -63,12 +65,13 @@ class Driver:
         self.out_dir = out_dir
         self.global_timeout = global_timeout
         self.race_timer = threading.Timer(global_timeout, self.terminate_test)
+        self.logger = logger
 
         tmp_dir = get_tmp_dir()
 
-        with rootlog.nested("start all VLans"):
+        with self.logger.nested("start all VLans"):
             vlans = list(set(vlans))
-            self.vlans = [VLan(nr, tmp_dir) for nr in vlans]
+            self.vlans = [VLan(nr, tmp_dir, self.logger) for nr in vlans]
 
         def cmd(scripts: List[str]) -> Iterator[NixStartScript]:
             for s in scripts:
@@ -84,6 +87,7 @@ class Driver:
                 tmp_dir=tmp_dir,
                 callbacks=[self.check_polling_conditions],
                 out_dir=self.out_dir,
+                logger=self.logger,
             )
             for cmd in cmd(start_scripts)
         ]
@@ -92,19 +96,19 @@ class Driver:
         return self
 
     def __exit__(self, *_: Any) -> None:
-        with rootlog.nested("cleanup"):
+        with self.logger.nested("cleanup"):
             self.race_timer.cancel()
             for machine in self.machines:
                 machine.release()
 
     def subtest(self, name: str) -> Iterator[None]:
         """Group logs under a given test name"""
-        with rootlog.nested("subtest: " + name):
+        with self.logger.subtest(name):
             try:
                 yield
                 return True
             except Exception as e:
-                rootlog.error(f'Test "{name}" failed with error: "{e}"')
+                self.logger.error(f'Test "{name}" failed with error: "{e}"')
                 raise e
 
     def test_symbols(self) -> Dict[str, Any]:
@@ -118,7 +122,7 @@ class Driver:
             machines=self.machines,
             vlans=self.vlans,
             driver=self,
-            log=rootlog,
+            log=self.logger,
             os=os,
             create_machine=self.create_machine,
             subtest=subtest,
@@ -150,13 +154,13 @@ class Driver:
 
     def test_script(self) -> None:
         """Run the test script"""
-        with rootlog.nested("run the VM test script"):
+        with self.logger.nested("run the VM test script"):
             symbols = self.test_symbols()  # call eagerly
             exec(self.tests, symbols, None)
 
     def run_tests(self) -> None:
         """Run the test script (for non-interactive test runs)"""
-        rootlog.info(
+        self.logger.info(
             f"Test will time out and terminate in {self.global_timeout} seconds"
         )
         self.race_timer.start()
@@ -168,13 +172,13 @@ class Driver:
 
     def start_all(self) -> None:
         """Start all machines"""
-        with rootlog.nested("start all VMs"):
+        with self.logger.nested("start all VMs"):
             for machine in self.machines:
                 machine.start()
 
     def join_all(self) -> None:
         """Wait for all machines to shut down"""
-        with rootlog.nested("wait for all VMs to finish"):
+        with self.logger.nested("wait for all VMs to finish"):
             for machine in self.machines:
                 machine.wait_for_shutdown()
             self.race_timer.cancel()
@@ -182,7 +186,7 @@ class Driver:
     def terminate_test(self) -> None:
         # This will be usually running in another thread than
         # the thread actually executing the test script.
-        with rootlog.nested("timeout reached; test terminating..."):
+        with self.logger.nested("timeout reached; test terminating..."):
             for machine in self.machines:
                 machine.release()
             # As we cannot `sys.exit` from another thread
@@ -227,7 +231,7 @@ class Driver:
                     f"Unsupported arguments passed to create_machine: {args}"
                 )
 
-            rootlog.warning(
+            self.logger.warning(
                 Fore.YELLOW
                 + Style.BRIGHT
                 + "WARNING: Using create_machine with a single dictionary argument is deprecated and will be removed in NixOS 24.11"
@@ -246,13 +250,14 @@ class Driver:
             start_command=cmd,
             name=name,
             keep_vm_state=keep_vm_state,
+            logger=self.logger,
         )
 
     def serial_stdout_on(self) -> None:
-        rootlog._print_serial_logs = True
+        self.logger.print_serial_logs(True)
 
     def serial_stdout_off(self) -> None:
-        rootlog._print_serial_logs = False
+        self.logger.print_serial_logs(False)
 
     def check_polling_conditions(self) -> None:
         for condition in self.polling_conditions:
@@ -271,6 +276,7 @@ class Driver:
             def __init__(self, fun: Callable):
                 self.condition = PollingCondition(
                     fun,
+                    driver.logger,
                     seconds_interval,
                     description,
                 )
@@ -285,15 +291,17 @@ class Driver:
             def wait(self, timeout: int = 900) -> None:
                 def condition(last: bool) -> bool:
                     if last:
-                        rootlog.info(f"Last chance for {self.condition.description}")
+                        driver.logger.info(
+                            f"Last chance for {self.condition.description}"
+                        )
                     ret = self.condition.check(force=True)
                     if not ret and not last:
-                        rootlog.info(
+                        driver.logger.info(
                             f"({self.condition.description} failure not fatal yet)"
                         )
                     return ret
 
-                with rootlog.nested(f"waiting for {self.condition.description}"):
+                with driver.logger.nested(f"waiting for {self.condition.description}"):
                     retry(condition, timeout=timeout)
 
         if fun_ is None:
diff --git a/nixos/lib/test-driver/test_driver/logger.py b/nixos/lib/test-driver/test_driver/logger.py
index 0b0623bddfa1e..484829254b812 100644
--- a/nixos/lib/test-driver/test_driver/logger.py
+++ b/nixos/lib/test-driver/test_driver/logger.py
@@ -1,33 +1,238 @@
+import atexit
 import codecs
 import os
 import sys
 import time
 import unicodedata
-from contextlib import contextmanager
+from abc import ABC, abstractmethod
+from contextlib import ExitStack, contextmanager
+from pathlib import Path
 from queue import Empty, Queue
-from typing import Any, Dict, Iterator
+from typing import Any, Dict, Iterator, List
 from xml.sax.saxutils import XMLGenerator
 from xml.sax.xmlreader import AttributesImpl
 
 from colorama import Fore, Style
+from junit_xml import TestCase, TestSuite
 
 
-class Logger:
-    def __init__(self) -> None:
-        self.logfile = os.environ.get("LOGFILE", "/dev/null")
-        self.logfile_handle = codecs.open(self.logfile, "wb")
-        self.xml = XMLGenerator(self.logfile_handle, encoding="utf-8")
-        self.queue: "Queue[Dict[str, str]]" = Queue()
+class AbstractLogger(ABC):
+    @abstractmethod
+    def log(self, message: str, attributes: Dict[str, str] = {}) -> None:
+        pass
 
-        self.xml.startDocument()
-        self.xml.startElement("logfile", attrs=AttributesImpl({}))
+    @abstractmethod
+    @contextmanager
+    def subtest(self, name: str, attributes: Dict[str, str] = {}) -> Iterator[None]:
+        pass
+
+    @abstractmethod
+    @contextmanager
+    def nested(self, message: str, attributes: Dict[str, str] = {}) -> Iterator[None]:
+        pass
+
+    @abstractmethod
+    def info(self, *args, **kwargs) -> None:  # type: ignore
+        pass
+
+    @abstractmethod
+    def warning(self, *args, **kwargs) -> None:  # type: ignore
+        pass
+
+    @abstractmethod
+    def error(self, *args, **kwargs) -> None:  # type: ignore
+        pass
+
+    @abstractmethod
+    def log_serial(self, message: str, machine: str) -> None:
+        pass
+
+    @abstractmethod
+    def print_serial_logs(self, enable: bool) -> None:
+        pass
+
+
+class JunitXMLLogger(AbstractLogger):
+    class TestCaseState:
+        def __init__(self) -> None:
+            self.stdout = ""
+            self.stderr = ""
+            self.failure = False
+
+    def __init__(self, outfile: Path) -> None:
+        self.tests: dict[str, JunitXMLLogger.TestCaseState] = {
+            "main": self.TestCaseState()
+        }
+        self.currentSubtest = "main"
+        self.outfile: Path = outfile
+        self._print_serial_logs = True
+        atexit.register(self.close)
+
+    def log(self, message: str, attributes: Dict[str, str] = {}) -> None:
+        self.tests[self.currentSubtest].stdout += message + os.linesep
+
+    @contextmanager
+    def subtest(self, name: str, attributes: Dict[str, str] = {}) -> Iterator[None]:
+        old_test = self.currentSubtest
+        self.tests.setdefault(name, self.TestCaseState())
+        self.currentSubtest = name
+
+        yield
+
+        self.currentSubtest = old_test
+
+    @contextmanager
+    def nested(self, message: str, attributes: Dict[str, str] = {}) -> Iterator[None]:
+        self.log(message)
+        yield
+
+    def info(self, *args, **kwargs) -> None:  # type: ignore
+        self.tests[self.currentSubtest].stdout += args[0] + os.linesep
+
+    def warning(self, *args, **kwargs) -> None:  # type: ignore
+        self.tests[self.currentSubtest].stdout += args[0] + os.linesep
+
+    def error(self, *args, **kwargs) -> None:  # type: ignore
+        self.tests[self.currentSubtest].stderr += args[0] + os.linesep
+        self.tests[self.currentSubtest].failure = True
+
+    def log_serial(self, message: str, machine: str) -> None:
+        if not self._print_serial_logs:
+            return
+
+        self.log(f"{machine} # {message}")
+
+    def print_serial_logs(self, enable: bool) -> None:
+        self._print_serial_logs = enable
+
+    def close(self) -> None:
+        with open(self.outfile, "w") as f:
+            test_cases = []
+            for name, test_case_state in self.tests.items():
+                tc = TestCase(
+                    name,
+                    stdout=test_case_state.stdout,
+                    stderr=test_case_state.stderr,
+                )
+                if test_case_state.failure:
+                    tc.add_failure_info("test case failed")
+
+                test_cases.append(tc)
+            ts = TestSuite("NixOS integration test", test_cases)
+            f.write(TestSuite.to_xml_string([ts]))
+
+
+class CompositeLogger(AbstractLogger):
+    def __init__(self, logger_list: List[AbstractLogger]) -> None:
+        self.logger_list = logger_list
+
+    def add_logger(self, logger: AbstractLogger) -> None:
+        self.logger_list.append(logger)
+
+    def log(self, message: str, attributes: Dict[str, str] = {}) -> None:
+        for logger in self.logger_list:
+            logger.log(message, attributes)
+
+    @contextmanager
+    def subtest(self, name: str, attributes: Dict[str, str] = {}) -> Iterator[None]:
+        with ExitStack() as stack:
+            for logger in self.logger_list:
+                stack.enter_context(logger.subtest(name, attributes))
+            yield
+
+    @contextmanager
+    def nested(self, message: str, attributes: Dict[str, str] = {}) -> Iterator[None]:
+        with ExitStack() as stack:
+            for logger in self.logger_list:
+                stack.enter_context(logger.nested(message, attributes))
+            yield
+
+    def info(self, *args, **kwargs) -> None:  # type: ignore
+        for logger in self.logger_list:
+            logger.info(*args, **kwargs)
+
+    def warning(self, *args, **kwargs) -> None:  # type: ignore
+        for logger in self.logger_list:
+            logger.warning(*args, **kwargs)
+
+    def error(self, *args, **kwargs) -> None:  # type: ignore
+        for logger in self.logger_list:
+            logger.error(*args, **kwargs)
+        sys.exit(1)
 
+    def print_serial_logs(self, enable: bool) -> None:
+        for logger in self.logger_list:
+            logger.print_serial_logs(enable)
+
+    def log_serial(self, message: str, machine: str) -> None:
+        for logger in self.logger_list:
+            logger.log_serial(message, machine)
+
+
+class TerminalLogger(AbstractLogger):
+    def __init__(self) -> None:
         self._print_serial_logs = True
 
+    def maybe_prefix(self, message: str, attributes: Dict[str, str]) -> str:
+        if "machine" in attributes:
+            return f"{attributes['machine']}: {message}"
+        return message
+
     @staticmethod
     def _eprint(*args: object, **kwargs: Any) -> None:
         print(*args, file=sys.stderr, **kwargs)
 
+    def log(self, message: str, attributes: Dict[str, str] = {}) -> None:
+        self._eprint(self.maybe_prefix(message, attributes))
+
+    @contextmanager
+    def subtest(self, name: str, attributes: Dict[str, str] = {}) -> Iterator[None]:
+        with self.nested("subtest: " + name, attributes):
+            yield
+
+    @contextmanager
+    def nested(self, message: str, attributes: Dict[str, str] = {}) -> Iterator[None]:
+        self._eprint(
+            self.maybe_prefix(
+                Style.BRIGHT + Fore.GREEN + message + Style.RESET_ALL, attributes
+            )
+        )
+
+        tic = time.time()
+        yield
+        toc = time.time()
+        self.log(f"(finished: {message}, in {toc - tic:.2f} seconds)")
+
+    def info(self, *args, **kwargs) -> None:  # type: ignore
+        self.log(*args, **kwargs)
+
+    def warning(self, *args, **kwargs) -> None:  # type: ignore
+        self.log(*args, **kwargs)
+
+    def error(self, *args, **kwargs) -> None:  # type: ignore
+        self.log(*args, **kwargs)
+
+    def print_serial_logs(self, enable: bool) -> None:
+        self._print_serial_logs = enable
+
+    def log_serial(self, message: str, machine: str) -> None:
+        if not self._print_serial_logs:
+            return
+
+        self._eprint(Style.DIM + f"{machine} # {message}" + Style.RESET_ALL)
+
+
+class XMLLogger(AbstractLogger):
+    def __init__(self, outfile: str) -> None:
+        self.logfile_handle = codecs.open(outfile, "wb")
+        self.xml = XMLGenerator(self.logfile_handle, encoding="utf-8")
+        self.queue: Queue[dict[str, str]] = Queue()
+
+        self._print_serial_logs = True
+
+        self.xml.startDocument()
+        self.xml.startElement("logfile", attrs=AttributesImpl({}))
+
     def close(self) -> None:
         self.xml.endElement("logfile")
         self.xml.endDocument()
@@ -54,17 +259,19 @@ class Logger:
 
     def error(self, *args, **kwargs) -> None:  # type: ignore
         self.log(*args, **kwargs)
-        sys.exit(1)
 
     def log(self, message: str, attributes: Dict[str, str] = {}) -> None:
-        self._eprint(self.maybe_prefix(message, attributes))
         self.drain_log_queue()
         self.log_line(message, attributes)
 
+    def print_serial_logs(self, enable: bool) -> None:
+        self._print_serial_logs = enable
+
     def log_serial(self, message: str, machine: str) -> None:
+        if not self._print_serial_logs:
+            return
+
         self.enqueue({"msg": message, "machine": machine, "type": "serial"})
-        if self._print_serial_logs:
-            self._eprint(Style.DIM + f"{machine} # {message}" + Style.RESET_ALL)
 
     def enqueue(self, item: Dict[str, str]) -> None:
         self.queue.put(item)
@@ -80,13 +287,12 @@ class Logger:
             pass
 
     @contextmanager
-    def nested(self, message: str, attributes: Dict[str, str] = {}) -> Iterator[None]:
-        self._eprint(
-            self.maybe_prefix(
-                Style.BRIGHT + Fore.GREEN + message + Style.RESET_ALL, attributes
-            )
-        )
+    def subtest(self, name: str, attributes: Dict[str, str] = {}) -> Iterator[None]:
+        with self.nested("subtest: " + name, attributes):
+            yield
 
+    @contextmanager
+    def nested(self, message: str, attributes: Dict[str, str] = {}) -> Iterator[None]:
         self.xml.startElement("nest", attrs=AttributesImpl({}))
         self.xml.startElement("head", attrs=AttributesImpl(attributes))
         self.xml.characters(message)
@@ -100,6 +306,3 @@ class Logger:
         self.log(f"(finished: {message}, in {toc - tic:.2f} seconds)")
 
         self.xml.endElement("nest")
-
-
-rootlog = Logger()
diff --git a/nixos/lib/test-driver/test_driver/machine.py b/nixos/lib/test-driver/test_driver/machine.py
index 652cc600fad59..3a1d5bc1be764 100644
--- a/nixos/lib/test-driver/test_driver/machine.py
+++ b/nixos/lib/test-driver/test_driver/machine.py
@@ -17,7 +17,7 @@ from pathlib import Path
 from queue import Queue
 from typing import Any, Callable, Dict, Iterable, List, Optional, Tuple
 
-from test_driver.logger import rootlog
+from test_driver.logger import AbstractLogger
 
 from .qmp import QMPSession
 
@@ -270,6 +270,7 @@ class Machine:
         out_dir: Path,
         tmp_dir: Path,
         start_command: StartCommand,
+        logger: AbstractLogger,
         name: str = "machine",
         keep_vm_state: bool = False,
         callbacks: Optional[List[Callable]] = None,
@@ -280,6 +281,7 @@ class Machine:
         self.name = name
         self.start_command = start_command
         self.callbacks = callbacks if callbacks is not None else []
+        self.logger = logger
 
         # set up directories
         self.shared_dir = self.tmp_dir / "shared-xchg"
@@ -307,15 +309,15 @@ class Machine:
         return self.booted and self.connected
 
     def log(self, msg: str) -> None:
-        rootlog.log(msg, {"machine": self.name})
+        self.logger.log(msg, {"machine": self.name})
 
     def log_serial(self, msg: str) -> None:
-        rootlog.log_serial(msg, self.name)
+        self.logger.log_serial(msg, self.name)
 
     def nested(self, msg: str, attrs: Dict[str, str] = {}) -> _GeneratorContextManager:
         my_attrs = {"machine": self.name}
         my_attrs.update(attrs)
-        return rootlog.nested(msg, my_attrs)
+        return self.logger.nested(msg, my_attrs)
 
     def wait_for_monitor_prompt(self) -> str:
         assert self.monitor is not None
@@ -1113,8 +1115,8 @@ class Machine:
 
     def cleanup_statedir(self) -> None:
         shutil.rmtree(self.state_dir)
-        rootlog.log(f"deleting VM state directory {self.state_dir}")
-        rootlog.log("if you want to keep the VM state, pass --keep-vm-state")
+        self.logger.log(f"deleting VM state directory {self.state_dir}")
+        self.logger.log("if you want to keep the VM state, pass --keep-vm-state")
 
     def shutdown(self) -> None:
         """
@@ -1221,7 +1223,7 @@ class Machine:
     def release(self) -> None:
         if self.pid is None:
             return
-        rootlog.info(f"kill machine (pid {self.pid})")
+        self.logger.info(f"kill machine (pid {self.pid})")
         assert self.process
         assert self.shell
         assert self.monitor
diff --git a/nixos/lib/test-driver/test_driver/polling_condition.py b/nixos/lib/test-driver/test_driver/polling_condition.py
index 12cbad69e34e9..1cccaf2c71e74 100644
--- a/nixos/lib/test-driver/test_driver/polling_condition.py
+++ b/nixos/lib/test-driver/test_driver/polling_condition.py
@@ -2,7 +2,7 @@ import time
 from math import isfinite
 from typing import Callable, Optional
 
-from .logger import rootlog
+from test_driver.logger import AbstractLogger
 
 
 class PollingConditionError(Exception):
@@ -13,6 +13,7 @@ class PollingCondition:
     condition: Callable[[], bool]
     seconds_interval: float
     description: Optional[str]
+    logger: AbstractLogger
 
     last_called: float
     entry_count: int
@@ -20,11 +21,13 @@ class PollingCondition:
     def __init__(
         self,
         condition: Callable[[], Optional[bool]],
+        logger: AbstractLogger,
         seconds_interval: float = 2.0,
         description: Optional[str] = None,
     ):
         self.condition = condition  # type: ignore
         self.seconds_interval = seconds_interval
+        self.logger = logger
 
         if description is None:
             if condition.__doc__:
@@ -41,7 +44,7 @@ class PollingCondition:
         if (self.entered or not self.overdue) and not force:
             return True
 
-        with self, rootlog.nested(self.nested_message):
+        with self, self.logger.nested(self.nested_message):
             time_since_last = time.monotonic() - self.last_called
             last_message = (
                 f"Time since last: {time_since_last:.2f}s"
@@ -49,13 +52,13 @@ class PollingCondition:
                 else "(not called yet)"
             )
 
-            rootlog.info(last_message)
+            self.logger.info(last_message)
             try:
                 res = self.condition()  # type: ignore
             except Exception:
                 res = False
             res = res is None or res
-            rootlog.info(self.status_message(res))
+            self.logger.info(self.status_message(res))
             return res
 
     def maybe_raise(self) -> None:
diff --git a/nixos/lib/test-driver/test_driver/vlan.py b/nixos/lib/test-driver/test_driver/vlan.py
index ec9679108e58d..9340fc92ed4c4 100644
--- a/nixos/lib/test-driver/test_driver/vlan.py
+++ b/nixos/lib/test-driver/test_driver/vlan.py
@@ -4,7 +4,7 @@ import pty
 import subprocess
 from pathlib import Path
 
-from test_driver.logger import rootlog
+from test_driver.logger import AbstractLogger
 
 
 class VLan:
@@ -19,17 +19,20 @@ class VLan:
     pid: int
     fd: io.TextIOBase
 
+    logger: AbstractLogger
+
     def __repr__(self) -> str:
         return f"<Vlan Nr. {self.nr}>"
 
-    def __init__(self, nr: int, tmp_dir: Path):
+    def __init__(self, nr: int, tmp_dir: Path, logger: AbstractLogger):
         self.nr = nr
         self.socket_dir = tmp_dir / f"vde{self.nr}.ctl"
+        self.logger = logger
 
         # TODO: don't side-effect environment here
         os.environ[f"QEMU_VDE_SOCKET_{self.nr}"] = str(self.socket_dir)
 
-        rootlog.info("start vlan")
+        self.logger.info("start vlan")
         pty_master, pty_slave = pty.openpty()
 
         # The --hub is required for the scenario determined by
@@ -52,11 +55,11 @@ class VLan:
         assert self.process.stdout is not None
         self.process.stdout.readline()
         if not (self.socket_dir / "ctl").exists():
-            rootlog.error("cannot start vde_switch")
+            self.logger.error("cannot start vde_switch")
 
-        rootlog.info(f"running vlan (pid {self.pid}; ctl {self.socket_dir})")
+        self.logger.info(f"running vlan (pid {self.pid}; ctl {self.socket_dir})")
 
     def __del__(self) -> None:
-        rootlog.info(f"kill vlan (pid {self.pid})")
+        self.logger.info(f"kill vlan (pid {self.pid})")
         self.fd.close()
         self.process.terminate()
diff --git a/nixos/lib/test-script-prepend.py b/nixos/lib/test-script-prepend.py
index 976992ea00158..9d2efdf973031 100644
--- a/nixos/lib/test-script-prepend.py
+++ b/nixos/lib/test-script-prepend.py
@@ -4,7 +4,7 @@
 from test_driver.driver import Driver
 from test_driver.vlan import VLan
 from test_driver.machine import Machine
-from test_driver.logger import Logger
+from test_driver.logger import AbstractLogger
 from typing import Callable, Iterator, ContextManager, Optional, List, Dict, Any, Union
 from typing_extensions import Protocol
 from pathlib import Path
@@ -44,7 +44,7 @@ test_script: Callable[[], None]
 machines: List[Machine]
 vlans: List[VLan]
 driver: Driver
-log: Logger
+log: AbstractLogger
 create_machine: CreateMachineProtocol
 run_tests: Callable[[], None]
 join_all: Callable[[], None]
diff --git a/nixos/lib/testing/driver.nix b/nixos/lib/testing/driver.nix
index 7eb06e023918b..d4f8e0f0c6e38 100644
--- a/nixos/lib/testing/driver.nix
+++ b/nixos/lib/testing/driver.nix
@@ -139,7 +139,7 @@ in
     enableOCR = mkOption {
       description = ''
         Whether to enable Optical Character Recognition functionality for
-        testing graphical programs. See [Machine objects](`ssec-machine-objects`).
+        testing graphical programs. See [`Machine objects`](#ssec-machine-objects).
       '';
       type = types.bool;
       default = false;
diff --git a/nixos/modules/config/nsswitch.nix b/nixos/modules/config/nsswitch.nix
index c7ba9b8eec6a2..fe0402ee9e666 100644
--- a/nixos/modules/config/nsswitch.nix
+++ b/nixos/modules/config/nsswitch.nix
@@ -12,7 +12,7 @@ with lib;
     system.nssModules = mkOption {
       type = types.listOf types.path;
       internal = true;
-      default = [];
+      default = [ ];
       description = ''
         Search path for NSS (Name Service Switch) modules.  This allows
         several DNS resolution methods to be specified via
@@ -35,7 +35,7 @@ with lib;
 
           This option only takes effect if nscd is enabled.
         '';
-        default = [];
+        default = [ ];
       };
 
       group = mkOption {
@@ -47,7 +47,7 @@ with lib;
 
           This option only takes effect if nscd is enabled.
         '';
-        default = [];
+        default = [ ];
       };
 
       shadow = mkOption {
@@ -59,7 +59,19 @@ with lib;
 
           This option only takes effect if nscd is enabled.
         '';
-        default = [];
+        default = [ ];
+      };
+
+      sudoers = mkOption {
+        type = types.listOf types.str;
+        description = ''
+          List of sudoers entries to configure in {file}`/etc/nsswitch.conf`.
+
+          Note that "files" is always prepended.
+
+          This option only takes effect if nscd is enabled.
+        '';
+        default = [ ];
       };
 
       hosts = mkOption {
@@ -71,7 +83,7 @@ with lib;
 
           This option only takes effect if nscd is enabled.
         '';
-        default = [];
+        default = [ ];
       };
 
       services = mkOption {
@@ -83,7 +95,7 @@ with lib;
 
           This option only takes effect if nscd is enabled.
         '';
-        default = [];
+        default = [ ];
       };
     };
   };
@@ -112,6 +124,7 @@ with lib;
       passwd:    ${concatStringsSep " " config.system.nssDatabases.passwd}
       group:     ${concatStringsSep " " config.system.nssDatabases.group}
       shadow:    ${concatStringsSep " " config.system.nssDatabases.shadow}
+      sudoers:   ${concatStringsSep " " config.system.nssDatabases.sudoers}
 
       hosts:     ${concatStringsSep " " config.system.nssDatabases.hosts}
       networks:  files
@@ -126,6 +139,7 @@ with lib;
       passwd = mkBefore [ "files" ];
       group = mkBefore [ "files" ];
       shadow = mkBefore [ "files" ];
+      sudoers = mkBefore [ "files" ];
       hosts = mkMerge [
         (mkOrder 998 [ "files" ])
         (mkOrder 1499 [ "dns" ])
diff --git a/nixos/modules/hardware/video/nvidia.nix b/nixos/modules/hardware/video/nvidia.nix
index 37d8e53a2e049..949b1e346269e 100644
--- a/nixos/modules/hardware/video/nvidia.nix
+++ b/nixos/modules/hardware/video/nvidia.nix
@@ -3,12 +3,10 @@
   lib,
   pkgs,
   ...
-}: let
+}:
+let
   nvidiaEnabled = (lib.elem "nvidia" config.services.xserver.videoDrivers);
-  nvidia_x11 =
-    if nvidiaEnabled || cfg.datacenter.enable
-    then cfg.package
-    else null;
+  nvidia_x11 = if nvidiaEnabled || cfg.datacenter.enable then cfg.package else null;
 
   cfg = config.hardware.nvidia;
 
@@ -19,8 +17,9 @@
   primeEnabled = syncCfg.enable || reverseSyncCfg.enable || offloadCfg.enable;
   busIDType = lib.types.strMatching "([[:print:]]+[\:\@][0-9]{1,3}\:[0-9]{1,2}\:[0-9])?";
   ibtSupport = cfg.open || (nvidia_x11.ibtSupport or false);
-  settingsFormat = pkgs.formats.keyValue {};
-in {
+  settingsFormat = pkgs.formats.keyValue { };
+in
+{
   options = {
     hardware.nvidia = {
       datacenter.enable = lib.mkEnableOption ''
@@ -29,50 +28,50 @@ in {
       datacenter.settings = lib.mkOption {
         type = settingsFormat.type;
         default = {
-          LOG_LEVEL=4;
-          LOG_FILE_NAME="/var/log/fabricmanager.log";
-          LOG_APPEND_TO_LOG=1;
-          LOG_FILE_MAX_SIZE=1024;
-          LOG_USE_SYSLOG=0;
-          DAEMONIZE=1;
-          BIND_INTERFACE_IP="127.0.0.1";
-          STARTING_TCP_PORT=16000;
-          FABRIC_MODE=0;
-          FABRIC_MODE_RESTART=0;
-          STATE_FILE_NAME="/var/tmp/fabricmanager.state";
-          FM_CMD_BIND_INTERFACE="127.0.0.1";
-          FM_CMD_PORT_NUMBER=6666;
-          FM_STAY_RESIDENT_ON_FAILURES=0;
-          ACCESS_LINK_FAILURE_MODE=0;
-          TRUNK_LINK_FAILURE_MODE=0;
-          NVSWITCH_FAILURE_MODE=0;
-          ABORT_CUDA_JOBS_ON_FM_EXIT=1;
-          TOPOLOGY_FILE_PATH="${nvidia_x11.fabricmanager}/share/nvidia-fabricmanager/nvidia/nvswitch";
-          DATABASE_PATH="${nvidia_x11.fabricmanager}/share/nvidia-fabricmanager/nvidia/nvswitch";
+          LOG_LEVEL = 4;
+          LOG_FILE_NAME = "/var/log/fabricmanager.log";
+          LOG_APPEND_TO_LOG = 1;
+          LOG_FILE_MAX_SIZE = 1024;
+          LOG_USE_SYSLOG = 0;
+          DAEMONIZE = 1;
+          BIND_INTERFACE_IP = "127.0.0.1";
+          STARTING_TCP_PORT = 16000;
+          FABRIC_MODE = 0;
+          FABRIC_MODE_RESTART = 0;
+          STATE_FILE_NAME = "/var/tmp/fabricmanager.state";
+          FM_CMD_BIND_INTERFACE = "127.0.0.1";
+          FM_CMD_PORT_NUMBER = 6666;
+          FM_STAY_RESIDENT_ON_FAILURES = 0;
+          ACCESS_LINK_FAILURE_MODE = 0;
+          TRUNK_LINK_FAILURE_MODE = 0;
+          NVSWITCH_FAILURE_MODE = 0;
+          ABORT_CUDA_JOBS_ON_FM_EXIT = 1;
+          TOPOLOGY_FILE_PATH = "${nvidia_x11.fabricmanager}/share/nvidia-fabricmanager/nvidia/nvswitch";
+          DATABASE_PATH = "${nvidia_x11.fabricmanager}/share/nvidia-fabricmanager/nvidia/nvswitch";
         };
         defaultText = lib.literalExpression ''
-        {
-          LOG_LEVEL=4;
-          LOG_FILE_NAME="/var/log/fabricmanager.log";
-          LOG_APPEND_TO_LOG=1;
-          LOG_FILE_MAX_SIZE=1024;
-          LOG_USE_SYSLOG=0;
-          DAEMONIZE=1;
-          BIND_INTERFACE_IP="127.0.0.1";
-          STARTING_TCP_PORT=16000;
-          FABRIC_MODE=0;
-          FABRIC_MODE_RESTART=0;
-          STATE_FILE_NAME="/var/tmp/fabricmanager.state";
-          FM_CMD_BIND_INTERFACE="127.0.0.1";
-          FM_CMD_PORT_NUMBER=6666;
-          FM_STAY_RESIDENT_ON_FAILURES=0;
-          ACCESS_LINK_FAILURE_MODE=0;
-          TRUNK_LINK_FAILURE_MODE=0;
-          NVSWITCH_FAILURE_MODE=0;
-          ABORT_CUDA_JOBS_ON_FM_EXIT=1;
-          TOPOLOGY_FILE_PATH="''${nvidia_x11.fabricmanager}/share/nvidia-fabricmanager/nvidia/nvswitch";
-          DATABASE_PATH="''${nvidia_x11.fabricmanager}/share/nvidia-fabricmanager/nvidia/nvswitch";
-        }
+          {
+            LOG_LEVEL=4;
+            LOG_FILE_NAME="/var/log/fabricmanager.log";
+            LOG_APPEND_TO_LOG=1;
+            LOG_FILE_MAX_SIZE=1024;
+            LOG_USE_SYSLOG=0;
+            DAEMONIZE=1;
+            BIND_INTERFACE_IP="127.0.0.1";
+            STARTING_TCP_PORT=16000;
+            FABRIC_MODE=0;
+            FABRIC_MODE_RESTART=0;
+            STATE_FILE_NAME="/var/tmp/fabricmanager.state";
+            FM_CMD_BIND_INTERFACE="127.0.0.1";
+            FM_CMD_PORT_NUMBER=6666;
+            FM_STAY_RESIDENT_ON_FAILURES=0;
+            ACCESS_LINK_FAILURE_MODE=0;
+            TRUNK_LINK_FAILURE_MODE=0;
+            NVSWITCH_FAILURE_MODE=0;
+            ABORT_CUDA_JOBS_ON_FM_EXIT=1;
+            TOPOLOGY_FILE_PATH="''${nvidia_x11.fabricmanager}/share/nvidia-fabricmanager/nvidia/nvswitch";
+            DATABASE_PATH="''${nvidia_x11.fabricmanager}/share/nvidia-fabricmanager/nvidia/nvswitch";
+          }
         '';
         description = ''
           Additional configuration options for fabricmanager.
@@ -211,7 +210,9 @@ in {
         (lib.mkEnableOption ''
           nvidia-settings, NVIDIA's GUI configuration tool
         '')
-        // {default = true;};
+        // {
+          default = true;
+        };
 
       nvidiaPersistenced = lib.mkEnableOption ''
         nvidia-persistenced a update for NVIDIA GPU headless mode, i.e.
@@ -226,7 +227,8 @@ in {
       '';
 
       package = lib.mkOption {
-        default = config.boot.kernelPackages.nvidiaPackages."${if cfg.datacenter.enable then "dc" else "stable"}";
+        default =
+          config.boot.kernelPackages.nvidiaPackages."${if cfg.datacenter.enable then "dc" else "stable"}";
         defaultText = lib.literalExpression ''
           config.boot.kernelPackages.nvidiaPackages."\$\{if cfg.datacenter.enable then "dc" else "stable"}"
         '';
@@ -242,403 +244,404 @@ in {
     };
   };
 
-  config = let
-    igpuDriver =
-      if pCfg.intelBusId != ""
-      then "modesetting"
-      else "amdgpu";
-    igpuBusId =
-      if pCfg.intelBusId != ""
-      then pCfg.intelBusId
-      else pCfg.amdgpuBusId;
-  in
-    lib.mkIf (nvidia_x11 != null) (lib.mkMerge [
-      # Common
-      ({
-        assertions = [
-          {
-            assertion = !(nvidiaEnabled && cfg.datacenter.enable);
-            message = "You cannot configure both X11 and Data Center drivers at the same time.";
-          }
-        ];
-        boot = {
-          blacklistedKernelModules = ["nouveau" "nvidiafb"];
-
-          # Don't add `nvidia-uvm` to `kernelModules`, because we want
-          # `nvidia-uvm` be loaded only after `udev` rules for `nvidia` kernel
-          # module are applied.
-          #
-          # Instead, we use `softdep` to lazily load `nvidia-uvm` kernel module
-          # after `nvidia` kernel module is loaded and `udev` rules are applied.
-          extraModprobeConfig = ''
-            softdep nvidia post: nvidia-uvm
-          '';
-        };
-        systemd.tmpfiles.rules =
-          lib.optional config.virtualisation.docker.enableNvidia
-            "L+ /run/nvidia-docker/bin - - - - ${nvidia_x11.bin}/origBin";
-        services.udev.extraRules =
-        ''
-          # Create /dev/nvidia-uvm when the nvidia-uvm module is loaded.
-          KERNEL=="nvidia", RUN+="${pkgs.runtimeShell} -c 'mknod -m 666 /dev/nvidiactl c 195 255'"
-          KERNEL=="nvidia", RUN+="${pkgs.runtimeShell} -c 'for i in $$(cat /proc/driver/nvidia/gpus/*/information | grep Minor | cut -d \  -f 4); do mknod -m 666 /dev/nvidia$${i} c 195 $${i}; done'"
-          KERNEL=="nvidia_modeset", RUN+="${pkgs.runtimeShell} -c 'mknod -m 666 /dev/nvidia-modeset c 195 254'"
-          KERNEL=="nvidia_uvm", RUN+="${pkgs.runtimeShell} -c 'mknod -m 666 /dev/nvidia-uvm c $$(grep nvidia-uvm /proc/devices | cut -d \  -f 1) 0'"
-          KERNEL=="nvidia_uvm", RUN+="${pkgs.runtimeShell} -c 'mknod -m 666 /dev/nvidia-uvm-tools c $$(grep nvidia-uvm /proc/devices | cut -d \  -f 1) 1'"
-        '';
-        hardware.opengl = {
-          extraPackages = [
-            nvidia_x11.out
-          ];
-          extraPackages32 = [
-            nvidia_x11.lib32
+  config =
+    let
+      igpuDriver = if pCfg.intelBusId != "" then "modesetting" else "amdgpu";
+      igpuBusId = if pCfg.intelBusId != "" then pCfg.intelBusId else pCfg.amdgpuBusId;
+    in
+    lib.mkIf (nvidia_x11 != null) (
+      lib.mkMerge [
+        # Common
+        ({
+          assertions = [
+            {
+              assertion = !(nvidiaEnabled && cfg.datacenter.enable);
+              message = "You cannot configure both X11 and Data Center drivers at the same time.";
+            }
           ];
-        };
-        environment.systemPackages = [
-          nvidia_x11.bin
-        ];
-      })
-      # X11
-      (lib.mkIf nvidiaEnabled {
-        assertions = [
-        {
-          assertion = primeEnabled -> pCfg.intelBusId == "" || pCfg.amdgpuBusId == "";
-          message = "You cannot configure both an Intel iGPU and an AMD APU. Pick the one corresponding to your processor.";
-        }
-
-        {
-          assertion = offloadCfg.enableOffloadCmd -> offloadCfg.enable || reverseSyncCfg.enable;
-          message = "Offload command requires offloading or reverse prime sync to be enabled.";
-        }
-
-        {
-          assertion = primeEnabled -> pCfg.nvidiaBusId != "" && (pCfg.intelBusId != "" || pCfg.amdgpuBusId != "");
-          message = "When NVIDIA PRIME is enabled, the GPU bus IDs must be configured.";
-        }
-
-        {
-          assertion = offloadCfg.enable -> lib.versionAtLeast nvidia_x11.version "435.21";
-          message = "NVIDIA PRIME render offload is currently only supported on versions >= 435.21.";
-        }
-
-        {
-          assertion = (reverseSyncCfg.enable && pCfg.amdgpuBusId != "") -> lib.versionAtLeast nvidia_x11.version "470.0";
-          message = "NVIDIA PRIME render offload for AMD APUs is currently only supported on versions >= 470 beta.";
-        }
-
-        {
-          assertion = !(syncCfg.enable && offloadCfg.enable);
-          message = "PRIME Sync and Offload cannot be both enabled";
-        }
-
-        {
-          assertion = !(syncCfg.enable && reverseSyncCfg.enable);
-          message = "PRIME Sync and PRIME Reverse Sync cannot be both enabled";
-        }
-
-        {
-          assertion = !(syncCfg.enable && cfg.powerManagement.finegrained);
-          message = "Sync precludes powering down the NVIDIA GPU.";
-        }
-
-        {
-          assertion = cfg.powerManagement.finegrained -> offloadCfg.enable;
-          message = "Fine-grained power management requires offload to be enabled.";
-        }
-
-        {
-          assertion = cfg.powerManagement.enable -> lib.versionAtLeast nvidia_x11.version "430.09";
-          message = "Required files for driver based power management only exist on versions >= 430.09.";
-        }
-
-        {
-          assertion = cfg.open -> (cfg.package ? open && cfg.package ? firmware);
-          message = "This version of NVIDIA driver does not provide a corresponding opensource kernel driver";
-        }
-
-        {
-          assertion = cfg.dynamicBoost.enable -> lib.versionAtLeast nvidia_x11.version "510.39.01";
-          message = "NVIDIA's Dynamic Boost feature only exists on versions >= 510.39.01";
-        }];
-
-        # If Optimus/PRIME is enabled, we:
-        # - Specify the configured NVIDIA GPU bus ID in the Device section for the
-        #   "nvidia" driver.
-        # - Add the AllowEmptyInitialConfiguration option to the Screen section for the
-        #   "nvidia" driver, in order to allow the X server to start without any outputs.
-        # - Add a separate Device section for the Intel GPU, using the "modesetting"
-        #   driver and with the configured BusID.
-        # - OR add a separate Device section for the AMD APU, using the "amdgpu"
-        #   driver and with the configures BusID.
-        # - Reference that Device section from the ServerLayout section as an inactive
-        #   device.
-        # - Configure the display manager to run specific `xrandr` commands which will
-        #   configure/enable displays connected to the Intel iGPU / AMD APU.
-
-        # reverse sync implies offloading
-        hardware.nvidia.prime.offload.enable = lib.mkDefault reverseSyncCfg.enable;
-
-        services.xserver.drivers =
-          lib.optional primeEnabled {
-            name = igpuDriver;
-            display = offloadCfg.enable;
-            modules = lib.optional (igpuDriver == "amdgpu") pkgs.xorg.xf86videoamdgpu;
-            deviceSection =
-              ''
-                BusID "${igpuBusId}"
-              ''
-              + lib.optionalString (syncCfg.enable && igpuDriver != "amdgpu") ''
-                Option "AccelMethod" "none"
-              '';
-          }
-          ++ lib.singleton {
-            name = "nvidia";
-            modules = [nvidia_x11.bin];
-            display = !offloadCfg.enable;
-            deviceSection =
-              ''
-                Option "SidebandSocketPath" "/run/nvidia-xdriver/"
-              '' +
-              lib.optionalString primeEnabled
-              ''
-                BusID "${pCfg.nvidiaBusId}"
-              ''
-              + lib.optionalString pCfg.allowExternalGpu ''
-                Option "AllowExternalGpus"
-              '';
-            screenSection =
-              ''
-                Option "RandRRotation" "on"
-              ''
-              + lib.optionalString syncCfg.enable ''
-                Option "AllowEmptyInitialConfiguration"
-              ''
-              + lib.optionalString cfg.forceFullCompositionPipeline ''
-                Option         "metamodes" "nvidia-auto-select +0+0 {ForceFullCompositionPipeline=On}"
-                Option         "AllowIndirectGLXProtocol" "off"
-                Option         "TripleBuffer" "on"
-              '';
+          boot = {
+            blacklistedKernelModules = [
+              "nouveau"
+              "nvidiafb"
+            ];
+
+            # Don't add `nvidia-uvm` to `kernelModules`, because we want
+            # `nvidia-uvm` be loaded only after `udev` rules for `nvidia` kernel
+            # module are applied.
+            #
+            # Instead, we use `softdep` to lazily load `nvidia-uvm` kernel module
+            # after `nvidia` kernel module is loaded and `udev` rules are applied.
+            extraModprobeConfig = ''
+              softdep nvidia post: nvidia-uvm
+            '';
           };
-
-        services.xserver.serverLayoutSection =
-          lib.optionalString syncCfg.enable ''
-            Inactive "Device-${igpuDriver}[0]"
-          ''
-          + lib.optionalString reverseSyncCfg.enable ''
-            Inactive "Device-nvidia[0]"
-          ''
-          + lib.optionalString offloadCfg.enable ''
-            Option "AllowNVIDIAGPUScreens"
+          systemd.tmpfiles.rules = lib.optional config.virtualisation.docker.enableNvidia "L+ /run/nvidia-docker/bin - - - - ${nvidia_x11.bin}/origBin";
+          services.udev.extraRules = ''
+            # Create /dev/nvidia-uvm when the nvidia-uvm module is loaded.
+            KERNEL=="nvidia", RUN+="${pkgs.runtimeShell} -c 'mknod -m 666 /dev/nvidiactl c 195 255'"
+            KERNEL=="nvidia", RUN+="${pkgs.runtimeShell} -c 'for i in $$(cat /proc/driver/nvidia/gpus/*/information | grep Minor | cut -d \  -f 4); do mknod -m 666 /dev/nvidia$${i} c 195 $${i}; done'"
+            KERNEL=="nvidia_modeset", RUN+="${pkgs.runtimeShell} -c 'mknod -m 666 /dev/nvidia-modeset c 195 254'"
+            KERNEL=="nvidia_uvm", RUN+="${pkgs.runtimeShell} -c 'mknod -m 666 /dev/nvidia-uvm c $$(grep nvidia-uvm /proc/devices | cut -d \  -f 1) 0'"
+            KERNEL=="nvidia_uvm", RUN+="${pkgs.runtimeShell} -c 'mknod -m 666 /dev/nvidia-uvm-tools c $$(grep nvidia-uvm /proc/devices | cut -d \  -f 1) 1'"
           '';
+          hardware.opengl = {
+            extraPackages = [ nvidia_x11.out nvidia_x11.settings.libXNVCtrl ];
+            extraPackages32 = [ nvidia_x11.lib32 ];
+          };
+          environment.systemPackages = [ nvidia_x11.bin ];
+        })
+        # X11
+        (lib.mkIf nvidiaEnabled {
+          assertions = [
+            {
+              assertion = primeEnabled -> pCfg.intelBusId == "" || pCfg.amdgpuBusId == "";
+              message = "You cannot configure both an Intel iGPU and an AMD APU. Pick the one corresponding to your processor.";
+            }
+
+            {
+              assertion = offloadCfg.enableOffloadCmd -> offloadCfg.enable || reverseSyncCfg.enable;
+              message = "Offload command requires offloading or reverse prime sync to be enabled.";
+            }
+
+            {
+              assertion =
+                primeEnabled -> pCfg.nvidiaBusId != "" && (pCfg.intelBusId != "" || pCfg.amdgpuBusId != "");
+              message = "When NVIDIA PRIME is enabled, the GPU bus IDs must be configured.";
+            }
+
+            {
+              assertion = offloadCfg.enable -> lib.versionAtLeast nvidia_x11.version "435.21";
+              message = "NVIDIA PRIME render offload is currently only supported on versions >= 435.21.";
+            }
+
+            {
+              assertion =
+                (reverseSyncCfg.enable && pCfg.amdgpuBusId != "") -> lib.versionAtLeast nvidia_x11.version "470.0";
+              message = "NVIDIA PRIME render offload for AMD APUs is currently only supported on versions >= 470 beta.";
+            }
+
+            {
+              assertion = !(syncCfg.enable && offloadCfg.enable);
+              message = "PRIME Sync and Offload cannot be both enabled";
+            }
+
+            {
+              assertion = !(syncCfg.enable && reverseSyncCfg.enable);
+              message = "PRIME Sync and PRIME Reverse Sync cannot be both enabled";
+            }
+
+            {
+              assertion = !(syncCfg.enable && cfg.powerManagement.finegrained);
+              message = "Sync precludes powering down the NVIDIA GPU.";
+            }
+
+            {
+              assertion = cfg.powerManagement.finegrained -> offloadCfg.enable;
+              message = "Fine-grained power management requires offload to be enabled.";
+            }
+
+            {
+              assertion = cfg.powerManagement.enable -> lib.versionAtLeast nvidia_x11.version "430.09";
+              message = "Required files for driver based power management only exist on versions >= 430.09.";
+            }
+
+            {
+              assertion = cfg.open -> (cfg.package ? open && cfg.package ? firmware);
+              message = "This version of NVIDIA driver does not provide a corresponding opensource kernel driver";
+            }
+
+            {
+              assertion = cfg.dynamicBoost.enable -> lib.versionAtLeast nvidia_x11.version "510.39.01";
+              message = "NVIDIA's Dynamic Boost feature only exists on versions >= 510.39.01";
+            }
+          ];
 
-        services.xserver.displayManager.setupCommands = let
-          gpuProviderName =
-            if igpuDriver == "amdgpu"
-            then
-              # find the name of the provider if amdgpu
-              "`${lib.getExe pkgs.xorg.xrandr} --listproviders | ${lib.getExe pkgs.gnugrep} -i AMD | ${lib.getExe pkgs.gnused} -n 's/^.*name://p'`"
-            else igpuDriver;
-          providerCmdParams =
-            if syncCfg.enable
-            then "\"${gpuProviderName}\" NVIDIA-0"
-            else "NVIDIA-G0 \"${gpuProviderName}\"";
-        in
-          lib.optionalString (syncCfg.enable || reverseSyncCfg.enable) ''
-            # Added by nvidia configuration module for Optimus/PRIME.
-            ${lib.getExe pkgs.xorg.xrandr} --setprovideroutputsource ${providerCmdParams}
-            ${lib.getExe pkgs.xorg.xrandr} --auto
-          '';
+          # If Optimus/PRIME is enabled, we:
+          # - Specify the configured NVIDIA GPU bus ID in the Device section for the
+          #   "nvidia" driver.
+          # - Add the AllowEmptyInitialConfiguration option to the Screen section for the
+          #   "nvidia" driver, in order to allow the X server to start without any outputs.
+          # - Add a separate Device section for the Intel GPU, using the "modesetting"
+          #   driver and with the configured BusID.
+          # - OR add a separate Device section for the AMD APU, using the "amdgpu"
+          #   driver and with the configures BusID.
+          # - Reference that Device section from the ServerLayout section as an inactive
+          #   device.
+          # - Configure the display manager to run specific `xrandr` commands which will
+          #   configure/enable displays connected to the Intel iGPU / AMD APU.
+
+          # reverse sync implies offloading
+          hardware.nvidia.prime.offload.enable = lib.mkDefault reverseSyncCfg.enable;
+
+          services.xserver.drivers =
+            lib.optional primeEnabled {
+              name = igpuDriver;
+              display = offloadCfg.enable;
+              modules = lib.optional (igpuDriver == "amdgpu") pkgs.xorg.xf86videoamdgpu;
+              deviceSection =
+                ''
+                  BusID "${igpuBusId}"
+                ''
+                + lib.optionalString (syncCfg.enable && igpuDriver != "amdgpu") ''
+                  Option "AccelMethod" "none"
+                '';
+            }
+            ++ lib.singleton {
+              name = "nvidia";
+              modules = [ nvidia_x11.bin ];
+              display = !offloadCfg.enable;
+              deviceSection =
+                ''
+                  Option "SidebandSocketPath" "/run/nvidia-xdriver/"
+                ''
+                + lib.optionalString primeEnabled ''
+                  BusID "${pCfg.nvidiaBusId}"
+                ''
+                + lib.optionalString pCfg.allowExternalGpu ''
+                  Option "AllowExternalGpus"
+                '';
+              screenSection =
+                ''
+                  Option "RandRRotation" "on"
+                ''
+                + lib.optionalString syncCfg.enable ''
+                  Option "AllowEmptyInitialConfiguration"
+                ''
+                + lib.optionalString cfg.forceFullCompositionPipeline ''
+                  Option         "metamodes" "nvidia-auto-select +0+0 {ForceFullCompositionPipeline=On}"
+                  Option         "AllowIndirectGLXProtocol" "off"
+                  Option         "TripleBuffer" "on"
+                '';
+            };
 
-        environment.etc = {
-          "nvidia/nvidia-application-profiles-rc" = lib.mkIf nvidia_x11.useProfiles {source = "${nvidia_x11.bin}/share/nvidia/nvidia-application-profiles-rc";};
+          services.xserver.serverLayoutSection =
+            lib.optionalString syncCfg.enable ''
+              Inactive "Device-${igpuDriver}[0]"
+            ''
+            + lib.optionalString reverseSyncCfg.enable ''
+              Inactive "Device-nvidia[0]"
+            ''
+            + lib.optionalString offloadCfg.enable ''
+              Option "AllowNVIDIAGPUScreens"
+            '';
+
+          services.xserver.displayManager.setupCommands =
+            let
+              gpuProviderName =
+                if igpuDriver == "amdgpu" then
+                  # find the name of the provider if amdgpu
+                  "`${lib.getExe pkgs.xorg.xrandr} --listproviders | ${lib.getExe pkgs.gnugrep} -i AMD | ${lib.getExe pkgs.gnused} -n 's/^.*name://p'`"
+                else
+                  igpuDriver;
+              providerCmdParams =
+                if syncCfg.enable then "\"${gpuProviderName}\" NVIDIA-0" else "NVIDIA-G0 \"${gpuProviderName}\"";
+            in
+            lib.optionalString (syncCfg.enable || reverseSyncCfg.enable) ''
+              # Added by nvidia configuration module for Optimus/PRIME.
+              ${lib.getExe pkgs.xorg.xrandr} --setprovideroutputsource ${providerCmdParams}
+              ${lib.getExe pkgs.xorg.xrandr} --auto
+            '';
+
+          environment.etc = {
+            "nvidia/nvidia-application-profiles-rc" = lib.mkIf nvidia_x11.useProfiles {
+              source = "${nvidia_x11.bin}/share/nvidia/nvidia-application-profiles-rc";
+            };
 
-          # 'nvidia_x11' installs it's files to /run/opengl-driver/...
-          "egl/egl_external_platform.d".source = "/run/opengl-driver/share/egl/egl_external_platform.d/";
-        };
+            # 'nvidia_x11' installs it's files to /run/opengl-driver/...
+            "egl/egl_external_platform.d".source = "/run/opengl-driver/share/egl/egl_external_platform.d/";
+          };
 
-        hardware.opengl = {
-          extraPackages = [
-            pkgs.nvidia-vaapi-driver
-          ];
-          extraPackages32 = [
-            pkgs.pkgsi686Linux.nvidia-vaapi-driver
-          ];
-        };
-        environment.systemPackages =
-          lib.optional cfg.nvidiaSettings nvidia_x11.settings
-          ++ lib.optional cfg.nvidiaPersistenced nvidia_x11.persistenced
-          ++ lib.optional offloadCfg.enableOffloadCmd
-          (pkgs.writeShellScriptBin "nvidia-offload" ''
-            export __NV_PRIME_RENDER_OFFLOAD=1
-            export __NV_PRIME_RENDER_OFFLOAD_PROVIDER=NVIDIA-G0
-            export __GLX_VENDOR_LIBRARY_NAME=nvidia
-            export __VK_LAYER_NV_optimus=NVIDIA_only
-            exec "$@"
-          '');
-
-        systemd.packages = lib.optional cfg.powerManagement.enable nvidia_x11.out;
-
-        systemd.services = let
-          nvidiaService = state: {
-            description = "NVIDIA system ${state} actions";
-            path = [pkgs.kbd];
-            serviceConfig = {
-              Type = "oneshot";
-              ExecStart = "${nvidia_x11.out}/bin/nvidia-sleep.sh '${state}'";
-            };
-            before = ["systemd-${state}.service"];
-            requiredBy = ["systemd-${state}.service"];
+          hardware.opengl = {
+            extraPackages = [ pkgs.nvidia-vaapi-driver ];
+            extraPackages32 = [ pkgs.pkgsi686Linux.nvidia-vaapi-driver ];
           };
-        in
-          lib.mkMerge [
-            (lib.mkIf cfg.powerManagement.enable {
-              nvidia-suspend = nvidiaService "suspend";
-              nvidia-hibernate = nvidiaService "hibernate";
-              nvidia-resume =
-                (nvidiaService "resume")
-                // {
-                  before = [];
-                  after = ["systemd-suspend.service" "systemd-hibernate.service"];
-                  requiredBy = ["systemd-suspend.service" "systemd-hibernate.service"];
-                };
-            })
-            (lib.mkIf cfg.nvidiaPersistenced {
-              "nvidia-persistenced" = {
-                description = "NVIDIA Persistence Daemon";
-                wantedBy = ["multi-user.target"];
+          environment.systemPackages =
+            lib.optional cfg.nvidiaSettings nvidia_x11.settings
+            ++ lib.optional cfg.nvidiaPersistenced nvidia_x11.persistenced
+            ++ lib.optional offloadCfg.enableOffloadCmd (
+              pkgs.writeShellScriptBin "nvidia-offload" ''
+                export __NV_PRIME_RENDER_OFFLOAD=1
+                export __NV_PRIME_RENDER_OFFLOAD_PROVIDER=NVIDIA-G0
+                export __GLX_VENDOR_LIBRARY_NAME=nvidia
+                export __VK_LAYER_NV_optimus=NVIDIA_only
+                exec "$@"
+              ''
+            );
+
+          systemd.packages = lib.optional cfg.powerManagement.enable nvidia_x11.out;
+
+          systemd.services =
+            let
+              nvidiaService = state: {
+                description = "NVIDIA system ${state} actions";
+                path = [ pkgs.kbd ];
                 serviceConfig = {
-                  Type = "forking";
-                  Restart = "always";
-                  PIDFile = "/var/run/nvidia-persistenced/nvidia-persistenced.pid";
-                  ExecStart = "${lib.getExe nvidia_x11.persistenced} --verbose";
-                  ExecStopPost = "${pkgs.coreutils}/bin/rm -rf /var/run/nvidia-persistenced";
+                  Type = "oneshot";
+                  ExecStart = "${nvidia_x11.out}/bin/nvidia-sleep.sh '${state}'";
                 };
+                before = [ "systemd-${state}.service" ];
+                requiredBy = [ "systemd-${state}.service" ];
               };
-            })
-            (lib.mkIf cfg.dynamicBoost.enable {
-              "nvidia-powerd" = {
-                description = "nvidia-powerd service";
-                path = [
-                  pkgs.util-linux # nvidia-powerd wants lscpu
-                ];
-                wantedBy = ["multi-user.target"];
-                serviceConfig = {
-                  Type = "dbus";
-                  BusName = "nvidia.powerd.server";
-                  ExecStart = "${nvidia_x11.bin}/bin/nvidia-powerd";
+            in
+            lib.mkMerge [
+              (lib.mkIf cfg.powerManagement.enable {
+                nvidia-suspend = nvidiaService "suspend";
+                nvidia-hibernate = nvidiaService "hibernate";
+                nvidia-resume = (nvidiaService "resume") // {
+                  before = [ ];
+                  after = [
+                    "systemd-suspend.service"
+                    "systemd-hibernate.service"
+                  ];
+                  requiredBy = [
+                    "systemd-suspend.service"
+                    "systemd-hibernate.service"
+                  ];
                 };
-              };
-            })
-          ];
-        services.acpid.enable = true;
-
-        services.dbus.packages = lib.optional cfg.dynamicBoost.enable nvidia_x11.bin;
-
-        hardware.firmware = lib.optional cfg.open nvidia_x11.firmware;
-
-        systemd.tmpfiles.rules = [
-          # Remove the following log message:
-          #    (WW) NVIDIA: Failed to bind sideband socket to
-          #    (WW) NVIDIA:     '/var/run/nvidia-xdriver-b4f69129' Permission denied
-          #
-          # https://bbs.archlinux.org/viewtopic.php?pid=1909115#p1909115
-          "d /run/nvidia-xdriver 0770 root users"
-        ] ++ lib.optional (nvidia_x11.persistenced != null && config.virtualisation.docker.enableNvidia)
-          "L+ /run/nvidia-docker/extras/bin/nvidia-persistenced - - - - ${nvidia_x11.persistenced}/origBin/nvidia-persistenced";
-
-        boot = {
-          extraModulePackages =
-            if cfg.open
-            then [nvidia_x11.open]
-            else [nvidia_x11.bin];
-          # nvidia-uvm is required by CUDA applications.
-          kernelModules =
-            lib.optionals config.services.xserver.enable ["nvidia" "nvidia_modeset" "nvidia_drm"];
-
-          # If requested enable modesetting via kernel parameter.
-          kernelParams =
-            lib.optional (offloadCfg.enable || cfg.modesetting.enable) "nvidia-drm.modeset=1"
-            ++ lib.optional cfg.powerManagement.enable "nvidia.NVreg_PreserveVideoMemoryAllocations=1"
-            ++ lib.optional cfg.open "nvidia.NVreg_OpenRmEnableUnsupportedGpus=1"
-            ++ lib.optional (config.boot.kernelPackages.kernel.kernelAtLeast "6.2" && !ibtSupport) "ibt=off";
-
-          # enable finegrained power management
-          extraModprobeConfig = lib.optionalString cfg.powerManagement.finegrained ''
-            options nvidia "NVreg_DynamicPowerManagement=0x02"
-          '';
-        };
-        services.udev.extraRules =
-          lib.optionalString cfg.powerManagement.finegrained (
-          lib.optionalString (lib.versionOlder config.boot.kernelPackages.kernel.version "5.5") ''
-            # Remove NVIDIA USB xHCI Host Controller devices, if present
-            ACTION=="add", SUBSYSTEM=="pci", ATTR{vendor}=="0x10de", ATTR{class}=="0x0c0330", ATTR{remove}="1"
-
-            # Remove NVIDIA USB Type-C UCSI devices, if present
-            ACTION=="add", SUBSYSTEM=="pci", ATTR{vendor}=="0x10de", ATTR{class}=="0x0c8000", ATTR{remove}="1"
-
-            # Remove NVIDIA Audio devices, if present
-            ACTION=="add", SUBSYSTEM=="pci", ATTR{vendor}=="0x10de", ATTR{class}=="0x040300", ATTR{remove}="1"
-          ''
-          + ''
-            # Enable runtime PM for NVIDIA VGA/3D controller devices on driver bind
-            ACTION=="bind", SUBSYSTEM=="pci", ATTR{vendor}=="0x10de", ATTR{class}=="0x030000", TEST=="power/control", ATTR{power/control}="auto"
-            ACTION=="bind", SUBSYSTEM=="pci", ATTR{vendor}=="0x10de", ATTR{class}=="0x030200", TEST=="power/control", ATTR{power/control}="auto"
-
-            # Disable runtime PM for NVIDIA VGA/3D controller devices on driver unbind
-            ACTION=="unbind", SUBSYSTEM=="pci", ATTR{vendor}=="0x10de", ATTR{class}=="0x030000", TEST=="power/control", ATTR{power/control}="on"
-            ACTION=="unbind", SUBSYSTEM=="pci", ATTR{vendor}=="0x10de", ATTR{class}=="0x030200", TEST=="power/control", ATTR{power/control}="on"
-          ''
-        );
-      })
-      # Data Center
-      (lib.mkIf (cfg.datacenter.enable) {
-        boot.extraModulePackages = [
-          nvidia_x11.bin
-        ];
-
-        systemd = {
-          tmpfiles.rules =
-            lib.optional (nvidia_x11.persistenced != null && config.virtualisation.docker.enableNvidia)
-            "L+ /run/nvidia-docker/extras/bin/nvidia-persistenced - - - - ${nvidia_x11.persistenced}/origBin/nvidia-persistenced";
-
-          services = lib.mkMerge [
-            ({
-              nvidia-fabricmanager = {
-                enable = true;
-                description = "Start NVIDIA NVLink Management";
-                wantedBy = [ "multi-user.target" ];
-                unitConfig.After = [ "network-online.target" ];
-                unitConfig.Requires = [ "network-online.target" ];
-                serviceConfig = {
-                  Type = "forking";
-                  TimeoutStartSec = 240;
-                  ExecStart = let
-                    nv-fab-conf = settingsFormat.generate "fabricmanager.conf" cfg.datacenter.settings;
-                    in
+              })
+              (lib.mkIf cfg.nvidiaPersistenced {
+                "nvidia-persistenced" = {
+                  description = "NVIDIA Persistence Daemon";
+                  wantedBy = [ "multi-user.target" ];
+                  serviceConfig = {
+                    Type = "forking";
+                    Restart = "always";
+                    PIDFile = "/var/run/nvidia-persistenced/nvidia-persistenced.pid";
+                    ExecStart = "${lib.getExe nvidia_x11.persistenced} --verbose";
+                    ExecStopPost = "${pkgs.coreutils}/bin/rm -rf /var/run/nvidia-persistenced";
+                  };
+                };
+              })
+              (lib.mkIf cfg.dynamicBoost.enable {
+                "nvidia-powerd" = {
+                  description = "nvidia-powerd service";
+                  path = [
+                    pkgs.util-linux # nvidia-powerd wants lscpu
+                  ];
+                  wantedBy = [ "multi-user.target" ];
+                  serviceConfig = {
+                    Type = "dbus";
+                    BusName = "nvidia.powerd.server";
+                    ExecStart = "${nvidia_x11.bin}/bin/nvidia-powerd";
+                  };
+                };
+              })
+            ];
+          services.acpid.enable = true;
+
+          services.dbus.packages = lib.optional cfg.dynamicBoost.enable nvidia_x11.bin;
+
+          hardware.firmware =
+            let
+              isOpen = cfg.open;
+              isNewUnfree = lib.versionAtLeast nvidia_x11.version "555";
+            in
+            lib.optional (isOpen || isNewUnfree) nvidia_x11.firmware;
+
+          systemd.tmpfiles.rules =
+            [
+              # Remove the following log message:
+              #    (WW) NVIDIA: Failed to bind sideband socket to
+              #    (WW) NVIDIA:     '/var/run/nvidia-xdriver-b4f69129' Permission denied
+              #
+              # https://bbs.archlinux.org/viewtopic.php?pid=1909115#p1909115
+              "d /run/nvidia-xdriver 0770 root users"
+            ]
+            ++ lib.optional (nvidia_x11.persistenced != null && config.virtualisation.docker.enableNvidia)
+              "L+ /run/nvidia-docker/extras/bin/nvidia-persistenced - - - - ${nvidia_x11.persistenced}/origBin/nvidia-persistenced";
+
+          boot = {
+            extraModulePackages = if cfg.open then [ nvidia_x11.open ] else [ nvidia_x11.bin ];
+            # nvidia-uvm is required by CUDA applications.
+            kernelModules = lib.optionals config.services.xserver.enable [
+              "nvidia"
+              "nvidia_modeset"
+              "nvidia_drm"
+            ];
+
+            # If requested enable modesetting via kernel parameter.
+            kernelParams =
+              lib.optional (offloadCfg.enable || cfg.modesetting.enable) "nvidia-drm.modeset=1"
+              ++ lib.optional cfg.powerManagement.enable "nvidia.NVreg_PreserveVideoMemoryAllocations=1"
+              ++ lib.optional cfg.open "nvidia.NVreg_OpenRmEnableUnsupportedGpus=1"
+              ++ lib.optional (config.boot.kernelPackages.kernel.kernelAtLeast "6.2" && !ibtSupport) "ibt=off";
+
+            # enable finegrained power management
+            extraModprobeConfig = lib.optionalString cfg.powerManagement.finegrained ''
+              options nvidia "NVreg_DynamicPowerManagement=0x02"
+            '';
+          };
+          services.udev.extraRules = lib.optionalString cfg.powerManagement.finegrained (
+            lib.optionalString (lib.versionOlder config.boot.kernelPackages.kernel.version "5.5") ''
+              # Remove NVIDIA USB xHCI Host Controller devices, if present
+              ACTION=="add", SUBSYSTEM=="pci", ATTR{vendor}=="0x10de", ATTR{class}=="0x0c0330", ATTR{remove}="1"
+
+              # Remove NVIDIA USB Type-C UCSI devices, if present
+              ACTION=="add", SUBSYSTEM=="pci", ATTR{vendor}=="0x10de", ATTR{class}=="0x0c8000", ATTR{remove}="1"
+
+              # Remove NVIDIA Audio devices, if present
+              ACTION=="add", SUBSYSTEM=="pci", ATTR{vendor}=="0x10de", ATTR{class}=="0x040300", ATTR{remove}="1"
+            ''
+            + ''
+              # Enable runtime PM for NVIDIA VGA/3D controller devices on driver bind
+              ACTION=="bind", SUBSYSTEM=="pci", ATTR{vendor}=="0x10de", ATTR{class}=="0x030000", TEST=="power/control", ATTR{power/control}="auto"
+              ACTION=="bind", SUBSYSTEM=="pci", ATTR{vendor}=="0x10de", ATTR{class}=="0x030200", TEST=="power/control", ATTR{power/control}="auto"
+
+              # Disable runtime PM for NVIDIA VGA/3D controller devices on driver unbind
+              ACTION=="unbind", SUBSYSTEM=="pci", ATTR{vendor}=="0x10de", ATTR{class}=="0x030000", TEST=="power/control", ATTR{power/control}="on"
+              ACTION=="unbind", SUBSYSTEM=="pci", ATTR{vendor}=="0x10de", ATTR{class}=="0x030200", TEST=="power/control", ATTR{power/control}="on"
+            ''
+          );
+        })
+        # Data Center
+        (lib.mkIf (cfg.datacenter.enable) {
+          boot.extraModulePackages = [ nvidia_x11.bin ];
+
+          systemd = {
+            tmpfiles.rules =
+              lib.optional (nvidia_x11.persistenced != null && config.virtualisation.docker.enableNvidia)
+                "L+ /run/nvidia-docker/extras/bin/nvidia-persistenced - - - - ${nvidia_x11.persistenced}/origBin/nvidia-persistenced";
+
+            services = lib.mkMerge [
+              ({
+                nvidia-fabricmanager = {
+                  enable = true;
+                  description = "Start NVIDIA NVLink Management";
+                  wantedBy = [ "multi-user.target" ];
+                  unitConfig.After = [ "network-online.target" ];
+                  unitConfig.Requires = [ "network-online.target" ];
+                  serviceConfig = {
+                    Type = "forking";
+                    TimeoutStartSec = 240;
+                    ExecStart =
+                      let
+                        nv-fab-conf = settingsFormat.generate "fabricmanager.conf" cfg.datacenter.settings;
+                      in
                       "${lib.getExe nvidia_x11.fabricmanager} -c ${nv-fab-conf}";
-                  LimitCORE="infinity";
+                    LimitCORE = "infinity";
+                  };
                 };
-              };
-            })
-            (lib.mkIf cfg.nvidiaPersistenced {
-              "nvidia-persistenced" = {
-                description = "NVIDIA Persistence Daemon";
-                wantedBy = ["multi-user.target"];
-                serviceConfig = {
-                  Type = "forking";
-                  Restart = "always";
-                  PIDFile = "/var/run/nvidia-persistenced/nvidia-persistenced.pid";
-                  ExecStart = "${lib.getExe nvidia_x11.persistenced} --verbose";
-                  ExecStopPost = "${pkgs.coreutils}/bin/rm -rf /var/run/nvidia-persistenced";
+              })
+              (lib.mkIf cfg.nvidiaPersistenced {
+                "nvidia-persistenced" = {
+                  description = "NVIDIA Persistence Daemon";
+                  wantedBy = [ "multi-user.target" ];
+                  serviceConfig = {
+                    Type = "forking";
+                    Restart = "always";
+                    PIDFile = "/var/run/nvidia-persistenced/nvidia-persistenced.pid";
+                    ExecStart = "${lib.getExe nvidia_x11.persistenced} --verbose";
+                    ExecStopPost = "${pkgs.coreutils}/bin/rm -rf /var/run/nvidia-persistenced";
+                  };
                 };
-              };
-            })
-          ];
-      };
+              })
+            ];
+          };
 
-      environment.systemPackages =
-        lib.optional cfg.datacenter.enable nvidia_x11.fabricmanager
-        ++ lib.optional cfg.nvidiaPersistenced nvidia_x11.persistenced;
-    })
-  ]);
+          environment.systemPackages =
+            lib.optional cfg.datacenter.enable nvidia_x11.fabricmanager
+            ++ lib.optional cfg.nvidiaPersistenced nvidia_x11.persistenced;
+        })
+      ]
+    );
 }
diff --git a/nixos/modules/misc/version.nix b/nixos/modules/misc/version.nix
index d582e0c162de3..29e9498018ec9 100644
--- a/nixos/modules/misc/version.nix
+++ b/nixos/modules/misc/version.nix
@@ -135,7 +135,7 @@ in
       };
 
       version = lib.mkOption {
-        type = types.nullOr (types.strMatching "^[a-z0-9._-]+$");
+        type = types.nullOr (types.strMatching "^[a-z0-9._-~^]+$");
         default = null;
         description = ''
           Image version.
diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix
index 76ccf5a341094..76fa899ef7cef 100644
--- a/nixos/modules/module-list.nix
+++ b/nixos/modules/module-list.nix
@@ -158,6 +158,7 @@
   ./programs/bash/ls-colors.nix
   ./programs/bash/undistract-me.nix
   ./programs/bcc.nix
+  ./programs/benchexec.nix
   ./programs/browserpass.nix
   ./programs/calls.nix
   ./programs/captive-browser.nix
@@ -167,6 +168,7 @@
   ./programs/chromium.nix
   ./programs/clash-verge.nix
   ./programs/cnping.nix
+  ./programs/cpu-energy-meter.nix
   ./programs/command-not-found/command-not-found.nix
   ./programs/coolercontrol.nix
   ./programs/criu.nix
@@ -247,9 +249,9 @@
   ./programs/oblogout.nix
   ./programs/oddjobd.nix
   ./programs/openvpn3.nix
-  ./programs/pantheon-tweaks.nix
   ./programs/partition-manager.nix
   ./programs/plotinus.nix
+  ./programs/pqos-wrapper.nix
   ./programs/projecteur.nix
   ./programs/proxychains.nix
   ./programs/qdmr.nix
@@ -308,6 +310,7 @@
   ./programs/xwayland.nix
   ./programs/yabar.nix
   ./programs/yazi.nix
+  ./programs/ydotool.nix
   ./programs/yubikey-touch-detector.nix
   ./programs/zmap.nix
   ./programs/zsh/oh-my-zsh.nix
@@ -699,6 +702,7 @@
   ./services/misc/cpuminer-cryptonight.nix
   ./services/misc/db-rest.nix
   ./services/misc/devmon.nix
+  ./services/misc/devpi-server.nix
   ./services/misc/dictd.nix
   ./services/misc/disnix.nix
   ./services/misc/docker-registry.nix
@@ -776,6 +780,7 @@
   ./services/misc/polaris.nix
   ./services/misc/portunus.nix
   ./services/misc/preload.nix
+  ./services/misc/private-gpt.nix
   ./services/misc/prowlarr.nix
   ./services/misc/pufferpanel.nix
   ./services/misc/pykms.nix
@@ -1103,6 +1108,7 @@
   ./services/networking/ocserv.nix
   ./services/networking/ofono.nix
   ./services/networking/oidentd.nix
+  ./services/networking/oink.nix
   ./services/networking/onedrive.nix
   ./services/networking/openconnect.nix
   ./services/networking/openvpn.nix
@@ -1322,6 +1328,7 @@
   ./services/web-apps/akkoma.nix
   ./services/web-apps/alps.nix
   ./services/web-apps/anuko-time-tracker.nix
+  ./services/web-apps/artalk.nix
   ./services/web-apps/atlassian/confluence.nix
   ./services/web-apps/atlassian/crowd.nix
   ./services/web-apps/atlassian/jira.nix
@@ -1335,6 +1342,7 @@
   ./services/web-apps/chatgpt-retrieval-plugin.nix
   ./services/web-apps/cloudlog.nix
   ./services/web-apps/code-server.nix
+  ./services/web-apps/commafeed.nix
   ./services/web-apps/convos.nix
   ./services/web-apps/crabfit.nix
   ./services/web-apps/davis.nix
@@ -1345,7 +1353,9 @@
   ./services/web-apps/dolibarr.nix
   ./services/web-apps/engelsystem.nix
   ./services/web-apps/ethercalc.nix
+  ./services/web-apps/filesender.nix
   ./services/web-apps/firefly-iii.nix
+  ./services/web-apps/flarum.nix
   ./services/web-apps/fluidd.nix
   ./services/web-apps/freshrss.nix
   ./services/web-apps/galene.nix
@@ -1389,6 +1399,7 @@
   ./services/web-apps/netbox.nix
   ./services/web-apps/nextcloud.nix
   ./services/web-apps/nextcloud-notify_push.nix
+  ./services/web-apps/nextjs-ollama-llm-ui.nix
   ./services/web-apps/nexus.nix
   ./services/web-apps/nifi.nix
   ./services/web-apps/node-red.nix
@@ -1417,6 +1428,7 @@
   ./services/web-apps/selfoss.nix
   ./services/web-apps/shiori.nix
   ./services/web-apps/silverbullet.nix
+  ./services/web-apps/simplesamlphp.nix
   ./services/web-apps/slskd.nix
   ./services/web-apps/snipe-it.nix
   ./services/web-apps/sogo.nix
@@ -1428,11 +1440,13 @@
   ./services/web-apps/windmill.nix
   ./services/web-apps/wordpress.nix
   ./services/web-apps/writefreely.nix
+  ./services/web-apps/your_spotify.nix
   ./services/web-apps/youtrack.nix
   ./services/web-apps/zabbix.nix
   ./services/web-apps/zitadel.nix
   ./services/web-servers/agate.nix
   ./services/web-servers/apache-httpd/default.nix
+  ./services/web-servers/bluemap.nix
   ./services/web-servers/caddy/default.nix
   ./services/web-servers/darkhttpd.nix
   ./services/web-servers/fcgiwrap.nix
diff --git a/nixos/modules/programs/_1password-gui.nix b/nixos/modules/programs/_1password-gui.nix
index b21e8783f660e..04f36cf0237ab 100644
--- a/nixos/modules/programs/_1password-gui.nix
+++ b/nixos/modules/programs/_1password-gui.nix
@@ -1,7 +1,5 @@
 { config, pkgs, lib, ... }:
 
-with lib;
-
 let
 
   cfg = config.programs._1password-gui;
@@ -9,25 +7,25 @@ let
 in
 {
   imports = [
-    (mkRemovedOptionModule [ "programs" "_1password-gui" "gid" ] ''
+    (lib.mkRemovedOptionModule [ "programs" "_1password-gui" "gid" ] ''
       A preallocated GID will be used instead.
     '')
   ];
 
   options = {
     programs._1password-gui = {
-      enable = mkEnableOption "the 1Password GUI application";
+      enable = lib.mkEnableOption "the 1Password GUI application";
 
-      polkitPolicyOwners = mkOption {
-        type = types.listOf types.str;
+      polkitPolicyOwners = lib.mkOption {
+        type = lib.types.listOf lib.types.str;
         default = [ ];
-        example = literalExpression ''["user1" "user2" "user3"]'';
+        example = lib.literalExpression ''["user1" "user2" "user3"]'';
         description = ''
           A list of users who should be able to integrate 1Password with polkit-based authentication mechanisms.
         '';
       };
 
-      package = mkPackageOption pkgs "1Password GUI" {
+      package = lib.mkPackageOption pkgs "1Password GUI" {
         default = [ "_1password-gui" ];
       };
     };
@@ -39,7 +37,7 @@ in
         polkitPolicyOwners = cfg.polkitPolicyOwners;
       };
     in
-    mkIf cfg.enable {
+    lib.mkIf cfg.enable {
       environment.systemPackages = [ package ];
       users.groups.onepassword.gid = config.ids.gids.onepassword;
 
diff --git a/nixos/modules/programs/_1password.nix b/nixos/modules/programs/_1password.nix
index b87e9b776e85b..5dff199341b94 100644
--- a/nixos/modules/programs/_1password.nix
+++ b/nixos/modules/programs/_1password.nix
@@ -1,7 +1,5 @@
 { config, pkgs, lib, ... }:
 
-with lib;
-
 let
 
   cfg = config.programs._1password;
@@ -9,22 +7,22 @@ let
 in
 {
   imports = [
-    (mkRemovedOptionModule [ "programs" "_1password" "gid" ] ''
+    (lib.mkRemovedOptionModule [ "programs" "_1password" "gid" ] ''
       A preallocated GID will be used instead.
     '')
   ];
 
   options = {
     programs._1password = {
-      enable = mkEnableOption "the 1Password CLI tool";
+      enable = lib.mkEnableOption "the 1Password CLI tool";
 
-      package = mkPackageOption pkgs "1Password CLI" {
+      package = lib.mkPackageOption pkgs "1Password CLI" {
         default = [ "_1password" ];
       };
     };
   };
 
-  config = mkIf cfg.enable {
+  config = lib.mkIf cfg.enable {
     environment.systemPackages = [ cfg.package ];
     users.groups.onepassword-cli.gid = config.ids.gids.onepassword-cli;
 
diff --git a/nixos/modules/programs/adb.nix b/nixos/modules/programs/adb.nix
index d8c700bc36b65..62ab6ab4137a1 100644
--- a/nixos/modules/programs/adb.nix
+++ b/nixos/modules/programs/adb.nix
@@ -1,16 +1,14 @@
 { config, lib, pkgs, ... }:
 
-with lib;
-
 {
-  meta.maintainers = [ maintainers.mic92 ];
+  meta.maintainers = [ lib.maintainers.mic92 ];
 
   ###### interface
   options = {
     programs.adb = {
-      enable = mkOption {
+      enable = lib.mkOption {
         default = false;
-        type = types.bool;
+        type = lib.types.bool;
         description = ''
           Whether to configure system to use Android Debug Bridge (adb).
           To grant access to a user, it must be part of adbusers group:
@@ -21,7 +19,7 @@ with lib;
   };
 
   ###### implementation
-  config = mkIf config.programs.adb.enable {
+  config = lib.mkIf config.programs.adb.enable {
     services.udev.packages = [ pkgs.android-udev-rules ];
     environment.systemPackages = [ pkgs.android-tools ];
     users.groups.adbusers = {};
diff --git a/nixos/modules/programs/alvr.nix b/nixos/modules/programs/alvr.nix
index e5de06f1157ad..da66200cf075b 100644
--- a/nixos/modules/programs/alvr.nix
+++ b/nixos/modules/programs/alvr.nix
@@ -1,19 +1,17 @@
 { config, pkgs, lib, ... }:
 
-with lib;
-
 let
   cfg = config.programs.alvr;
 in
 {
   options = {
     programs.alvr = {
-      enable = mkEnableOption "ALVR, the VR desktop streamer";
+      enable = lib.mkEnableOption "ALVR, the VR desktop streamer";
 
-      package = mkPackageOption pkgs "alvr" { };
+      package = lib.mkPackageOption pkgs "alvr" { };
 
-      openFirewall = mkOption {
-        type = types.bool;
+      openFirewall = lib.mkOption {
+        type = lib.types.bool;
         default = false;
         description = ''
           Whether to open the default ports in the firewall for the ALVR server.
@@ -22,14 +20,14 @@ in
     };
   };
 
-  config = mkIf cfg.enable {
+  config = lib.mkIf cfg.enable {
     environment.systemPackages = [ cfg.package ];
 
-    networking.firewall = mkIf cfg.openFirewall {
+    networking.firewall = lib.mkIf cfg.openFirewall {
       allowedTCPPorts = [ 9943 9944 ];
       allowedUDPPorts = [ 9943 9944 ];
     };
   };
 
-  meta.maintainers = with maintainers; [ passivelemon ];
+  meta.maintainers = with lib.maintainers; [ passivelemon ];
 }
diff --git a/nixos/modules/programs/appgate-sdp.nix b/nixos/modules/programs/appgate-sdp.nix
index 6d61c87eeb612..f4d4140571a64 100644
--- a/nixos/modules/programs/appgate-sdp.nix
+++ b/nixos/modules/programs/appgate-sdp.nix
@@ -1,15 +1,13 @@
 { config, pkgs, lib, ... }:
 
-with lib;
-
 {
   options = {
     programs.appgate-sdp = {
-      enable = mkEnableOption "the AppGate SDP VPN client";
+      enable = lib.mkEnableOption "the AppGate SDP VPN client";
     };
   };
 
-  config = mkIf config.programs.appgate-sdp.enable {
+  config = lib.mkIf config.programs.appgate-sdp.enable {
     boot.kernelModules = [ "tun" ];
     environment.systemPackages = [ pkgs.appgate-sdp ];
     services.dbus.packages = [ pkgs.appgate-sdp ];
diff --git a/nixos/modules/programs/atop.nix b/nixos/modules/programs/atop.nix
index 618b641143590..3738f926ca3d8 100644
--- a/nixos/modules/programs/atop.nix
+++ b/nixos/modules/programs/atop.nix
@@ -2,8 +2,6 @@
 
 { config, lib, pkgs, ... }:
 
-with lib;
-
 let cfg = config.programs.atop;
 
 in
@@ -14,31 +12,31 @@ in
 
     programs.atop = rec {
 
-      enable = mkEnableOption "Atop, a tool for monitoring system resources";
+      enable = lib.mkEnableOption "Atop, a tool for monitoring system resources";
 
-      package = mkPackageOption pkgs "atop" { };
+      package = lib.mkPackageOption pkgs "atop" { };
 
       netatop = {
-        enable = mkOption {
-          type = types.bool;
+        enable = lib.mkOption {
+          type = lib.types.bool;
           default = false;
           description = ''
             Whether to install and enable the netatop kernel module.
             Note: this sets the kernel taint flag "O" for loading out-of-tree modules.
           '';
         };
-        package = mkOption {
-          type = types.package;
+        package = lib.mkOption {
+          type = lib.types.package;
           default = config.boot.kernelPackages.netatop;
-          defaultText = literalExpression "config.boot.kernelPackages.netatop";
+          defaultText = lib.literalExpression "config.boot.kernelPackages.netatop";
           description = ''
             Which package to use for netatop.
           '';
         };
       };
 
-      atopgpu.enable = mkOption {
-        type = types.bool;
+      atopgpu.enable = lib.mkOption {
+        type = lib.types.bool;
         default = false;
         description = ''
           Whether to install and enable the atopgpud daemon to get information about
@@ -46,8 +44,8 @@ in
         '';
       };
 
-      setuidWrapper.enable = mkOption {
-        type = types.bool;
+      setuidWrapper.enable = lib.mkOption {
+        type = lib.types.bool;
         default = false;
         description = ''
           Whether to install a setuid wrapper for Atop. This is required to use some of
@@ -56,24 +54,24 @@ in
         '';
       };
 
-      atopService.enable = mkOption {
-        type = types.bool;
+      atopService.enable = lib.mkOption {
+        type = lib.types.bool;
         default = true;
         description = ''
           Whether to enable the atop service responsible for storing statistics for
           long-term analysis.
         '';
       };
-      atopRotateTimer.enable = mkOption {
-        type = types.bool;
+      atopRotateTimer.enable = lib.mkOption {
+        type = lib.types.bool;
         default = true;
         description = ''
           Whether to enable the atop-rotate timer, which restarts the atop service
           daily to make sure the data files are rotate.
         '';
       };
-      atopacctService.enable = mkOption {
-        type = types.bool;
+      atopacctService.enable = lib.mkOption {
+        type = lib.types.bool;
         default = true;
         description = ''
           Whether to enable the atopacct service which manages process accounting.
@@ -81,8 +79,8 @@ in
           two refresh intervals.
         '';
       };
-      settings = mkOption {
-        type = types.attrs;
+      settings = lib.mkOption {
+        type = lib.types.attrs;
         default = { };
         example = {
           flags = "a1f";
@@ -95,7 +93,7 @@ in
     };
   };
 
-  config = mkIf cfg.enable (
+  config = lib.mkIf cfg.enable (
     let
       atop =
         if cfg.atopgpu.enable then
@@ -104,11 +102,11 @@ in
           cfg.package;
     in
     {
-      environment.etc = mkIf (cfg.settings != { }) {
-        atoprc.text = concatStrings
-          (mapAttrsToList
+      environment.etc = lib.mkIf (cfg.settings != { }) {
+        atoprc.text = lib.concatStrings
+          (lib.mapAttrsToList
             (n: v: ''
-              ${n} ${toString v}
+              ${n} ${builtins.toString v}
             '')
             cfg.settings);
       };
diff --git a/nixos/modules/programs/ausweisapp.nix b/nixos/modules/programs/ausweisapp.nix
index 0359e58c554ca..ebd6a3e13bf66 100644
--- a/nixos/modules/programs/ausweisapp.nix
+++ b/nixos/modules/programs/ausweisapp.nix
@@ -1,15 +1,13 @@
 { config, lib, pkgs, ... }:
 
-with lib;
-
 let
   cfg  = config.programs.ausweisapp;
 in
 {
   options.programs.ausweisapp = {
-    enable = mkEnableOption "AusweisApp";
+    enable = lib.mkEnableOption "AusweisApp";
 
-    openFirewall = mkOption {
+    openFirewall = lib.mkOption {
       description = ''
         Whether to open the required firewall ports for the Smartphone as Card Reader (SaC) functionality of AusweisApp.
       '';
@@ -18,7 +16,7 @@ in
     };
   };
 
-  config = mkIf cfg.enable {
+  config = lib.mkIf cfg.enable {
     environment.systemPackages = with pkgs; [ ausweisapp ];
     networking.firewall.allowedUDPPorts = lib.optionals cfg.openFirewall [ 24727 ];
   };
diff --git a/nixos/modules/programs/autojump.nix b/nixos/modules/programs/autojump.nix
index ecfc2f658079d..5011d7e142375 100644
--- a/nixos/modules/programs/autojump.nix
+++ b/nixos/modules/programs/autojump.nix
@@ -1,7 +1,5 @@
 { config, lib, pkgs, ... }:
 
-with lib;
-
 let
   cfg = config.programs.autojump;
   prg = config.programs;
@@ -10,8 +8,8 @@ in
   options = {
     programs.autojump = {
 
-      enable = mkOption {
-        type = types.bool;
+      enable = lib.mkOption {
+        type = lib.types.bool;
         default = false;
         description = ''
           Whether to enable autojump.
@@ -22,12 +20,12 @@ in
 
   ###### implementation
 
-  config = mkIf cfg.enable {
+  config = lib.mkIf cfg.enable {
     environment.pathsToLink = [ "/share/autojump" ];
     environment.systemPackages = [ pkgs.autojump ];
 
     programs.bash.interactiveShellInit = "source ${pkgs.autojump}/share/autojump/autojump.bash";
-    programs.zsh.interactiveShellInit = mkIf prg.zsh.enable "source ${pkgs.autojump}/share/autojump/autojump.zsh";
-    programs.fish.interactiveShellInit = mkIf prg.fish.enable "source ${pkgs.autojump}/share/autojump/autojump.fish";
+    programs.zsh.interactiveShellInit = lib.mkIf prg.zsh.enable "source ${pkgs.autojump}/share/autojump/autojump.zsh";
+    programs.fish.interactiveShellInit = lib.mkIf prg.fish.enable "source ${pkgs.autojump}/share/autojump/autojump.fish";
   };
 }
diff --git a/nixos/modules/programs/bandwhich.nix b/nixos/modules/programs/bandwhich.nix
index 2c78584f2d248..e2c55ca5bea4a 100644
--- a/nixos/modules/programs/bandwhich.nix
+++ b/nixos/modules/programs/bandwhich.nix
@@ -1,15 +1,13 @@
 { config, lib, pkgs, ... }:
 
-with lib;
-
 let cfg = config.programs.bandwhich;
 in {
-  meta.maintainers = with maintainers; [ Br1ght0ne ];
+  meta.maintainers = with lib.maintainers; [ Br1ght0ne ];
 
   options = {
     programs.bandwhich = {
-      enable = mkOption {
-        type = types.bool;
+      enable = lib.mkOption {
+        type = lib.types.bool;
         default = false;
         description = ''
           Whether to add bandwhich to the global environment and configure a
@@ -19,7 +17,7 @@ in {
     };
   };
 
-  config = mkIf cfg.enable {
+  config = lib.mkIf cfg.enable {
     environment.systemPackages = with pkgs; [ bandwhich ];
     security.wrappers.bandwhich = {
       owner = "root";
diff --git a/nixos/modules/programs/bash-my-aws.nix b/nixos/modules/programs/bash-my-aws.nix
index 15e429a754976..85618ad98f080 100644
--- a/nixos/modules/programs/bash-my-aws.nix
+++ b/nixos/modules/programs/bash-my-aws.nix
@@ -1,7 +1,5 @@
 { config, pkgs, lib, ... }:
 
-with lib;
-
 let
   prg = config.programs;
   cfg = prg.bash-my-aws;
@@ -13,11 +11,11 @@ in
   {
     options = {
       programs.bash-my-aws = {
-        enable = mkEnableOption "bash-my-aws";
+        enable = lib.mkEnableOption "bash-my-aws";
       };
     };
 
-    config = mkIf cfg.enable {
+    config = lib.mkIf cfg.enable {
       environment.systemPackages = with pkgs; [ bash-my-aws ];
 
       programs.bash.interactiveShellInit = initScript;
diff --git a/nixos/modules/programs/bash/bash-completion.nix b/nixos/modules/programs/bash/bash-completion.nix
index b8e5b1bfa336f..c973d36fdfbf0 100644
--- a/nixos/modules/programs/bash/bash-completion.nix
+++ b/nixos/modules/programs/bash/bash-completion.nix
@@ -1,18 +1,16 @@
 { config, lib, pkgs, ... }:
 
-with lib;
-
 let
   enable = config.programs.bash.enableCompletion;
 in
 {
   options = {
-    programs.bash.enableCompletion = mkEnableOption "Bash completion for all interactive bash shells" // {
+    programs.bash.enableCompletion = lib.mkEnableOption "Bash completion for all interactive bash shells" // {
       default = true;
     };
   };
 
-  config = mkIf enable {
+  config = lib.mkIf enable {
     programs.bash.promptPluginInit = ''
       # Check whether we're running a version of Bash that has support for
       # programmable completion. If we do, enable all modules installed in
diff --git a/nixos/modules/programs/bash/bash.nix b/nixos/modules/programs/bash/bash.nix
index 21ef8338d8dd8..0f8c40da801b6 100644
--- a/nixos/modules/programs/bash/bash.nix
+++ b/nixos/modules/programs/bash/bash.nix
@@ -3,24 +3,22 @@
 
 { config, lib, pkgs, ... }:
 
-with lib;
-
 let
 
   cfge = config.environment;
 
   cfg = config.programs.bash;
 
-  bashAliases = concatStringsSep "\n" (
-    mapAttrsFlatten (k: v: "alias -- ${k}=${escapeShellArg v}")
-      (filterAttrs (k: v: v != null) cfg.shellAliases)
+  bashAliases = builtins.concatStringsSep "\n" (
+    lib.mapAttrsFlatten (k: v: "alias -- ${k}=${lib.escapeShellArg v}")
+      (lib.filterAttrs (k: v: v != null) cfg.shellAliases)
   );
 
 in
 
 {
   imports = [
-    (mkRemovedOptionModule [ "programs" "bash" "enable" ] "")
+    (lib.mkRemovedOptionModule [ "programs" "bash" "enable" ] "")
   ];
 
   options = {
@@ -28,7 +26,7 @@ in
     programs.bash = {
 
       /*
-      enable = mkOption {
+      enable = lib.mkOption {
         default = true;
         description = ''
           Whenever to configure Bash as an interactive shell.
@@ -38,44 +36,44 @@ in
           set this variable if you have another shell configured
           with NixOS.
         '';
-        type = types.bool;
+        type = lib.types.bool;
       };
       */
 
-      shellAliases = mkOption {
+      shellAliases = lib.mkOption {
         default = {};
         description = ''
           Set of aliases for bash shell, which overrides {option}`environment.shellAliases`.
           See {option}`environment.shellAliases` for an option format description.
         '';
-        type = with types; attrsOf (nullOr (either str path));
+        type = with lib.types; attrsOf (nullOr (either str path));
       };
 
-      shellInit = mkOption {
+      shellInit = lib.mkOption {
         default = "";
         description = ''
           Shell script code called during bash shell initialisation.
         '';
-        type = types.lines;
+        type = lib.types.lines;
       };
 
-      loginShellInit = mkOption {
+      loginShellInit = lib.mkOption {
         default = "";
         description = ''
           Shell script code called during login bash shell initialisation.
         '';
-        type = types.lines;
+        type = lib.types.lines;
       };
 
-      interactiveShellInit = mkOption {
+      interactiveShellInit = lib.mkOption {
         default = "";
         description = ''
           Shell script code called during interactive bash shell initialisation.
         '';
-        type = types.lines;
+        type = lib.types.lines;
       };
 
-      promptInit = mkOption {
+      promptInit = lib.mkOption {
         default = ''
           # Provide a nice prompt if the terminal supports it.
           if [ "$TERM" != "dumb" ] || [ -n "$INSIDE_EMACS" ]; then
@@ -95,15 +93,15 @@ in
         description = ''
           Shell script code used to initialise the bash prompt.
         '';
-        type = types.lines;
+        type = lib.types.lines;
       };
 
-      promptPluginInit = mkOption {
+      promptPluginInit = lib.mkOption {
         default = "";
         description = ''
           Shell script code used to initialise bash prompt plugins.
         '';
-        type = types.lines;
+        type = lib.types.lines;
         internal = true;
       };
 
@@ -111,11 +109,11 @@ in
 
   };
 
-  config = /* mkIf cfg.enable */ {
+  config = /* lib.mkIf cfg.enable */ {
 
     programs.bash = {
 
-      shellAliases = mapAttrs (name: mkDefault) cfge.shellAliases;
+      shellAliases = builtins.mapAttrs (name: lib.mkDefault) cfge.shellAliases;
 
       shellInit = ''
         if [ -z "$__NIXOS_SET_ENVIRONMENT_DONE" ]; then
@@ -196,11 +194,11 @@ in
 
     # Configuration for readline in bash. We use "option default"
     # priority to allow user override using both .text and .source.
-    environment.etc.inputrc.source = mkOptionDefault ./inputrc;
+    environment.etc.inputrc.source = lib.mkOptionDefault ./inputrc;
 
-    users.defaultUserShell = mkDefault pkgs.bashInteractive;
+    users.defaultUserShell = lib.mkDefault pkgs.bashInteractive;
 
-    environment.pathsToLink = optionals cfg.enableCompletion [
+    environment.pathsToLink = lib.optionals cfg.enableCompletion [
       "/etc/bash_completion.d"
       "/share/bash-completion"
     ];
diff --git a/nixos/modules/programs/bash/blesh.nix b/nixos/modules/programs/bash/blesh.nix
index ea342b0ce3eec..b5ca83a883bb0 100644
--- a/nixos/modules/programs/bash/blesh.nix
+++ b/nixos/modules/programs/bash/blesh.nix
@@ -1,16 +1,15 @@
 { lib, config, pkgs, ... }:
-with lib;
 let
   cfg = config.programs.bash.blesh;
 in {
   options = {
-    programs.bash.blesh.enable = mkEnableOption "blesh, a full-featured line editor written in pure Bash";
+    programs.bash.blesh.enable = lib.mkEnableOption "blesh, a full-featured line editor written in pure Bash";
   };
 
-  config = mkIf cfg.enable {
-    programs.bash.interactiveShellInit = mkBefore ''
+  config = lib.mkIf cfg.enable {
+    programs.bash.interactiveShellInit = lib.mkBefore ''
       source ${pkgs.blesh}/share/blesh/ble.sh
     '';
   };
-  meta.maintainers = with maintainers; [ laalsaas ];
+  meta.maintainers = with lib.maintainers; [ laalsaas ];
 }
diff --git a/nixos/modules/programs/bash/ls-colors.nix b/nixos/modules/programs/bash/ls-colors.nix
index 254ee14c477d6..3ee00e93d4dae 100644
--- a/nixos/modules/programs/bash/ls-colors.nix
+++ b/nixos/modules/programs/bash/ls-colors.nix
@@ -1,18 +1,16 @@
 { config, lib, pkgs, ... }:
 
-with lib;
-
 let
   enable = config.programs.bash.enableLsColors;
 in
 {
   options = {
-    programs.bash.enableLsColors = mkEnableOption "extra colors in directory listings" // {
+    programs.bash.enableLsColors = lib.mkEnableOption "extra colors in directory listings" // {
       default = true;
     };
   };
 
-  config = mkIf enable {
+  config = lib.mkIf enable {
     programs.bash.promptPluginInit = ''
       eval "$(${pkgs.coreutils}/bin/dircolors -b)"
     '';
diff --git a/nixos/modules/programs/bash/undistract-me.nix b/nixos/modules/programs/bash/undistract-me.nix
index 0e6465e048a10..af4f3a737dabd 100644
--- a/nixos/modules/programs/bash/undistract-me.nix
+++ b/nixos/modules/programs/bash/undistract-me.nix
@@ -1,36 +1,34 @@
 { config, lib, pkgs, ... }:
 
-with lib;
-
 let
   cfg = config.programs.bash.undistractMe;
 in
 {
   options = {
     programs.bash.undistractMe = {
-      enable = mkEnableOption "notifications when long-running terminal commands complete";
+      enable = lib.mkEnableOption "notifications when long-running terminal commands complete";
 
-      playSound = mkEnableOption "notification sounds when long-running terminal commands complete";
+      playSound = lib.mkEnableOption "notification sounds when long-running terminal commands complete";
 
-      timeout = mkOption {
+      timeout = lib.mkOption {
         default = 10;
         description = ''
           Number of seconds it would take for a command to be considered long-running.
         '';
-        type = types.int;
+        type = lib.types.int;
       };
     };
   };
 
-  config = mkIf cfg.enable {
+  config = lib.mkIf cfg.enable {
     programs.bash.promptPluginInit = ''
-      export LONG_RUNNING_COMMAND_TIMEOUT=${toString cfg.timeout}
+      export LONG_RUNNING_COMMAND_TIMEOUT=${builtins.toString cfg.timeout}
       export UDM_PLAY_SOUND=${if cfg.playSound then "1" else "0"}
       . "${pkgs.undistract-me}/etc/profile.d/undistract-me.sh"
     '';
   };
 
   meta = {
-    maintainers = with maintainers; [ kira-bruneau ];
+    maintainers = with lib.maintainers; [ kira-bruneau ];
   };
 }
diff --git a/nixos/modules/programs/benchexec.nix b/nixos/modules/programs/benchexec.nix
new file mode 100644
index 0000000000000..652670c117ea3
--- /dev/null
+++ b/nixos/modules/programs/benchexec.nix
@@ -0,0 +1,98 @@
+{ lib
+, pkgs
+, config
+, options
+, ...
+}:
+let
+  cfg = config.programs.benchexec;
+  opt = options.programs.benchexec;
+
+  filterUsers = x:
+    if builtins.isString x then config.users.users ? ${x} else
+    if builtins.isInt    x then x                         else
+    throw "filterUsers expects string (username) or int (UID)";
+
+  uid = x:
+    if builtins.isString x then config.users.users.${x}.uid else
+    if builtins.isInt    x then x                           else
+    throw "uid expects string (username) or int (UID)";
+in
+{
+  options.programs.benchexec = {
+    enable = lib.mkEnableOption "BenchExec";
+    package = lib.options.mkPackageOption pkgs "benchexec" { };
+
+    users = lib.options.mkOption {
+      type = with lib.types; listOf (either str int);
+      description = ''
+        Users that intend to use BenchExec.
+        Provide usernames of users that are configured via {option}`${options.users.users}` as string,
+        and UIDs of "mutable users" as integers.
+        Control group delegation will be configured via systemd.
+        For more information, see <https://github.com/sosy-lab/benchexec/blob/3.18/doc/INSTALL.md#setting-up-cgroups>.
+      '';
+      default = [ ];
+      example = lib.literalExpression ''
+        [
+          "alice" # username of a user configured via ${options.users.users}
+          1007    # UID of a mutable user
+        ]
+      '';
+    };
+  };
+
+  config = lib.mkIf cfg.enable {
+    assertions = (map
+      (user: {
+        assertion = config.users.users ? ${user};
+        message = ''
+          The user '${user}' intends to use BenchExec (via `${opt.users}`), but is not configured via `${options.users.users}`.
+        '';
+      })
+      (builtins.filter builtins.isString cfg.users)
+    ) ++ (map
+      (id: {
+        assertion = config.users.mutableUsers;
+        message = ''
+          The user with UID '${id}' intends to use BenchExec (via `${opt.users}`), but mutable users are disabled via `${options.users.mutableUsers}`.
+        '';
+      })
+      (builtins.filter builtins.isInt cfg.users)
+    ) ++ [
+      {
+        assertion = config.systemd.enableUnifiedCgroupHierarchy == true;
+        message = ''
+          The BenchExec module `${opt.enable}` only supports control groups 2 (`${options.systemd.enableUnifiedCgroupHierarchy} = true`).
+        '';
+      }
+    ];
+
+    environment.systemPackages = [ cfg.package ];
+
+    # See <https://github.com/sosy-lab/benchexec/blob/3.18/doc/INSTALL.md#setting-up-cgroups>.
+    systemd.services = builtins.listToAttrs (map
+      (user: {
+        name = "user@${builtins.toString (uid user)}";
+        value = {
+          serviceConfig.Delegate = "yes";
+          overrideStrategy = "asDropin";
+        };
+      })
+      (builtins.filter filterUsers cfg.users));
+
+    # See <https://github.com/sosy-lab/benchexec/blob/3.18/doc/INSTALL.md#requirements>.
+    virtualisation.lxc.lxcfs.enable = lib.mkDefault true;
+
+    # See <https://github.com/sosy-lab/benchexec/blob/3.18/doc/INSTALL.md#requirements>.
+    programs = {
+      cpu-energy-meter.enable = lib.mkDefault true;
+      pqos-wrapper.enable = lib.mkDefault true;
+    };
+
+    # See <https://github.com/sosy-lab/benchexec/blob/3.18/doc/INSTALL.md#kernel-requirements>.
+    security.unprivilegedUsernsClone = true;
+  };
+
+  meta.maintainers = with lib.maintainers; [ lorenzleutgeb ];
+}
diff --git a/nixos/modules/programs/browserpass.nix b/nixos/modules/programs/browserpass.nix
index 2894e237e3d4a..ab6be266ea8d6 100644
--- a/nixos/modules/programs/browserpass.nix
+++ b/nixos/modules/programs/browserpass.nix
@@ -1,12 +1,10 @@
 { config, lib, pkgs, ... }:
 
-with lib;
-
 {
 
-  options.programs.browserpass.enable = mkEnableOption "Browserpass native messaging host";
+  options.programs.browserpass.enable = lib.mkEnableOption "Browserpass native messaging host";
 
-  config = mkIf config.programs.browserpass.enable {
+  config = lib.mkIf config.programs.browserpass.enable {
     environment.etc = let
       appId = "com.github.browserpass.native.json";
       source = part: "${pkgs.browserpass}/lib/browserpass/${part}/${appId}";
diff --git a/nixos/modules/programs/calls.nix b/nixos/modules/programs/calls.nix
index 0cf05f8a2ea0c..36a4c51ddf438 100644
--- a/nixos/modules/programs/calls.nix
+++ b/nixos/modules/programs/calls.nix
@@ -1,19 +1,17 @@
 { config, lib, pkgs, ... }:
 
-with lib;
-
 let
   cfg = config.programs.calls;
 in {
   options = {
     programs.calls = {
-      enable = mkEnableOption ''
+      enable = lib.mkEnableOption ''
         GNOME calls: a phone dialer and call handler
       '';
     };
   };
 
-  config = mkIf cfg.enable {
+  config = lib.mkIf cfg.enable {
     programs.dconf.enable = true;
 
     environment.systemPackages = [
diff --git a/nixos/modules/programs/cdemu.nix b/nixos/modules/programs/cdemu.nix
index 3ee8b2d8fcd65..1aac28af1d2ca 100644
--- a/nixos/modules/programs/cdemu.nix
+++ b/nixos/modules/programs/cdemu.nix
@@ -1,36 +1,34 @@
 { config, lib, pkgs, ... }:
 
-with lib;
-
 let cfg = config.programs.cdemu;
 in {
 
   options = {
     programs.cdemu = {
-      enable = mkOption {
-        type = types.bool;
+      enable = lib.mkOption {
+        type = lib.types.bool;
         default = false;
         description = ''
           {command}`cdemu` for members of
           {option}`programs.cdemu.group`.
         '';
       };
-      group = mkOption {
-        type = types.str;
+      group = lib.mkOption {
+        type = lib.types.str;
         default = "cdrom";
         description = ''
           Group that users must be in to use {command}`cdemu`.
         '';
       };
-      gui = mkOption {
-        type = types.bool;
+      gui = lib.mkOption {
+        type = lib.types.bool;
         default = true;
         description = ''
           Whether to install the {command}`cdemu` GUI (gCDEmu).
         '';
       };
-      image-analyzer = mkOption {
-        type = types.bool;
+      image-analyzer = lib.mkOption {
+        type = lib.types.bool;
         default = true;
         description = ''
           Whether to install the image analyzer.
@@ -39,7 +37,7 @@ in {
     };
   };
 
-  config = mkIf cfg.enable {
+  config = lib.mkIf cfg.enable {
 
     boot = {
       extraModulePackages = [ config.boot.kernelPackages.vhba ];
@@ -68,8 +66,8 @@ in {
 
     environment.systemPackages =
       [ pkgs.cdemu-daemon pkgs.cdemu-client ]
-      ++ optional cfg.gui pkgs.gcdemu
-      ++ optional cfg.image-analyzer pkgs.image-analyzer;
+      ++ lib.optional cfg.gui pkgs.gcdemu
+      ++ lib.optional cfg.image-analyzer pkgs.image-analyzer;
   };
 
 }
diff --git a/nixos/modules/programs/cfs-zen-tweaks.nix b/nixos/modules/programs/cfs-zen-tweaks.nix
index 28d1ef5992d7d..bc16264039352 100644
--- a/nixos/modules/programs/cfs-zen-tweaks.nix
+++ b/nixos/modules/programs/cfs-zen-tweaks.nix
@@ -2,8 +2,6 @@
 
 { config, pkgs, lib, ... }:
 
-with lib;
-
 let
 
   cfg = config.programs.cfs-zen-tweaks;
@@ -13,14 +11,14 @@ in
 {
 
   meta = {
-    maintainers = with maintainers; [ mkg20001 ];
+    maintainers = with lib.maintainers; [ mkg20001 ];
   };
 
   options = {
-    programs.cfs-zen-tweaks.enable = mkEnableOption "CFS Zen Tweaks";
+    programs.cfs-zen-tweaks.enable = lib.mkEnableOption "CFS Zen Tweaks";
   };
 
-  config = mkIf cfg.enable {
+  config = lib.mkIf cfg.enable {
     systemd.packages = [ pkgs.cfs-zen-tweaks ];
 
     systemd.services.set-cfs-tweaks.wantedBy = [
diff --git a/nixos/modules/programs/chromium.nix b/nixos/modules/programs/chromium.nix
index fa5abe957a904..4d248dbe0945f 100644
--- a/nixos/modules/programs/chromium.nix
+++ b/nixos/modules/programs/chromium.nix
@@ -1,11 +1,9 @@
 { config, lib, pkgs, ... }:
 
-with lib;
-
 let
   cfg = config.programs.chromium;
 
-  defaultProfile = filterAttrs (k: v: v != null) {
+  defaultProfile = lib.filterAttrs (k: v: v != null) {
     HomepageLocation = cfg.homepageLocation;
     DefaultSearchProviderEnabled = cfg.defaultSearchProviderEnabled;
     DefaultSearchProviderSearchURL = cfg.defaultSearchProviderSearchURL;
@@ -19,14 +17,14 @@ in
 
   options = {
     programs.chromium = {
-      enable = mkEnableOption "{command}`chromium` policies";
+      enable = lib.mkEnableOption "{command}`chromium` policies";
 
-      enablePlasmaBrowserIntegration = mkEnableOption "Native Messaging Host for Plasma Browser Integration";
+      enablePlasmaBrowserIntegration = lib.mkEnableOption "Native Messaging Host for Plasma Browser Integration";
 
-      plasmaBrowserIntegrationPackage = mkPackageOption pkgs [ "plasma5Packages" "plasma-browser-integration" ] { };
+      plasmaBrowserIntegrationPackage = lib.mkPackageOption pkgs [ "plasma5Packages" "plasma-browser-integration" ] { };
 
-      extensions = mkOption {
-        type = with types; nullOr (listOf str);
+      extensions = lib.mkOption {
+        type = with lib.types; nullOr (listOf str);
         description = ''
           List of chromium extensions to install.
           For list of plugins ids see id in url of extensions on
@@ -38,7 +36,7 @@ in
           for additional details.
         '';
         default = null;
-        example = literalExpression ''
+        example = lib.literalExpression ''
           [
             "chlffgpmiacpedhhbkiomidkjlcfhogd" # pushbullet
             "mbniclmhobmnbdlbpiphghaielnnpgdp" # lightshot
@@ -48,36 +46,36 @@ in
         '';
       };
 
-      homepageLocation = mkOption {
-        type = types.nullOr types.str;
+      homepageLocation = lib.mkOption {
+        type = lib.types.nullOr lib.types.str;
         description = "Chromium default homepage";
         default = null;
         example = "https://nixos.org";
       };
 
-      defaultSearchProviderEnabled = mkOption {
-        type = types.nullOr types.bool;
+      defaultSearchProviderEnabled = lib.mkOption {
+        type = lib.types.nullOr lib.types.bool;
         description = "Enable the default search provider.";
         default = null;
         example = true;
       };
 
-      defaultSearchProviderSearchURL = mkOption {
-        type = types.nullOr types.str;
+      defaultSearchProviderSearchURL = lib.mkOption {
+        type = lib.types.nullOr lib.types.str;
         description = "Chromium default search provider url.";
         default = null;
         example = "https://encrypted.google.com/search?q={searchTerms}&{google:RLZ}{google:originalQueryForSuggestion}{google:assistedQueryStats}{google:searchFieldtrialParameter}{google:searchClient}{google:sourceId}{google:instantExtendedEnabledParameter}ie={inputEncoding}";
       };
 
-      defaultSearchProviderSuggestURL = mkOption {
-        type = types.nullOr types.str;
+      defaultSearchProviderSuggestURL = lib.mkOption {
+        type = lib.types.nullOr lib.types.str;
         description = "Chromium default search provider url for suggestions.";
         default = null;
         example = "https://encrypted.google.com/complete/search?output=chrome&q={searchTerms}";
       };
 
-      extraOpts = mkOption {
-        type = types.attrs;
+      extraOpts = lib.mkOption {
+        type = lib.types.attrs;
         description = ''
           Extra chromium policy options. A list of available policies
           can be found in the Chrome Enterprise documentation:
@@ -85,7 +83,7 @@ in
           Make sure the selected policy is supported on Linux and your browser version.
         '';
         default = {};
-        example = literalExpression ''
+        example = lib.literalExpression ''
           {
             "BrowserSignin" = 0;
             "SyncDisabled" = true;
@@ -99,8 +97,8 @@ in
         '';
       };
 
-      initialPrefs = mkOption {
-        type = types.attrs;
+      initialPrefs = lib.mkOption {
+        type = lib.types.attrs;
         description = ''
           Initial preferences are used to configure the browser for the first run.
           Unlike {option}`programs.chromium.extraOpts`, initialPrefs can be changed by users in the browser settings.
@@ -108,7 +106,7 @@ in
           <https://www.chromium.org/administrators/configuring-other-preferences/>
         '';
         default = {};
-        example = literalExpression ''
+        example = lib.literalExpression ''
           {
             "first_run_tabs" = [
               "https://nixos.org/"
diff --git a/nixos/modules/programs/cnping.nix b/nixos/modules/programs/cnping.nix
index 77cbf4d82086b..f4b5aa845b5f2 100644
--- a/nixos/modules/programs/cnping.nix
+++ b/nixos/modules/programs/cnping.nix
@@ -1,18 +1,16 @@
 { config, lib, pkgs, ... }:
 
-with lib;
-
 let
   cfg = config.programs.cnping;
 in
 {
   options = {
     programs.cnping = {
-      enable = mkEnableOption "a setcap wrapper for cnping";
+      enable = lib.mkEnableOption "a setcap wrapper for cnping";
     };
   };
 
-  config = mkIf cfg.enable {
+  config = lib.mkIf cfg.enable {
     security.wrappers.cnping = {
       source = "${pkgs.cnping}/bin/cnping";
       capabilities = "cap_net_raw+ep";
diff --git a/nixos/modules/programs/command-not-found/command-not-found.nix b/nixos/modules/programs/command-not-found/command-not-found.nix
index 4d2a89b515842..a223e811728dc 100644
--- a/nixos/modules/programs/command-not-found/command-not-found.nix
+++ b/nixos/modules/programs/command-not-found/command-not-found.nix
@@ -5,8 +5,6 @@
 
 { config, lib, pkgs, ... }:
 
-with lib;
-
 let
   cfg = config.programs.command-not-found;
   commandNotFound = pkgs.substituteAll {
@@ -23,8 +21,8 @@ in
 {
   options.programs.command-not-found = {
 
-    enable = mkOption {
-      type = types.bool;
+    enable = lib.mkOption {
+      type = lib.types.bool;
       default = true;
       description = ''
         Whether interactive shells should show which Nix package (if
@@ -32,7 +30,7 @@ in
       '';
     };
 
-    dbPath = mkOption {
+    dbPath = lib.mkOption {
       default = "/nix/var/nix/profiles/per-user/root/channels/nixos/programs.sqlite" ;
       description = ''
         Absolute path to programs.sqlite.
@@ -40,11 +38,11 @@ in
         By default this file will be provided by your channel
         (nixexprs.tar.xz).
       '';
-      type = types.path;
+      type = lib.types.path;
     };
   };
 
-  config = mkIf cfg.enable {
+  config = lib.mkIf cfg.enable {
     programs.bash.interactiveShellInit =
       ''
         # This function is called whenever a command is not found.
diff --git a/nixos/modules/programs/cpu-energy-meter.nix b/nixos/modules/programs/cpu-energy-meter.nix
new file mode 100644
index 0000000000000..653ec067492d7
--- /dev/null
+++ b/nixos/modules/programs/cpu-energy-meter.nix
@@ -0,0 +1,27 @@
+{ config
+, lib
+, pkgs
+, ...
+}: {
+  options.programs.cpu-energy-meter = {
+    enable = lib.mkEnableOption "CPU Energy Meter";
+    package = lib.mkPackageOption pkgs "cpu-energy-meter" { };
+  };
+
+  config =
+    let
+      cfg = config.programs.cpu-energy-meter;
+    in
+    lib.mkIf cfg.enable {
+      hardware.cpu.x86.msr.enable = true;
+
+      security.wrappers.${cfg.package.meta.mainProgram} = {
+        owner = "nobody";
+        group = config.hardware.cpu.x86.msr.group;
+        source = lib.getExe cfg.package;
+        capabilities = "cap_sys_rawio=ep";
+      };
+    };
+
+  meta.maintainers = with lib.maintainers; [ lorenzleutgeb ];
+}
diff --git a/nixos/modules/programs/criu.nix b/nixos/modules/programs/criu.nix
index 9414d0b27f0d2..492a158923cb2 100644
--- a/nixos/modules/programs/criu.nix
+++ b/nixos/modules/programs/criu.nix
@@ -1,14 +1,12 @@
 { config, lib, pkgs, ... }:
 
-with lib;
-
 let cfg = config.programs.criu;
 in {
 
   options = {
     programs.criu = {
-      enable = mkOption {
-        type = types.bool;
+      enable = lib.mkOption {
+        type = lib.types.bool;
         default = false;
         description = ''
           Install {command}`criu` along with necessary kernel options.
@@ -16,7 +14,7 @@ in {
       };
     };
   };
-  config = mkIf cfg.enable {
+  config = lib.mkIf cfg.enable {
     system.requiredKernelConfig = with config.lib.kernelConfig; [
       (isYes "CHECKPOINT_RESTORE")
     ];
diff --git a/nixos/modules/programs/digitalbitbox/default.nix b/nixos/modules/programs/digitalbitbox/default.nix
index 10b5a88171fcd..06d33966b4a07 100644
--- a/nixos/modules/programs/digitalbitbox/default.nix
+++ b/nixos/modules/programs/digitalbitbox/default.nix
@@ -1,29 +1,27 @@
 { config, lib, pkgs, ... }:
 
-with lib;
-
 let
   cfg = config.programs.digitalbitbox;
 in
 
 {
   options.programs.digitalbitbox = {
-    enable = mkOption {
-      type = types.bool;
+    enable = lib.mkOption {
+      type = lib.types.bool;
       default = false;
       description = ''
         Installs the Digital Bitbox application and enables the complementary hardware module.
       '';
     };
 
-    package = mkPackageOption pkgs "digitalbitbox" {
+    package = lib.mkPackageOption pkgs "digitalbitbox" {
       extraDescription = ''
         This can be used to install a package with udev rules that differ from the defaults.
       '';
     };
   };
 
-  config = mkIf cfg.enable {
+  config = lib.mkIf cfg.enable {
     environment.systemPackages = [ cfg.package ];
     hardware.digitalbitbox = {
       enable = true;
diff --git a/nixos/modules/programs/dmrconfig.nix b/nixos/modules/programs/dmrconfig.nix
index 15338681e642a..0078ca19f41a1 100644
--- a/nixos/modules/programs/dmrconfig.nix
+++ b/nixos/modules/programs/dmrconfig.nix
@@ -1,19 +1,17 @@
 { config, lib, pkgs, ... }:
 
-with lib;
-
 let
   cfg = config.programs.dmrconfig;
 
 in {
-  meta.maintainers = with maintainers; [ ];
+  meta.maintainers = with lib.maintainers; [ ];
 
   ###### interface
   options = {
     programs.dmrconfig = {
-      enable = mkOption {
+      enable = lib.mkOption {
         default = false;
-        type = types.bool;
+        type = lib.types.bool;
         description = ''
           Whether to configure system to enable use of dmrconfig. This
           enables the required udev rules and installs the program.
@@ -21,12 +19,12 @@ in {
         relatedPackages = [ "dmrconfig" ];
       };
 
-      package = mkPackageOption pkgs "dmrconfig" { };
+      package = lib.mkPackageOption pkgs "dmrconfig" { };
     };
   };
 
   ###### implementation
-  config = mkIf cfg.enable {
+  config = lib.mkIf cfg.enable {
     environment.systemPackages = [ cfg.package ];
     services.udev.packages = [ cfg.package ];
   };
diff --git a/nixos/modules/programs/droidcam.nix b/nixos/modules/programs/droidcam.nix
index 9843a1f5be252..eef3997e6b809 100644
--- a/nixos/modules/programs/droidcam.nix
+++ b/nixos/modules/programs/droidcam.nix
@@ -1,10 +1,8 @@
 { lib, pkgs, config, ... }:
 
-with lib;
-
 {
   options.programs.droidcam = {
-    enable = mkEnableOption "DroidCam client";
+    enable = lib.mkEnableOption "DroidCam client";
   };
 
   config = lib.mkIf config.programs.droidcam.enable {
diff --git a/nixos/modules/programs/dublin-traceroute.nix b/nixos/modules/programs/dublin-traceroute.nix
index 6ff8a5bdefc39..de9446ad7377c 100644
--- a/nixos/modules/programs/dublin-traceroute.nix
+++ b/nixos/modules/programs/dublin-traceroute.nix
@@ -1,7 +1,5 @@
 { config, lib, pkgs, ... }:
 
-with lib;
-
 let
   cfg = config.programs.dublin-traceroute;
 
@@ -10,22 +8,22 @@ in {
 
   options = {
     programs.dublin-traceroute = {
-      enable = mkEnableOption ''
+      enable = lib.mkEnableOption ''
       dublin-traceroute, add it to the global environment and configure a setcap wrapper for it.
       '';
 
-      package = mkPackageOption pkgs "dublin-traceroute" { };
+      package = lib.mkPackageOption pkgs "dublin-traceroute" { };
     };
   };
 
-  config = mkIf cfg.enable {
+  config = lib.mkIf cfg.enable {
     environment.systemPackages = [ cfg.package ];
 
     security.wrappers.dublin-traceroute = {
       owner = "root";
       group = "root";
       capabilities = "cap_net_raw+p";
-      source = getExe cfg.package;
+      source = lib.getExe cfg.package;
     };
   };
 }
diff --git a/nixos/modules/programs/ecryptfs.nix b/nixos/modules/programs/ecryptfs.nix
index ced5eb26fb9a2..8674f7ec80e0a 100644
--- a/nixos/modules/programs/ecryptfs.nix
+++ b/nixos/modules/programs/ecryptfs.nix
@@ -1,16 +1,14 @@
 { config, lib, pkgs, ... }:
 
-with lib;
-
 let
   cfg = config.programs.ecryptfs;
 
 in {
   options.programs.ecryptfs = {
-    enable = mkEnableOption "ecryptfs setuid mount wrappers";
+    enable = lib.mkEnableOption "ecryptfs setuid mount wrappers";
   };
 
-  config = mkIf cfg.enable {
+  config = lib.mkIf cfg.enable {
     security.wrappers = {
 
       "mount.ecryptfs_private" = {
diff --git a/nixos/modules/programs/environment.nix b/nixos/modules/programs/environment.nix
index 8ac723f42f61a..8a565b7bcac46 100644
--- a/nixos/modules/programs/environment.nix
+++ b/nixos/modules/programs/environment.nix
@@ -4,8 +4,6 @@
 
 { config, lib, ... }:
 
-with lib;
-
 let
 
   cfg = config.environment;
@@ -20,14 +18,14 @@ in
       { NIXPKGS_CONFIG = "/etc/nix/nixpkgs-config.nix";
         # note: many programs exec() this directly, so default options for less must not
         # be specified here; do so in the default value of programs.less.envVariables instead
-        PAGER = mkDefault "less";
-        EDITOR = mkDefault "nano";
+        PAGER = lib.mkDefault "less";
+        EDITOR = lib.mkDefault "nano";
       };
 
     # since we set PAGER to this above, make sure it's installed
     programs.less.enable = true;
 
-    environment.profiles = mkAfter
+    environment.profiles = lib.mkAfter
       [ "/nix/var/nix/profiles/default"
         "/run/current-system/sw"
       ];
@@ -53,7 +51,7 @@ in
     environment.extraInit =
       ''
          export NIX_USER_PROFILE_DIR="/nix/var/nix/profiles/per-user/$USER"
-         export NIX_PROFILES="${concatStringsSep " " (reverseList cfg.profiles)}"
+         export NIX_PROFILES="${builtins.concatStringsSep " " (lib.reverseList cfg.profiles)}"
       '';
 
   };
diff --git a/nixos/modules/programs/extra-container.nix b/nixos/modules/programs/extra-container.nix
index c10ccd7691688..6dcfba7971da2 100644
--- a/nixos/modules/programs/extra-container.nix
+++ b/nixos/modules/programs/extra-container.nix
@@ -1,16 +1,15 @@
 { config, pkgs, lib, ... }:
 
-with lib;
 let
   cfg = config.programs.extra-container;
 in {
   options = {
-    programs.extra-container.enable = mkEnableOption ''
+    programs.extra-container.enable = lib.mkEnableOption ''
       extra-container, a tool for running declarative NixOS containers
       without host system rebuilds
     '';
   };
-  config = mkIf cfg.enable {
+  config = lib.mkIf cfg.enable {
     environment.systemPackages = [ pkgs.extra-container ];
     boot.extraSystemdUnitPaths = [ "/etc/systemd-mutable/system" ];
   };
diff --git a/nixos/modules/programs/feedbackd.nix b/nixos/modules/programs/feedbackd.nix
index 9de604c34a7ea..0c82c7840c8f1 100644
--- a/nixos/modules/programs/feedbackd.nix
+++ b/nixos/modules/programs/feedbackd.nix
@@ -1,21 +1,19 @@
 { pkgs, lib, config, ... }:
 
-with lib;
-
 let
   cfg = config.programs.feedbackd;
 in {
   options = {
     programs.feedbackd = {
-      enable = mkEnableOption ''
+      enable = lib.mkEnableOption ''
         the feedbackd D-BUS service and udev rules.
 
         Your user needs to be in the `feedbackd` group to trigger effects
       '';
-      package = mkPackageOption pkgs "feedbackd" { };
+      package = lib.mkPackageOption pkgs "feedbackd" { };
     };
   };
-  config = mkIf cfg.enable {
+  config = lib.mkIf cfg.enable {
     environment.systemPackages = [ cfg.package ];
 
     services.dbus.packages = [ cfg.package ];
diff --git a/nixos/modules/programs/firefox.nix b/nixos/modules/programs/firefox.nix
index 39b30be48de9d..7e0dec57d2dac 100644
--- a/nixos/modules/programs/firefox.nix
+++ b/nixos/modules/programs/firefox.nix
@@ -1,7 +1,5 @@
 { pkgs, config, lib, ... }:
 
-with lib;
-
 let
   cfg = config.programs.firefox;
 
@@ -62,13 +60,13 @@ let
 in
 {
   options.programs.firefox = {
-    enable = mkEnableOption "the Firefox web browser";
+    enable = lib.mkEnableOption "the Firefox web browser";
 
-    package = mkOption {
-      type = types.package;
+    package = lib.mkOption {
+      type = lib.types.package;
       default = pkgs.firefox;
       description = "Firefox package to use.";
-      defaultText = literalExpression "pkgs.firefox";
+      defaultText = lib.literalExpression "pkgs.firefox";
       relatedPackages = [
         "firefox"
         "firefox-beta-bin"
@@ -78,13 +76,13 @@ in
       ];
     };
 
-    wrapperConfig = mkOption {
-      type = types.attrs;
+    wrapperConfig = lib.mkOption {
+      type = lib.types.attrs;
       default = {};
       description = "Arguments to pass to Firefox wrapper";
     };
 
-    policies = mkOption {
+    policies = lib.mkOption {
       type = policyFormat.type;
       default = { };
       description = ''
@@ -100,8 +98,8 @@ in
       '';
     };
 
-    preferences = mkOption {
-      type = with types; attrsOf (oneOf [ bool int str ]);
+    preferences = lib.mkOption {
+      type = with lib.types; attrsOf (oneOf [ bool int str ]);
       default = { };
       description = ''
         Preferences to set from `about:config`.
@@ -113,8 +111,8 @@ in
       '';
     };
 
-    preferencesStatus = mkOption {
-      type = types.enum [ "default" "locked" "user" "clear" ];
+    preferencesStatus = lib.mkOption {
+      type = lib.types.enum [ "default" "locked" "user" "clear" ];
       default = "locked";
       description = ''
         The status of `firefox.preferences`.
@@ -127,9 +125,9 @@ in
       '';
     };
 
-    languagePacks = mkOption {
+    languagePacks = lib.mkOption {
       # Available languages can be found in https://releases.mozilla.org/pub/firefox/releases/${cfg.package.version}/linux-x86_64/xpi/
-      type = types.listOf (types.enum ([
+      type = lib.types.listOf (lib.types.enum ([
         "ach"
         "af"
         "an"
@@ -235,8 +233,8 @@ in
       '';
     };
 
-    autoConfig = mkOption {
-      type = types.lines;
+    autoConfig = lib.mkOption {
+      type = lib.types.lines;
       default = "";
       description = ''
         AutoConfig files can be used to set and lock preferences that are not covered
@@ -247,19 +245,19 @@ in
     };
 
     nativeMessagingHosts = ({
-      packages = mkOption {
-        type = types.listOf types.package;
+      packages = lib.mkOption {
+        type = lib.types.listOf lib.types.package;
         default = [];
         description = ''
           Additional packages containing native messaging hosts that should be made available to Firefox extensions.
         '';
       };
-    }) // (mapAttrs (k: v: mkEnableOption "${v.name} support") nmhOptions);
+    }) // (builtins.mapAttrs (k: v: lib.mkEnableOption "${v.name} support") nmhOptions);
   };
 
   config = let
-    forEachEnabledNmh = fn: flatten (mapAttrsToList (k: v: lib.optional cfg.nativeMessagingHosts.${k} (fn k v)) nmhOptions);
-  in mkIf cfg.enable {
+    forEachEnabledNmh = fn: lib.flatten (lib.mapAttrsToList (k: v: lib.optional cfg.nativeMessagingHosts.${k} (fn k v)) nmhOptions);
+  in lib.mkIf cfg.enable {
     warnings = forEachEnabledNmh (k: v:
       "The `programs.firefox.nativeMessagingHosts.${k}` option is deprecated, " +
       "please add `${v.package.pname}` to `programs.firefox.nativeMessagingHosts.packages` instead."
@@ -278,18 +276,18 @@ in
       let
         policiesJSON = policyFormat.generate "firefox-policies.json" { inherit (cfg) policies; };
       in
-      mkIf (cfg.policies != { }) {
+      lib.mkIf (cfg.policies != { }) {
         "firefox/policies/policies.json".source = "${policiesJSON}";
       };
 
     # Preferences are converted into a policy
     programs.firefox.policies = {
       DisableAppUpdate = true;
-      Preferences = (mapAttrs
+      Preferences = (builtins.mapAttrs
         (_: value: { Value = value; Status = cfg.preferencesStatus; })
         cfg.preferences);
-      ExtensionSettings = listToAttrs (map
-        (lang: nameValuePair
+      ExtensionSettings = builtins.listToAttrs (builtins.map
+        (lang: lib.attrsets.nameValuePair
           "langpack-${lang}@firefox.mozilla.org"
           {
             installation_mode = "normal_installed";
@@ -300,5 +298,5 @@ in
     };
   };
 
-  meta.maintainers = with maintainers; [ danth ];
+  meta.maintainers = with lib.maintainers; [ danth ];
 }
diff --git a/nixos/modules/programs/firejail.nix b/nixos/modules/programs/firejail.nix
index 0510cf8c610d4..90da938182748 100644
--- a/nixos/modules/programs/firejail.nix
+++ b/nixos/modules/programs/firejail.nix
@@ -1,7 +1,5 @@
 { config, lib, pkgs, ... }:
 
-with lib;
-
 let
   cfg = config.programs.firejail;
 
@@ -21,13 +19,13 @@ let
         else { executable = value; desktop = null; profile = null; extraArgs = []; };
         args = lib.escapeShellArgs (
           opts.extraArgs
-          ++ (optional (opts.profile != null) "--profile=${toString opts.profile}")
+          ++ (lib.optional (opts.profile != null) "--profile=${builtins.toString opts.profile}")
         );
       in
       ''
         cat <<_EOF >$out/bin/${command}
         #! ${pkgs.runtimeShell} -e
-        exec /run/wrappers/bin/firejail ${args} -- ${toString opts.executable} "\$@"
+        exec /run/wrappers/bin/firejail ${args} -- ${builtins.toString opts.executable} "\$@"
         _EOF
         chmod 0755 $out/bin/${command}
 
@@ -40,30 +38,30 @@ let
 
 in {
   options.programs.firejail = {
-    enable = mkEnableOption "firejail, a sandboxing tool for Linux";
+    enable = lib.mkEnableOption "firejail, a sandboxing tool for Linux";
 
-    wrappedBinaries = mkOption {
-      type = types.attrsOf (types.either types.path (types.submodule {
+    wrappedBinaries = lib.mkOption {
+      type = lib.types.attrsOf (lib.types.either lib.types.path (lib.types.submodule {
         options = {
-          executable = mkOption {
-            type = types.path;
+          executable = lib.mkOption {
+            type = lib.types.path;
             description = "Executable to run sandboxed";
-            example = literalExpression ''"''${lib.getBin pkgs.firefox}/bin/firefox"'';
+            example = lib.literalExpression ''"''${lib.getBin pkgs.firefox}/bin/firefox"'';
           };
-          desktop = mkOption {
-            type = types.nullOr types.path;
+          desktop = lib.mkOption {
+            type = lib.types.nullOr lib.types.path;
             default = null;
             description = ".desktop file to modify. Only necessary if it uses the absolute path to the executable.";
-            example = literalExpression ''"''${pkgs.firefox}/share/applications/firefox.desktop"'';
+            example = lib.literalExpression ''"''${pkgs.firefox}/share/applications/firefox.desktop"'';
           };
-          profile = mkOption {
-            type = types.nullOr types.path;
+          profile = lib.mkOption {
+            type = lib.types.nullOr lib.types.path;
             default = null;
             description = "Profile to use";
-            example = literalExpression ''"''${pkgs.firejail}/etc/firejail/firefox.profile"'';
+            example = lib.literalExpression ''"''${pkgs.firejail}/etc/firejail/firefox.profile"'';
           };
-          extraArgs = mkOption {
-            type = types.listOf types.str;
+          extraArgs = lib.mkOption {
+            type = lib.types.listOf lib.types.str;
             default = [];
             description = "Extra arguments to pass to firejail";
             example = [ "--private=~/.firejail_home" ];
@@ -71,7 +69,7 @@ in {
         };
       }));
       default = {};
-      example = literalExpression ''
+      example = lib.literalExpression ''
         {
           firefox = {
             executable = "''${lib.getBin pkgs.firefox}/bin/firefox";
@@ -89,7 +87,7 @@ in {
     };
   };
 
-  config = mkIf cfg.enable {
+  config = lib.mkIf cfg.enable {
     security.wrappers.firejail =
       { setuid = true;
         owner = "root";
@@ -100,5 +98,5 @@ in {
     environment.systemPackages = [ pkgs.firejail ] ++ [ wrappedBins ];
   };
 
-  meta.maintainers = with maintainers; [ peterhoeg ];
+  meta.maintainers = with lib.maintainers; [ peterhoeg ];
 }
diff --git a/nixos/modules/programs/fish.nix b/nixos/modules/programs/fish.nix
index ebc16f6ff0129..5a6fdb9b5ec5a 100644
--- a/nixos/modules/programs/fish.nix
+++ b/nixos/modules/programs/fish.nix
@@ -1,21 +1,19 @@
 { config, lib, pkgs, ... }:
 
-with lib;
-
 let
 
   cfge = config.environment;
 
   cfg = config.programs.fish;
 
-  fishAbbrs = concatStringsSep "\n" (
-    mapAttrsFlatten (k: v: "abbr -ag ${k} ${escapeShellArg v}")
+  fishAbbrs = lib.concatStringsSep "\n" (
+    lib.mapAttrsFlatten (k: v: "abbr -ag ${k} ${lib.escapeShellArg v}")
       cfg.shellAbbrs
   );
 
-  fishAliases = concatStringsSep "\n" (
-    mapAttrsFlatten (k: v: "alias ${k} ${escapeShellArg v}")
-      (filterAttrs (k: v: v != null) cfg.shellAliases)
+  fishAliases = lib.concatStringsSep "\n" (
+    lib.mapAttrsFlatten (k: v: "alias ${k} ${lib.escapeShellArg v}")
+      (lib.filterAttrs (k: v: v != null) cfg.shellAliases)
   );
 
   envShellInit = pkgs.writeText "shellInit" cfge.shellInit;
@@ -47,18 +45,18 @@ in
 
     programs.fish = {
 
-      enable = mkOption {
+      enable = lib.mkOption {
         default = false;
         description = ''
           Whether to configure fish as an interactive shell.
         '';
-        type = types.bool;
+        type = lib.types.bool;
       };
 
-      package = mkPackageOption pkgs "fish" { };
+      package = lib.mkPackageOption pkgs "fish" { };
 
-      useBabelfish = mkOption {
-        type = types.bool;
+      useBabelfish = lib.mkOption {
+        type = lib.types.bool;
         default = false;
         description = ''
           If enabled, the configured environment will be translated to native fish using [babelfish](https://github.com/bouk/babelfish).
@@ -66,31 +64,31 @@ in
         '';
       };
 
-      vendor.config.enable = mkOption {
-        type = types.bool;
+      vendor.config.enable = lib.mkOption {
+        type = lib.types.bool;
         default = true;
         description = ''
           Whether fish should source configuration snippets provided by other packages.
         '';
       };
 
-      vendor.completions.enable = mkOption {
-        type = types.bool;
+      vendor.completions.enable = lib.mkOption {
+        type = lib.types.bool;
         default = true;
         description = ''
           Whether fish should use completion files provided by other packages.
         '';
       };
 
-      vendor.functions.enable = mkOption {
-        type = types.bool;
+      vendor.functions.enable = lib.mkOption {
+        type = lib.types.bool;
         default = true;
         description = ''
           Whether fish should autoload fish functions provided by other packages.
         '';
       };
 
-      shellAbbrs = mkOption {
+      shellAbbrs = lib.mkOption {
         default = {};
         example = {
           gco = "git checkout";
@@ -99,63 +97,63 @@ in
         description = ''
           Set of fish abbreviations.
         '';
-        type = with types; attrsOf str;
+        type = with lib.types; attrsOf str;
       };
 
-      shellAliases = mkOption {
+      shellAliases = lib.mkOption {
         default = {};
         description = ''
           Set of aliases for fish shell, which overrides {option}`environment.shellAliases`.
           See {option}`environment.shellAliases` for an option format description.
         '';
-        type = with types; attrsOf (nullOr (either str path));
+        type = with lib.types; attrsOf (nullOr (either str path));
       };
 
-      shellInit = mkOption {
+      shellInit = lib.mkOption {
         default = "";
         description = ''
           Shell script code called during fish shell initialisation.
         '';
-        type = types.lines;
+        type = lib.types.lines;
       };
 
-      loginShellInit = mkOption {
+      loginShellInit = lib.mkOption {
         default = "";
         description = ''
           Shell script code called during fish login shell initialisation.
         '';
-        type = types.lines;
+        type = lib.types.lines;
       };
 
-      interactiveShellInit = mkOption {
+      interactiveShellInit = lib.mkOption {
         default = "";
         description = ''
           Shell script code called during interactive fish shell initialisation.
         '';
-        type = types.lines;
+        type = lib.types.lines;
       };
 
-      promptInit = mkOption {
+      promptInit = lib.mkOption {
         default = "";
         description = ''
           Shell script code used to initialise fish prompt.
         '';
-        type = types.lines;
+        type = lib.types.lines;
       };
 
     };
 
   };
 
-  config = mkIf cfg.enable {
+  config = lib.mkIf cfg.enable {
 
-    programs.fish.shellAliases = mapAttrs (name: mkDefault) cfge.shellAliases;
+    programs.fish.shellAliases = lib.mapAttrs (name: lib.mkDefault) cfge.shellAliases;
 
     # Required for man completions
     documentation.man.generateCaches = lib.mkDefault true;
 
-    environment = mkMerge [
-      (mkIf cfg.useBabelfish
+    environment = lib.mkMerge [
+      (lib.mkIf cfg.useBabelfish
       {
         etc."fish/setEnvironment.fish".source = babelfishTranslate config.system.build.setEnvironment "setEnvironment";
         etc."fish/shellInit.fish".source = babelfishTranslate envShellInit "shellInit";
@@ -163,7 +161,7 @@ in
         etc."fish/interactiveShellInit.fish".source = babelfishTranslate envInteractiveShellInit "interactiveShellInit";
      })
 
-      (mkIf (!cfg.useBabelfish)
+      (lib.mkIf (!cfg.useBabelfish)
       {
         etc."fish/foreign-env/shellInit".source = envShellInit;
         etc."fish/foreign-env/loginShellInit".source = envLoginShellInit;
@@ -266,7 +264,7 @@ in
                 pathName = substring storeLength (stringLength package - storeLength) package;
               in (package.name or pathName) + "_fish-completions")
             ( { inherit package; } //
-              optionalAttrs (package ? meta.priority) { meta.priority = package.meta.priority; })
+              lib.optionalAttrs (package ? meta.priority) { meta.priority = package.meta.priority; })
             ''
               mkdir -p $out
               if [ -d $package/share/man ]; then
@@ -277,16 +275,16 @@ in
           pkgs.buildEnv {
             name = "system_fish-completions";
             ignoreCollisions = true;
-            paths = map generateCompletions config.environment.systemPackages;
+            paths = builtins.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";
+        ++ lib.optional cfg.vendor.config.enable "/share/fish/vendor_conf.d"
+        ++ lib.optional cfg.vendor.completions.enable "/share/fish/vendor_completions.d"
+        ++ lib.optional cfg.vendor.functions.enable "/share/fish/vendor_functions.d";
       }
 
       { systemPackages = [ cfg.package ]; }
diff --git a/nixos/modules/programs/flashrom.nix b/nixos/modules/programs/flashrom.nix
index 1b9b4493ef201..dd398497c2d0d 100644
--- a/nixos/modules/programs/flashrom.nix
+++ b/nixos/modules/programs/flashrom.nix
@@ -1,14 +1,12 @@
 { config, lib, pkgs, ... }:
 
-with lib;
-
 let
   cfg = config.programs.flashrom;
 in
 {
   options.programs.flashrom = {
-    enable = mkOption {
-      type = types.bool;
+    enable = lib.mkOption {
+      type = lib.types.bool;
       default = false;
       description = ''
         Installs flashrom and configures udev rules for programmers
@@ -16,10 +14,10 @@ in
         group.
       '';
     };
-    package = mkPackageOption pkgs "flashrom" { };
+    package = lib.mkPackageOption pkgs "flashrom" { };
   };
 
-  config = mkIf cfg.enable {
+  config = lib.mkIf cfg.enable {
     services.udev.packages = [ cfg.package ];
     environment.systemPackages = [ cfg.package ];
   };
diff --git a/nixos/modules/programs/flexoptix-app.nix b/nixos/modules/programs/flexoptix-app.nix
index 47a76da125f01..baa9e33882cae 100644
--- a/nixos/modules/programs/flexoptix-app.nix
+++ b/nixos/modules/programs/flexoptix-app.nix
@@ -1,19 +1,17 @@
 { config, pkgs, lib, ... }:
 
-with lib;
-
 let
   cfg = config.programs.flexoptix-app;
 in {
   options = {
     programs.flexoptix-app = {
-      enable = mkEnableOption "FLEXOPTIX app + udev rules";
+      enable = lib.mkEnableOption "FLEXOPTIX app + udev rules";
 
-      package = mkPackageOption pkgs "flexoptix-app" { };
+      package = lib.mkPackageOption pkgs "flexoptix-app" { };
     };
   };
 
-  config = mkIf cfg.enable {
+  config = lib.mkIf cfg.enable {
     environment.systemPackages = [ cfg.package ];
     services.udev.packages = [ cfg.package ];
   };
diff --git a/nixos/modules/programs/freetds.nix b/nixos/modules/programs/freetds.nix
index 8b52fc37c5e03..77daaa8fd3985 100644
--- a/nixos/modules/programs/freetds.nix
+++ b/nixos/modules/programs/freetds.nix
@@ -2,8 +2,6 @@
 
 { config, lib, pkgs, ... }:
 
-with lib;
-
 let
 
   cfg = config.environment.freetds;
@@ -14,10 +12,10 @@ in
 
   options = {
 
-    environment.freetds = mkOption {
-      type = types.attrsOf types.str;
+    environment.freetds = lib.mkOption {
+      type = lib.types.attrsOf lib.types.str;
       default = {};
-      example = literalExpression ''
+      example = lib.literalExpression ''
         { MYDATABASE = '''
             host = 10.0.2.100
             port = 1433
@@ -40,14 +38,14 @@ in
 
   ###### implementation
 
-  config = mkIf (length (attrNames cfg) > 0) {
+  config = lib.mkIf (builtins.length (builtins.attrNames cfg) > 0) {
 
     environment.variables.FREETDSCONF = "/etc/freetds.conf";
     environment.variables.FREETDS = "/etc/freetds.conf";
     environment.variables.SYBASE = "${pkgs.freetds}";
 
     environment.etc."freetds.conf" = { text =
-      (concatStrings (mapAttrsToList (name: value:
+      (lib.concatStrings (lib.mapAttrsToList (name: value:
         ''
         [${name}]
         ${value}
diff --git a/nixos/modules/programs/fuse.nix b/nixos/modules/programs/fuse.nix
index c15896efbb51a..7083194bd9894 100644
--- a/nixos/modules/programs/fuse.nix
+++ b/nixos/modules/programs/fuse.nix
@@ -1,25 +1,23 @@
 { config, lib, ... }:
 
-with lib;
-
 let
   cfg = config.programs.fuse;
 in {
-  meta.maintainers = with maintainers; [ primeos ];
+  meta.maintainers = with lib.maintainers; [ primeos ];
 
   options.programs.fuse = {
-    mountMax = mkOption {
+    mountMax = lib.mkOption {
       # In the C code it's an "int" (i.e. signed and at least 16 bit), but
       # negative numbers obviously make no sense:
-      type = types.ints.between 0 32767; # 2^15 - 1
+      type = lib.types.ints.between 0 32767; # 2^15 - 1
       default = 1000;
       description = ''
         Set the maximum number of FUSE mounts allowed to non-root users.
       '';
     };
 
-    userAllowOther = mkOption {
-      type = types.bool;
+    userAllowOther = lib.mkOption {
+      type = lib.types.bool;
       default = false;
       description = ''
         Allow non-root users to specify the allow_other or allow_root mount
@@ -30,8 +28,8 @@ in {
 
   config =  {
     environment.etc."fuse.conf".text = ''
-      ${optionalString (!cfg.userAllowOther) "#"}user_allow_other
-      mount_max = ${toString cfg.mountMax}
+      ${lib.optionalString (!cfg.userAllowOther) "#"}user_allow_other
+      mount_max = ${builtins.toString cfg.mountMax}
     '';
   };
 }
diff --git a/nixos/modules/programs/gamemode.nix b/nixos/modules/programs/gamemode.nix
index 878f785074f17..14892f9c6eac8 100644
--- a/nixos/modules/programs/gamemode.nix
+++ b/nixos/modules/programs/gamemode.nix
@@ -1,7 +1,5 @@
 { config, lib, pkgs, ... }:
 
-with lib;
-
 let
   cfg = config.programs.gamemode;
   settingsFormat = pkgs.formats.ini { };
@@ -10,20 +8,20 @@ in
 {
   options = {
     programs.gamemode = {
-      enable = mkEnableOption "GameMode to optimise system performance on demand";
+      enable = lib.mkEnableOption "GameMode to optimise system performance on demand";
 
-      enableRenice = mkEnableOption "CAP_SYS_NICE on gamemoded to support lowering process niceness" // {
+      enableRenice = lib.mkEnableOption "CAP_SYS_NICE on gamemoded to support lowering process niceness" // {
         default = true;
       };
 
-      settings = mkOption {
+      settings = lib.mkOption {
         type = settingsFormat.type;
         default = { };
         description = ''
           System-wide configuration for GameMode (/etc/gamemode.ini).
           See gamemoded(8) man page for available settings.
         '';
-        example = literalExpression ''
+        example = lib.literalExpression ''
           {
             general = {
               renice = 10;
@@ -46,7 +44,7 @@ in
     };
   };
 
-  config = mkIf cfg.enable {
+  config = lib.mkIf cfg.enable {
     environment = {
       systemPackages = [ pkgs.gamemode ];
       etc."gamemode.ini".source = configFile;
@@ -54,7 +52,7 @@ in
 
     security = {
       polkit.enable = true;
-      wrappers = mkIf cfg.enableRenice {
+      wrappers = lib.mkIf cfg.enableRenice {
         gamemoded = {
           owner = "root";
           group = "root";
@@ -77,14 +75,14 @@ in
         #
         # This uses a link farm to make sure other wrapped executables
         # aren't included in PATH.
-        environment.PATH = mkForce (pkgs.linkFarm "pkexec" [
+        environment.PATH = lib.mkForce (pkgs.linkFarm "pkexec" [
           {
             name = "pkexec";
             path = "${config.security.wrapperDir}/pkexec";
           }
         ]);
 
-        serviceConfig.ExecStart = mkIf cfg.enableRenice [
+        serviceConfig.ExecStart = lib.mkIf cfg.enableRenice [
           "" # Tell systemd to clear the existing ExecStart list, to prevent appending to it.
           "${config.security.wrapperDir}/gamemoded"
         ];
@@ -95,6 +93,6 @@ in
   };
 
   meta = {
-    maintainers = with maintainers; [ kira-bruneau ];
+    maintainers = with lib.maintainers; [ kira-bruneau ];
   };
 }
diff --git a/nixos/modules/programs/gamescope.nix b/nixos/modules/programs/gamescope.nix
index af9ced4715391..6a0b0a8fbdddd 100644
--- a/nixos/modules/programs/gamescope.nix
+++ b/nixos/modules/programs/gamescope.nix
@@ -3,30 +3,30 @@
 , pkgs
 , ...
 }:
-with lib; let
+let
   cfg = config.programs.gamescope;
 
   gamescope =
     let
       wrapperArgs =
-        optional (cfg.args != [ ])
-          ''--add-flags "${toString cfg.args}"''
-        ++ builtins.attrValues (mapAttrs (var: val: "--set-default ${var} ${val}") cfg.env);
+        lib.optional (cfg.args != [ ])
+          ''--add-flags "${builtins.toString cfg.args}"''
+        ++ builtins.attrValues (builtins.mapAttrs (var: val: "--set-default ${var} ${val}") cfg.env);
     in
     pkgs.runCommand "gamescope" { nativeBuildInputs = [ pkgs.makeBinaryWrapper ]; } ''
       mkdir -p $out/bin
       makeWrapper ${cfg.package}/bin/gamescope $out/bin/gamescope --inherit-argv0 \
-        ${toString wrapperArgs}
+        ${builtins.toString wrapperArgs}
     '';
 in
 {
   options.programs.gamescope = {
-    enable = mkEnableOption "gamescope, the SteamOS session compositing window manager";
+    enable = lib.mkEnableOption "gamescope, the SteamOS session compositing window manager";
 
-    package = mkPackageOption pkgs "gamescope" { };
+    package = lib.mkPackageOption pkgs "gamescope" { };
 
-    capSysNice = mkOption {
-      type = types.bool;
+    capSysNice = lib.mkOption {
+      type = lib.types.bool;
       default = false;
       description = ''
         Add cap_sys_nice capability to the GameScope
@@ -34,8 +34,8 @@ in
       '';
     };
 
-    args = mkOption {
-      type = types.listOf types.str;
+    args = lib.mkOption {
+      type = lib.types.listOf lib.types.str;
       default = [ ];
       example = [ "--rt" "--prefer-vk-device 8086:9bc4" ];
       description = ''
@@ -43,10 +43,10 @@ in
       '';
     };
 
-    env = mkOption {
-      type = types.attrsOf types.str;
+    env = lib.mkOption {
+      type = lib.types.attrsOf lib.types.str;
       default = { };
-      example = literalExpression ''
+      example = lib.literalExpression ''
         # for Prime render offload on Nvidia laptops.
         # Also requires `hardware.nvidia.prime.offload.enable`.
         {
@@ -61,8 +61,8 @@ in
     };
   };
 
-  config = mkIf cfg.enable {
-    security.wrappers = mkIf cfg.capSysNice {
+  config = lib.mkIf cfg.enable {
+    security.wrappers = lib.mkIf cfg.capSysNice {
       gamescope = {
         owner = "root";
         group = "root";
@@ -71,8 +71,8 @@ in
       };
     };
 
-    environment.systemPackages = mkIf (!cfg.capSysNice) [ gamescope ];
+    environment.systemPackages = lib.mkIf (!cfg.capSysNice) [ gamescope ];
   };
 
-  meta.maintainers = with maintainers; [ nrdxp ];
+  meta.maintainers = with lib.maintainers; [ nrdxp ];
 }
diff --git a/nixos/modules/programs/geary.nix b/nixos/modules/programs/geary.nix
index 6103ee7df8591..cfd5bed78d971 100644
--- a/nixos/modules/programs/geary.nix
+++ b/nixos/modules/programs/geary.nix
@@ -1,20 +1,18 @@
 { config, pkgs, lib, ... }:
 
-with lib;
-
 let
   cfg = config.programs.geary;
 
 in {
   meta = {
-    maintainers = teams.gnome.members;
+    maintainers = lib.teams.gnome.members;
   };
 
   options = {
-    programs.geary.enable = mkEnableOption "Geary, a Mail client for GNOME";
+    programs.geary.enable = lib.mkEnableOption "Geary, a Mail client for GNOME";
   };
 
-  config = mkIf cfg.enable {
+  config = lib.mkIf cfg.enable {
     environment.systemPackages = [ pkgs.gnome.geary ];
     programs.dconf.enable = true;
     services.gnome.gnome-keyring.enable = true;
diff --git a/nixos/modules/programs/git.nix b/nixos/modules/programs/git.nix
index 2a5d52f2d191f..e4f6ce937f04d 100644
--- a/nixos/modules/programs/git.nix
+++ b/nixos/modules/programs/git.nix
@@ -1,7 +1,5 @@
 { config, lib, pkgs, ... }:
 
-with lib;
-
 let
   cfg = config.programs.git;
 in
@@ -9,23 +7,23 @@ in
 {
   options = {
     programs.git = {
-      enable = mkEnableOption "git, a distributed version control system";
+      enable = lib.mkEnableOption "git, a distributed version control system";
 
-      package = mkPackageOption pkgs "git" {
+      package = lib.mkPackageOption pkgs "git" {
         example = "gitFull";
       };
 
-      config = mkOption {
+      config = lib.mkOption {
         type =
-          with types;
+          with lib.types;
           let
             gitini = attrsOf (attrsOf anything);
           in
           either gitini (listOf gitini) // {
             merge = loc: defs:
               let
-                config = foldl'
-                  (acc: { value, ... }@x: acc // (if isList value then {
+                config = builtins.foldl'
+                  (acc: { value, ... }@x: acc // (if builtins.isList value then {
                     ordered = acc.ordered ++ value;
                   } else {
                     unordered = acc.unordered ++ [ x ];
@@ -55,25 +53,25 @@ in
       };
 
       prompt = {
-        enable = mkEnableOption "automatically sourcing git-prompt.sh. This does not change $PS1; it simply provides relevant utility functions";
+        enable = lib.mkEnableOption "automatically sourcing git-prompt.sh. This does not change $PS1; it simply provides relevant utility functions";
       };
 
       lfs = {
-        enable = mkEnableOption "git-lfs (Large File Storage)";
+        enable = lib.mkEnableOption "git-lfs (Large File Storage)";
 
-        package = mkPackageOption pkgs "git-lfs" { };
+        package = lib.mkPackageOption pkgs "git-lfs" { };
       };
     };
   };
 
-  config = mkMerge [
-    (mkIf cfg.enable {
+  config = lib.mkMerge [
+    (lib.mkIf cfg.enable {
       environment.systemPackages = [ cfg.package ];
-      environment.etc.gitconfig = mkIf (cfg.config != [ ]) {
-        text = concatMapStringsSep "\n" generators.toGitINI cfg.config;
+      environment.etc.gitconfig = lib.mkIf (cfg.config != [ ]) {
+        text = lib.concatMapStringsSep "\n" lib.generators.toGitINI cfg.config;
       };
     })
-    (mkIf (cfg.enable && cfg.lfs.enable) {
+    (lib.mkIf (cfg.enable && cfg.lfs.enable) {
       environment.systemPackages = [ cfg.lfs.package ];
       programs.git.config = {
         filter.lfs = {
@@ -84,12 +82,12 @@ in
         };
       };
     })
-    (mkIf (cfg.enable && cfg.prompt.enable) {
+    (lib.mkIf (cfg.enable && cfg.prompt.enable) {
       environment.interactiveShellInit = ''
         source ${cfg.package}/share/bash-completion/completions/git-prompt.sh
       '';
     })
   ];
 
-  meta.maintainers = with maintainers; [ figsoda ];
+  meta.maintainers = with lib.maintainers; [ figsoda ];
 }
diff --git a/nixos/modules/programs/gnupg.nix b/nixos/modules/programs/gnupg.nix
index c755d110170c6..eb983d9ce78a9 100644
--- a/nixos/modules/programs/gnupg.nix
+++ b/nixos/modules/programs/gnupg.nix
@@ -8,22 +8,6 @@ let
   agentSettingsFormat = pkgs.formats.keyValue {
     mkKeyValue = lib.generators.mkKeyValueDefault { } " ";
   };
-
-  xserverCfg = config.services.xserver;
-
-  defaultPinentryFlavor =
-    if xserverCfg.desktopManager.lxqt.enable
-    || xserverCfg.desktopManager.plasma5.enable
-    || xserverCfg.desktopManager.plasma6.enable
-    || xserverCfg.desktopManager.deepin.enable then
-      "qt"
-    else if xserverCfg.desktopManager.xfce.enable then
-      "gtk2"
-    else if xserverCfg.enable || config.programs.sway.enable then
-      "gnome3"
-    else
-      "curses";
-
 in
 {
   imports = [
diff --git a/nixos/modules/programs/gphoto2.nix b/nixos/modules/programs/gphoto2.nix
index d99259b545825..d9f09483f63c1 100644
--- a/nixos/modules/programs/gphoto2.nix
+++ b/nixos/modules/programs/gphoto2.nix
@@ -1,16 +1,14 @@
 { config, lib, pkgs, ... }:
 
-with lib;
-
 {
-  meta.maintainers = [ maintainers.league ];
+  meta.maintainers = [ lib.maintainers.league ];
 
   ###### interface
   options = {
     programs.gphoto2 = {
-      enable = mkOption {
+      enable = lib.mkOption {
         default = false;
-        type = types.bool;
+        type = lib.types.bool;
         description = ''
           Whether to configure system to use gphoto2.
           To grant digital camera access to a user, the user must
@@ -22,7 +20,7 @@ with lib;
   };
 
   ###### implementation
-  config = mkIf config.programs.gphoto2.enable {
+  config = lib.mkIf config.programs.gphoto2.enable {
     services.udev.packages = [ pkgs.libgphoto2 ];
     environment.systemPackages = [ pkgs.gphoto2 ];
     users.groups.camera = {};
diff --git a/nixos/modules/programs/haguichi.nix b/nixos/modules/programs/haguichi.nix
index 4f48551cf1dac..fd769ac8d0a03 100644
--- a/nixos/modules/programs/haguichi.nix
+++ b/nixos/modules/programs/haguichi.nix
@@ -1,13 +1,11 @@
 { lib, pkgs, config, ... }:
 
-with lib;
-
 {
   options.programs.haguichi = {
-    enable = mkEnableOption "Haguichi, a Linux GUI frontend to the proprietary LogMeIn Hamachi";
+    enable = lib.mkEnableOption "Haguichi, a Linux GUI frontend to the proprietary LogMeIn Hamachi";
   };
 
-  config = mkIf config.programs.haguichi.enable {
+  config = lib.mkIf config.programs.haguichi.enable {
     environment.systemPackages = with pkgs; [ haguichi ];
 
     services.logmein-hamachi.enable = true;
diff --git a/nixos/modules/programs/hamster.nix b/nixos/modules/programs/hamster.nix
index 0bb56ad7ff36a..90cfc0f86a246 100644
--- a/nixos/modules/programs/hamster.nix
+++ b/nixos/modules/programs/hamster.nix
@@ -1,12 +1,10 @@
 { config, lib, pkgs, ... }:
 
-with lib;
-
 {
   meta.maintainers = pkgs.hamster.meta.maintainers;
 
   options.programs.hamster.enable =
-    mkEnableOption "hamster, a time tracking program";
+    lib.mkEnableOption "hamster, a time tracking program";
 
   config = lib.mkIf config.programs.hamster.enable {
     environment.systemPackages = [ pkgs.hamster ];
diff --git a/nixos/modules/programs/htop.nix b/nixos/modules/programs/htop.nix
index bf3d851081706..1252b41e8b851 100644
--- a/nixos/modules/programs/htop.nix
+++ b/nixos/modules/programs/htop.nix
@@ -1,29 +1,27 @@
 { config, lib, pkgs, ... }:
 
-with lib;
-
 let
 
   cfg = config.programs.htop;
 
   fmt = value:
-    if isList value then concatStringsSep " " (map fmt value) else
-    if isString value then value else
-    if isBool value then if value then "1" else "0" else
-    if isInt value then toString value else
-    throw "Unrecognized type ${typeOf value} in htop settings";
+    if builtins.isList value then builtins.concatStringsSep " " (builtins.map fmt value) else
+    if builtins.isString value then value else
+    if builtins.isBool value then if value then "1" else "0" else
+    if builtins.isInt value then builtins.toString value else
+    throw "Unrecognized type ${builtins.typeOf value} in htop settings";
 
 in
 
 {
 
   options.programs.htop = {
-    package = mkPackageOption pkgs "htop" { };
+    package = lib.mkPackageOption pkgs "htop" { };
 
-    enable = mkEnableOption "htop process monitor";
+    enable = lib.mkEnableOption "htop process monitor";
 
-    settings = mkOption {
-      type = with types; attrsOf (oneOf [ str int bool (listOf (oneOf [ str int bool ])) ]);
+    settings = lib.mkOption {
+      type = with lib.types; attrsOf (oneOf [ str int bool (listOf (oneOf [ str int bool ])) ]);
       default = {};
       example = {
         hide_kernel_threads = true;
@@ -38,7 +36,7 @@ in
     };
   };
 
-  config = mkIf cfg.enable {
+  config = lib.mkIf cfg.enable {
     environment.systemPackages = [
       cfg.package
     ];
@@ -46,7 +44,7 @@ in
     environment.etc."htoprc".text = ''
       # Global htop configuration
       # To change set: programs.htop.settings.KEY = VALUE;
-    '' + concatStringsSep "\n" (mapAttrsToList (key: value: "${key}=${fmt value}") cfg.settings);
+    '' + builtins.concatStringsSep "\n" (lib.mapAttrsToList (key: value: "${key}=${fmt value}") cfg.settings);
   };
 
 }
diff --git a/nixos/modules/programs/i3lock.nix b/nixos/modules/programs/i3lock.nix
index 8068ecaf08ca7..ff616144e2834 100644
--- a/nixos/modules/programs/i3lock.nix
+++ b/nixos/modules/programs/i3lock.nix
@@ -1,7 +1,5 @@
 { config, lib, pkgs, ... }:
 
-with lib;
-
 let
 
   cfg = config.programs.i3lock;
@@ -12,8 +10,8 @@ in {
 
   options = {
     programs.i3lock = {
-      enable = mkEnableOption "i3lock";
-      package = mkPackageOption pkgs "i3lock" {
+      enable = lib.mkEnableOption "i3lock";
+      package = lib.mkPackageOption pkgs "i3lock" {
         example = "i3lock-color";
         extraDescription = ''
           ::: {.note}
@@ -21,8 +19,8 @@ in {
           :::
         '';
       };
-      u2fSupport = mkOption {
-        type        = types.bool;
+      u2fSupport = lib.mkOption {
+        type        = lib.types.bool;
         default     = false;
         example     = true;
         description = ''
@@ -36,11 +34,11 @@ in {
 
   ###### implementation
 
-  config = mkIf cfg.enable {
+  config = lib.mkIf cfg.enable {
 
     environment.systemPackages = [ cfg.package ];
 
-    security.wrappers.i3lock = mkIf cfg.u2fSupport {
+    security.wrappers.i3lock = lib.mkIf cfg.u2fSupport {
       setuid = true;
       owner = "root";
       group = "root";
diff --git a/nixos/modules/programs/iftop.nix b/nixos/modules/programs/iftop.nix
index c74714a9a6d64..d6e56c8fded69 100644
--- a/nixos/modules/programs/iftop.nix
+++ b/nixos/modules/programs/iftop.nix
@@ -1,14 +1,12 @@
 { config, pkgs, lib, ... }:
 
-with lib;
-
 let
   cfg = config.programs.iftop;
 in {
   options = {
-    programs.iftop.enable = mkEnableOption "iftop + setcap wrapper";
+    programs.iftop.enable = lib.mkEnableOption "iftop + setcap wrapper";
   };
-  config = mkIf cfg.enable {
+  config = lib.mkIf cfg.enable {
     environment.systemPackages = [ pkgs.iftop ];
     security.wrappers.iftop = {
       owner = "root";
diff --git a/nixos/modules/programs/iotop.nix b/nixos/modules/programs/iotop.nix
index b7c1c69f9ddd0..ba8d028f6bb8d 100644
--- a/nixos/modules/programs/iotop.nix
+++ b/nixos/modules/programs/iotop.nix
@@ -1,14 +1,12 @@
 { config, pkgs, lib, ... }:
 
-with lib;
-
 let
   cfg = config.programs.iotop;
 in {
   options = {
-    programs.iotop.enable = mkEnableOption "iotop + setcap wrapper";
+    programs.iotop.enable = lib.mkEnableOption "iotop + setcap wrapper";
   };
-  config = mkIf cfg.enable {
+  config = lib.mkIf cfg.enable {
     security.wrappers.iotop = {
       owner = "root";
       group = "root";
diff --git a/nixos/modules/programs/java.nix b/nixos/modules/programs/java.nix
index f201f67b42e46..784add809682e 100644
--- a/nixos/modules/programs/java.nix
+++ b/nixos/modules/programs/java.nix
@@ -3,8 +3,6 @@
 
 { config, lib, pkgs, ... }:
 
-with lib;
-
 let
   cfg = config.programs.java;
 in
@@ -14,7 +12,7 @@ in
 
     programs.java = {
 
-      enable = mkEnableOption "java" // {
+      enable = lib.mkEnableOption "java" // {
         description = ''
           Install and setup the Java development kit.
 
@@ -30,19 +28,19 @@ in
         '';
       };
 
-      package = mkPackageOption pkgs "jdk" {
+      package = lib.mkPackageOption pkgs "jdk" {
         example = "jre";
       };
 
-      binfmt = mkEnableOption "binfmt to execute java jar's and classes";
+      binfmt = lib.mkEnableOption "binfmt to execute java jar's and classes";
 
     };
 
   };
 
-  config = mkIf cfg.enable {
+  config = lib.mkIf cfg.enable {
 
-    boot.binfmt.registrations = mkIf cfg.binfmt {
+    boot.binfmt.registrations = lib.mkIf cfg.binfmt {
       java-class = {
         recognitionType = "extension";
         magicOrExtension = "class";
diff --git a/nixos/modules/programs/joycond-cemuhook.nix b/nixos/modules/programs/joycond-cemuhook.nix
index ebb0198ee60c0..6cdd198a7df23 100644
--- a/nixos/modules/programs/joycond-cemuhook.nix
+++ b/nixos/modules/programs/joycond-cemuhook.nix
@@ -1,8 +1,7 @@
 { lib, pkgs, config, ... }:
-with lib;
 {
   options.programs.joycond-cemuhook = {
-    enable = mkEnableOption "joycond-cemuhook, a program to enable support for cemuhook's UDP protocol for joycond devices.";
+    enable = lib.mkEnableOption "joycond-cemuhook, a program to enable support for cemuhook's UDP protocol for joycond devices.";
   };
 
   config = lib.mkIf config.programs.joycond-cemuhook.enable {
diff --git a/nixos/modules/programs/k3b.nix b/nixos/modules/programs/k3b.nix
index 4d6385dab4f07..3e9435d3dc601 100644
--- a/nixos/modules/programs/k3b.nix
+++ b/nixos/modules/programs/k3b.nix
@@ -1,12 +1,10 @@
 { config, pkgs, lib, ... }:
 
-with lib;
-
 {
   # interface
   options.programs.k3b = {
-    enable = mkOption {
-      type = types.bool;
+    enable = lib.mkOption {
+      type = lib.types.bool;
       default = false;
       description = ''
         Whether to enable k3b, the KDE disk burning application.
@@ -22,7 +20,7 @@ with lib;
   };
 
   # implementation
-  config = mkIf config.programs.k3b.enable {
+  config = lib.mkIf config.programs.k3b.enable {
 
     environment.systemPackages = with pkgs; [
       k3b
diff --git a/nixos/modules/programs/k40-whisperer.nix b/nixos/modules/programs/k40-whisperer.nix
index 156ded6c39fe8..0f29c476cbb79 100644
--- a/nixos/modules/programs/k40-whisperer.nix
+++ b/nixos/modules/programs/k40-whisperer.nix
@@ -1,7 +1,5 @@
 { config, lib, pkgs, ... }:
 
-with lib;
-
 let
   cfg = config.programs.k40-whisperer;
   pkg = cfg.package.override {
@@ -10,20 +8,20 @@ let
 in
 {
   options.programs.k40-whisperer = {
-    enable = mkEnableOption "K40-Whisperer";
+    enable = lib.mkEnableOption "K40-Whisperer";
 
-    group = mkOption {
-      type = types.str;
+    group = lib.mkOption {
+      type = lib.types.str;
       description = ''
         Group assigned to the device when connected.
       '';
       default = "k40";
     };
 
-    package = mkPackageOption pkgs "k40-whisperer" { };
+    package = lib.mkPackageOption pkgs "k40-whisperer" { };
   };
 
-  config = mkIf cfg.enable {
+  config = lib.mkIf cfg.enable {
     users.groups.${cfg.group} = {};
 
     environment.systemPackages = [ pkg ];
diff --git a/nixos/modules/programs/kbdlight.nix b/nixos/modules/programs/kbdlight.nix
index 8a2a0057cf2da..934bb214c1166 100644
--- a/nixos/modules/programs/kbdlight.nix
+++ b/nixos/modules/programs/kbdlight.nix
@@ -1,15 +1,13 @@
 { config, lib, pkgs, ... }:
 
-with lib;
-
 let
   cfg = config.programs.kbdlight;
 
 in
 {
-  options.programs.kbdlight.enable = mkEnableOption "kbdlight";
+  options.programs.kbdlight.enable = lib.mkEnableOption "kbdlight";
 
-  config = mkIf cfg.enable {
+  config = lib.mkIf cfg.enable {
     environment.systemPackages = [ pkgs.kbdlight ];
     security.wrappers.kbdlight =
       { setuid = true;
diff --git a/nixos/modules/programs/kclock.nix b/nixos/modules/programs/kclock.nix
index c2299a3f1b034..b69f358ec1ff9 100644
--- a/nixos/modules/programs/kclock.nix
+++ b/nixos/modules/programs/kclock.nix
@@ -1,12 +1,11 @@
 { lib, pkgs, config, ... }:
-with lib;
 let
   cfg = config.programs.kclock;
   kclockPkg = pkgs.libsForQt5.kclock;
 in {
-  options.programs.kclock = { enable = mkEnableOption "KClock"; };
+  options.programs.kclock = { enable = lib.mkEnableOption "KClock"; };
 
-  config = mkIf cfg.enable {
+  config = lib.mkIf cfg.enable {
     services.dbus.packages = [ kclockPkg ];
     environment.systemPackages = [ kclockPkg ];
   };
diff --git a/nixos/modules/programs/kdeconnect.nix b/nixos/modules/programs/kdeconnect.nix
index 1431281405968..76bba40103084 100644
--- a/nixos/modules/programs/kdeconnect.nix
+++ b/nixos/modules/programs/kdeconnect.nix
@@ -1,8 +1,7 @@
 { config, pkgs, lib, ... }:
-with lib;
 {
   options.programs.kdeconnect = {
-    enable = mkEnableOption ''
+    enable = lib.mkEnableOption ''
       kdeconnect.
 
       Note that it will open the TCP and UDP port from
@@ -11,7 +10,7 @@ with lib;
       `gnomeExtensions.gsconnect` as an alternative
       implementation if you use Gnome
     '';
-    package = mkPackageOption pkgs [ "plasma5Packages" "kdeconnect-kde" ] {
+    package = lib.mkPackageOption pkgs [ "plasma5Packages" "kdeconnect-kde" ] {
       example = "gnomeExtensions.gsconnect";
     };
   };
@@ -19,10 +18,9 @@ with lib;
     let
       cfg = config.programs.kdeconnect;
     in
-      mkIf cfg.enable {
+      lib.mkIf cfg.enable {
         environment.systemPackages = [
           cfg.package
-          pkgs.sshfs
         ];
         networking.firewall = rec {
           allowedTCPPortRanges = [ { from = 1714; to = 1764; } ];
diff --git a/nixos/modules/programs/less.nix b/nixos/modules/programs/less.nix
index 2cb7620075118..c904fc2089aa3 100644
--- a/nixos/modules/programs/less.nix
+++ b/nixos/modules/programs/less.nix
@@ -1,26 +1,24 @@
 { config, lib, pkgs, ... }:
 
-with lib;
-
 let
 
   cfg = config.programs.less;
 
   configText = if (cfg.configFile != null) then (builtins.readFile cfg.configFile) else ''
     #command
-    ${concatStringsSep "\n"
-      (mapAttrsToList (command: action: "${command} ${action}") cfg.commands)
+    ${builtins.concatStringsSep "\n"
+      (lib.mapAttrsToList (command: action: "${command} ${action}") cfg.commands)
     }
-    ${optionalString cfg.clearDefaultCommands "#stop"}
+    ${lib.optionalString cfg.clearDefaultCommands "#stop"}
 
     #line-edit
-    ${concatStringsSep "\n"
-      (mapAttrsToList (command: action: "${command} ${action}") cfg.lineEditingKeys)
+    ${builtins.concatStringsSep "\n"
+      (lib.mapAttrsToList (command: action: "${command} ${action}") cfg.lineEditingKeys)
     }
 
     #env
-    ${concatStringsSep "\n"
-      (mapAttrsToList (variable: values: "${variable}=${values}") cfg.envVariables)
+    ${builtins.concatStringsSep "\n"
+      (lib.mapAttrsToList (variable: values: "${variable}=${values}") cfg.envVariables)
     }
   '';
 
@@ -35,12 +33,12 @@ in
 
       # note that environment.nix sets PAGER=less, and
       # therefore also enables this module
-      enable = mkEnableOption "less, a file pager";
+      enable = lib.mkEnableOption "less, a file pager";
 
-      configFile = mkOption {
-        type = types.nullOr types.path;
+      configFile = lib.mkOption {
+        type = lib.types.nullOr lib.types.path;
         default = null;
-        example = literalExpression ''"''${pkgs.my-configs}/lesskey"'';
+        example = lib.literalExpression ''"''${pkgs.my-configs}/lesskey"'';
         description = ''
           Path to lesskey configuration file.
 
@@ -50,8 +48,8 @@ in
         '';
       };
 
-      commands = mkOption {
-        type = types.attrsOf types.str;
+      commands = lib.mkOption {
+        type = lib.types.attrsOf lib.types.str;
         default = {};
         example = {
           h = "noaction 5\\e(";
@@ -60,8 +58,8 @@ in
         description = "Defines new command keys.";
       };
 
-      clearDefaultCommands = mkOption {
-        type = types.bool;
+      clearDefaultCommands = lib.mkOption {
+        type = lib.types.bool;
         default = false;
         description = ''
           Clear all default commands.
@@ -70,8 +68,8 @@ in
         '';
       };
 
-      lineEditingKeys = mkOption {
-        type = types.attrsOf types.str;
+      lineEditingKeys = lib.mkOption {
+        type = lib.types.attrsOf lib.types.str;
         default = {};
         example = {
           e = "abort";
@@ -79,8 +77,8 @@ in
         description = "Defines new line-editing keys.";
       };
 
-      envVariables = mkOption {
-        type = types.attrsOf types.str;
+      envVariables = lib.mkOption {
+        type = lib.types.attrsOf lib.types.str;
         default = {
           LESS = "-R";
         };
@@ -90,17 +88,17 @@ in
         description = "Defines environment variables.";
       };
 
-      lessopen = mkOption {
-        type = types.nullOr types.str;
+      lessopen = lib.mkOption {
+        type = lib.types.nullOr lib.types.str;
         default = "|${pkgs.lesspipe}/bin/lesspipe.sh %s";
-        defaultText = literalExpression ''"|''${pkgs.lesspipe}/bin/lesspipe.sh %s"'';
+        defaultText = lib.literalExpression ''"|''${pkgs.lesspipe}/bin/lesspipe.sh %s"'';
         description = ''
           Before less opens a file, it first gives your input preprocessor a chance to modify the way the contents of the file are displayed.
         '';
       };
 
-      lessclose = mkOption {
-        type = types.nullOr types.str;
+      lessclose = lib.mkOption {
+        type = lib.types.nullOr lib.types.str;
         default = null;
         description = ''
           When less closes a file opened in such a way, it will call another program, called the input postprocessor,
@@ -110,26 +108,26 @@ in
     };
   };
 
-  config = mkIf cfg.enable {
+  config = lib.mkIf cfg.enable {
 
     environment.systemPackages = [ pkgs.less ];
 
     environment.variables = {
-      LESSKEYIN_SYSTEM = toString lessKey;
-    } // optionalAttrs (cfg.lessopen != null) {
+      LESSKEYIN_SYSTEM = builtins.toString lessKey;
+    } // lib.optionalAttrs (cfg.lessopen != null) {
       LESSOPEN = cfg.lessopen;
-    } // optionalAttrs (cfg.lessclose != null) {
+    } // lib.optionalAttrs (cfg.lessclose != null) {
       LESSCLOSE = cfg.lessclose;
     };
 
-    warnings = optional (
-      cfg.clearDefaultCommands && (all (x: x != "quit") (attrValues cfg.commands))
+    warnings = lib.optional (
+      cfg.clearDefaultCommands && (builtins.all (x: x != "quit") (builtins.attrValues cfg.commands))
     ) ''
       config.programs.less.clearDefaultCommands clears all default commands of less but there is no alternative binding for exiting.
       Consider adding a binding for 'quit'.
     '';
   };
 
-  meta.maintainers = with maintainers; [ johnazoidberg ];
+  meta.maintainers = with lib.maintainers; [ johnazoidberg ];
 
 }
diff --git a/nixos/modules/programs/liboping.nix b/nixos/modules/programs/liboping.nix
index 4433f9767d6ee..5ff9ad74b1584 100644
--- a/nixos/modules/programs/liboping.nix
+++ b/nixos/modules/programs/liboping.nix
@@ -1,16 +1,14 @@
 { config, lib, pkgs, ... }:
 
-with lib;
-
 let
   cfg = config.programs.liboping;
 in {
   options.programs.liboping = {
-    enable = mkEnableOption "liboping";
+    enable = lib.mkEnableOption "liboping";
   };
-  config = mkIf cfg.enable {
+  config = lib.mkIf cfg.enable {
     environment.systemPackages = with pkgs; [ liboping ];
-    security.wrappers = mkMerge (map (
+    security.wrappers = lib.mkMerge (builtins.map (
       exec: {
         "${exec}" = {
           owner = "root";
diff --git a/nixos/modules/programs/light.nix b/nixos/modules/programs/light.nix
index b1584a1b3d28c..29fcc98a8e0ad 100644
--- a/nixos/modules/programs/light.nix
+++ b/nixos/modules/programs/light.nix
@@ -1,7 +1,5 @@
 { config, lib, pkgs, ... }:
 
-with lib;
-
 let
   cfg = config.programs.light;
 
@@ -10,9 +8,9 @@ in
   options = {
     programs.light = {
 
-      enable = mkOption {
+      enable = lib.mkOption {
         default = false;
-        type = types.bool;
+        type = lib.types.bool;
         description = ''
           Whether to install Light backlight control command
           and udev rules granting access to members of the "video" group.
@@ -20,8 +18,8 @@ in
       };
 
       brightnessKeys = {
-        enable = mkOption {
-          type = types.bool;
+        enable = lib.mkOption {
+          type = lib.types.bool;
           default = false;
           description = ''
             Whether to enable brightness control with keyboard keys.
@@ -38,8 +36,8 @@ in
           '';
         };
 
-        step = mkOption {
-          type = types.int;
+        step = lib.mkOption {
+          type = lib.types.int;
           default = 10;
           description = ''
             The percentage value by which to increase/decrease brightness.
@@ -51,14 +49,14 @@ in
     };
   };
 
-  config = mkIf cfg.enable {
+  config = lib.mkIf cfg.enable {
     environment.systemPackages = [ pkgs.light ];
     services.udev.packages = [ pkgs.light ];
-    services.actkbd = mkIf cfg.brightnessKeys.enable {
+    services.actkbd = lib.mkIf cfg.brightnessKeys.enable {
       enable = true;
       bindings = let
         light = "${pkgs.light}/bin/light";
-        step = toString cfg.brightnessKeys.step;
+        step = builtins.toString cfg.brightnessKeys.step;
       in [
         {
           keys = [ 224 ];
diff --git a/nixos/modules/programs/mdevctl.nix b/nixos/modules/programs/mdevctl.nix
index be33835639d2e..a7e7d01dffdfc 100644
--- a/nixos/modules/programs/mdevctl.nix
+++ b/nixos/modules/programs/mdevctl.nix
@@ -1,14 +1,13 @@
 { config, pkgs, lib, ... }:
 
-with lib;
 let
   cfg = config.programs.mdevctl;
 in {
   options.programs.mdevctl = {
-    enable = mkEnableOption "Mediated Device Management";
+    enable = lib.mkEnableOption "Mediated Device Management";
   };
 
-  config = mkIf cfg.enable {
+  config = lib.mkIf cfg.enable {
     environment.systemPackages = with pkgs; [ mdevctl ];
 
     environment.etc."mdevctl.d/scripts.d/notifiers/.keep".text = "";
diff --git a/nixos/modules/programs/mepo.nix b/nixos/modules/programs/mepo.nix
index 22596892ff5dc..783d2ad149626 100644
--- a/nixos/modules/programs/mepo.nix
+++ b/nixos/modules/programs/mepo.nix
@@ -1,15 +1,14 @@
 { pkgs, config, lib, ...}:
-with lib;
 let
   cfg = config.programs.mepo;
 in
 {
   options.programs.mepo = {
-    enable = mkEnableOption "Mepo, a fast, simple and hackable OSM map viewer";
+    enable = lib.mkEnableOption "Mepo, a fast, simple and hackable OSM map viewer";
 
     locationBackends = {
-      gpsd = mkOption {
-        type = types.bool;
+      gpsd = lib.mkOption {
+        type = lib.types.bool;
         default = false;
         description = ''
           Whether to enable location detection via gpsd.
@@ -17,21 +16,21 @@ in
         '';
       };
 
-      geoclue = mkOption {
-        type = types.bool;
+      geoclue = lib.mkOption {
+        type = lib.types.bool;
         default = true;
         description = "Whether to enable location detection via geoclue";
       };
     };
   };
 
-  config = mkIf cfg.enable {
+  config = lib.mkIf cfg.enable {
     environment.systemPackages = with pkgs; [
       mepo
     ] ++ lib.optional cfg.locationBackends.geoclue geoclue2-with-demo-agent
     ++ lib.optional cfg.locationBackends.gpsd gpsd;
 
-    services.geoclue2 = mkIf cfg.locationBackends.geoclue {
+    services.geoclue2 = lib.mkIf cfg.locationBackends.geoclue {
       enable = true;
       appConfig.where-am-i = {
         isAllowed = true;
@@ -42,5 +41,5 @@ in
     services.gpsd.enable = cfg.locationBackends.gpsd;
   };
 
-  meta.maintainers = with maintainers; [ laalsaas ];
+  meta.maintainers = with lib.maintainers; [ laalsaas ];
 }
diff --git a/nixos/modules/programs/mininet.nix b/nixos/modules/programs/mininet.nix
index a9190ed989007..ab862b21fe021 100644
--- a/nixos/modules/programs/mininet.nix
+++ b/nixos/modules/programs/mininet.nix
@@ -2,15 +2,13 @@
 # kernel must have NETNS/VETH/SCHED
 { config, lib, pkgs, ... }:
 
-with lib;
-
 let
   cfg = config.programs.mininet;
 in
 {
-  options.programs.mininet.enable = mkEnableOption "Mininet, an emulator for rapid prototyping of Software Defined Networks";
+  options.programs.mininet.enable = lib.mkEnableOption "Mininet, an emulator for rapid prototyping of Software Defined Networks";
 
-  config = mkIf cfg.enable {
+  config = lib.mkIf cfg.enable {
 
     virtualisation.vswitch.enable = true;
 
diff --git a/nixos/modules/programs/msmtp.nix b/nixos/modules/programs/msmtp.nix
index 9c067bdc96957..8a04acb3b7ea6 100644
--- a/nixos/modules/programs/msmtp.nix
+++ b/nixos/modules/programs/msmtp.nix
@@ -1,27 +1,25 @@
 { config, lib, pkgs, ... }:
 
-with lib;
-
 let
   cfg = config.programs.msmtp;
 
 in {
-  meta.maintainers = with maintainers; [ pacien ];
+  meta.maintainers = with lib.maintainers; [ pacien ];
 
   options = {
     programs.msmtp = {
-      enable = mkEnableOption "msmtp - an SMTP client";
+      enable = lib.mkEnableOption "msmtp - an SMTP client";
 
-      setSendmail = mkOption {
-        type = types.bool;
+      setSendmail = lib.mkOption {
+        type = lib.types.bool;
         default = true;
         description = ''
           Whether to set the system sendmail to msmtp's.
         '';
       };
 
-      defaults = mkOption {
-        type = types.attrs;
+      defaults = lib.mkOption {
+        type = lib.types.attrs;
         default = {};
         example = {
           aliases = "/etc/aliases";
@@ -34,8 +32,8 @@ in {
         '';
       };
 
-      accounts = mkOption {
-        type = with types; attrsOf attrs;
+      accounts = lib.mkOption {
+        type = with lib.types; attrsOf attrs;
         default = {};
         example = {
           "default" = {
@@ -59,8 +57,8 @@ in {
         '';
       };
 
-      extraConfig = mkOption {
-        type = types.lines;
+      extraConfig = lib.mkOption {
+        type = lib.types.lines;
         default = "";
         description = ''
           Extra lines to add to the msmtp configuration verbatim.
@@ -70,10 +68,10 @@ in {
     };
   };
 
-  config = mkIf cfg.enable {
+  config = lib.mkIf cfg.enable {
     environment.systemPackages = [ pkgs.msmtp ];
 
-    services.mail.sendmailSetuidWrapper = mkIf cfg.setSendmail {
+    services.mail.sendmailSetuidWrapper = lib.mkIf cfg.setSendmail {
       program = "sendmail";
       source = "${pkgs.msmtp}/bin/sendmail";
       setuid = false;
@@ -86,10 +84,10 @@ in {
       mkValueString = v:
         if v == true then "on"
         else if v == false then "off"
-        else generators.mkValueStringDefault {} v;
+        else lib.generators.mkValueStringDefault {} v;
       mkKeyValueString = k: v: "${k} ${mkValueString v}";
       mkInnerSectionString =
-        attrs: concatStringsSep "\n" (mapAttrsToList mkKeyValueString attrs);
+        attrs: builtins.concatStringsSep "\n" (lib.mapAttrsToList mkKeyValueString attrs);
       mkAccountString = name: attrs: ''
         account ${name}
         ${mkInnerSectionString attrs}
@@ -98,7 +96,7 @@ in {
       defaults
       ${mkInnerSectionString cfg.defaults}
 
-      ${concatStringsSep "\n" (mapAttrsToList mkAccountString cfg.accounts)}
+      ${builtins.concatStringsSep "\n" (lib.mapAttrsToList mkAccountString cfg.accounts)}
 
       ${cfg.extraConfig}
     '';
diff --git a/nixos/modules/programs/mtr.nix b/nixos/modules/programs/mtr.nix
index 6a767df15f098..1a9deba989663 100644
--- a/nixos/modules/programs/mtr.nix
+++ b/nixos/modules/programs/mtr.nix
@@ -1,15 +1,13 @@
 { config, lib, pkgs, ... }:
 
-with lib;
-
 let
   cfg = config.programs.mtr;
 
 in {
   options = {
     programs.mtr = {
-      enable = mkOption {
-        type = types.bool;
+      enable = lib.mkOption {
+        type = lib.types.bool;
         default = false;
         description = ''
           Whether to add mtr to the global environment and configure a
@@ -17,12 +15,12 @@ in {
         '';
       };
 
-      package = mkPackageOption pkgs "mtr" { };
+      package = lib.mkPackageOption pkgs "mtr" { };
     };
   };
 
-  config = mkIf cfg.enable {
-    environment.systemPackages = with pkgs; [ cfg.package ];
+  config = lib.mkIf cfg.enable {
+    environment.systemPackages = [ cfg.package ];
 
     security.wrappers.mtr-packet = {
       owner = "root";
diff --git a/nixos/modules/programs/nbd.nix b/nixos/modules/programs/nbd.nix
index fea9bc1ff71a1..1e319f0273455 100644
--- a/nixos/modules/programs/nbd.nix
+++ b/nixos/modules/programs/nbd.nix
@@ -1,18 +1,16 @@
 { config, lib, pkgs, ... }:
 
-with lib;
-
 let
   cfg = config.programs.nbd;
 in
 {
   options = {
     programs.nbd = {
-      enable = mkEnableOption "Network Block Device (nbd) support";
+      enable = lib.mkEnableOption "Network Block Device (nbd) support";
     };
   };
 
-  config = mkIf cfg.enable {
+  config = lib.mkIf cfg.enable {
     environment.systemPackages = with pkgs; [ nbd ];
     boot.kernelModules = [ "nbd" ];
   };
diff --git a/nixos/modules/programs/neovim.nix b/nixos/modules/programs/neovim.nix
index 6f6829444a641..8fe6a664b675a 100644
--- a/nixos/modules/programs/neovim.nix
+++ b/nixos/modules/programs/neovim.nix
@@ -1,14 +1,12 @@
 { config, lib, pkgs, ... }:
 
-with lib;
-
 let
   cfg = config.programs.neovim;
 in
 {
   options.programs.neovim = {
-    enable = mkOption {
-      type = types.bool;
+    enable = lib.mkOption {
+      type = lib.types.bool;
       default = false;
       example = true;
       description = ''
@@ -21,8 +19,8 @@ in
       '';
     };
 
-    defaultEditor = mkOption {
-      type = types.bool;
+    defaultEditor = lib.mkOption {
+      type = lib.types.bool;
       default = false;
       description = ''
         When enabled, installs neovim and configures neovim to be the default editor
@@ -30,44 +28,44 @@ in
       '';
     };
 
-    viAlias = mkOption {
-      type = types.bool;
+    viAlias = lib.mkOption {
+      type = lib.types.bool;
       default = false;
       description = ''
         Symlink {command}`vi` to {command}`nvim` binary.
       '';
     };
 
-    vimAlias = mkOption {
-      type = types.bool;
+    vimAlias = lib.mkOption {
+      type = lib.types.bool;
       default = false;
       description = ''
         Symlink {command}`vim` to {command}`nvim` binary.
       '';
     };
 
-    withRuby = mkOption {
-      type = types.bool;
+    withRuby = lib.mkOption {
+      type = lib.types.bool;
       default = true;
       description = "Enable Ruby provider.";
     };
 
-    withPython3 = mkOption {
-      type = types.bool;
+    withPython3 = lib.mkOption {
+      type = lib.types.bool;
       default = true;
       description = "Enable Python 3 provider.";
     };
 
-    withNodeJs = mkOption {
-      type = types.bool;
+    withNodeJs = lib.mkOption {
+      type = lib.types.bool;
       default = false;
       description = "Enable Node provider.";
     };
 
-    configure = mkOption {
-      type = types.attrs;
+    configure = lib.mkOption {
+      type = lib.types.attrs;
       default = { };
-      example = literalExpression ''
+      example = lib.literalExpression ''
         {
           customRC = '''
             " here your custom configuration goes!
@@ -86,31 +84,31 @@ in
       '';
     };
 
-    package = mkPackageOption pkgs "neovim-unwrapped" { };
+    package = lib.mkPackageOption pkgs "neovim-unwrapped" { };
 
-    finalPackage = mkOption {
-      type = types.package;
+    finalPackage = lib.mkOption {
+      type = lib.types.package;
       visible = false;
       readOnly = true;
       description = "Resulting customized neovim package.";
     };
 
-    runtime = mkOption {
+    runtime = lib.mkOption {
       default = { };
-      example = literalExpression ''
+      example = lib.literalExpression ''
         { "ftplugin/c.vim".text = "setlocal omnifunc=v:lua.vim.lsp.omnifunc"; }
       '';
       description = ''
         Set of files that have to be linked in {file}`runtime`.
       '';
 
-      type = with types; attrsOf (submodule (
+      type = with lib.types; attrsOf (submodule (
         { name, config, ... }:
         {
           options = {
 
-            enable = mkOption {
-              type = types.bool;
+            enable = lib.mkOption {
+              type = lib.types.bool;
               default = true;
               description = ''
                 Whether this runtime directory should be generated.  This
@@ -118,49 +116,49 @@ in
               '';
             };
 
-            target = mkOption {
-              type = types.str;
+            target = lib.mkOption {
+              type = lib.types.str;
               description = ''
                 Name of symlink.  Defaults to the attribute
                 name.
               '';
             };
 
-            text = mkOption {
+            text = lib.mkOption {
               default = null;
-              type = types.nullOr types.lines;
+              type = lib.types.nullOr lib.types.lines;
               description = "Text of the file.";
             };
 
-            source = mkOption {
+            source = lib.mkOption {
               default = null;
-              type = types.nullOr types.path;
+              type = lib.types.nullOr lib.types.path;
               description = "Path of the source file.";
             };
 
           };
 
-          config.target = mkDefault name;
+          config.target = lib.mkDefault name;
         }
       ));
 
     };
   };
 
-  config = mkIf cfg.enable {
+  config = lib.mkIf cfg.enable {
     environment.systemPackages = [
       cfg.finalPackage
     ];
-    environment.variables.EDITOR = mkIf cfg.defaultEditor (mkOverride 900 "nvim");
+    environment.variables.EDITOR = lib.mkIf cfg.defaultEditor (lib.mkOverride 900 "nvim");
 
-    environment.etc = listToAttrs (attrValues (mapAttrs
+    environment.etc = builtins.listToAttrs (builtins.attrValues (builtins.mapAttrs
       (name: value: {
         name = "xdg/nvim/${name}";
-        value = removeAttrs
+        value = builtins.removeAttrs
           (value // {
             target = "xdg/nvim/${value.target}";
           })
-          (optionals (isNull value.source) [ "source" ]);
+          (lib.optionals (builtins.isNull value.source) [ "source" ]);
       })
       cfg.runtime));
 
diff --git a/nixos/modules/programs/nethoscope.nix b/nixos/modules/programs/nethoscope.nix
index 495548e9c6561..7bc1f61b31eae 100644
--- a/nixos/modules/programs/nethoscope.nix
+++ b/nixos/modules/programs/nethoscope.nix
@@ -1,16 +1,14 @@
 { config, lib, pkgs, ... }:
 
-with lib;
-
 let cfg = config.programs.nethoscope;
 in
 {
-  meta.maintainers = with maintainers; [ _0x4A6F ];
+  meta.maintainers = with lib.maintainers; [ _0x4A6F ];
 
   options = {
     programs.nethoscope = {
-      enable = mkOption {
-        type = types.bool;
+      enable = lib.mkOption {
+        type = lib.types.bool;
         default = false;
         description = ''
           Whether to add nethoscope to the global environment and configure a
@@ -20,7 +18,7 @@ in
     };
   };
 
-  config = mkIf cfg.enable {
+  config = lib.mkIf cfg.enable {
     environment.systemPackages = with pkgs; [ nethoscope ];
     security.wrappers.nethoscope = {
       source = "${pkgs.nethoscope}/bin/nethoscope";
diff --git a/nixos/modules/programs/nncp.nix b/nixos/modules/programs/nncp.nix
index aa2e7c7a6e5b5..3feccef4cf11e 100644
--- a/nixos/modules/programs/nncp.nix
+++ b/nixos/modules/programs/nncp.nix
@@ -1,6 +1,5 @@
 { config, lib, pkgs, ... }:
 
-with lib;
 let
   nncpCfgFile = "/run/nncp.hjson";
   programCfg = config.programs.nncp;
@@ -11,10 +10,10 @@ in {
   options.programs.nncp = {
 
     enable =
-      mkEnableOption "NNCP (Node to Node copy) utilities and configuration";
+      lib.mkEnableOption "NNCP (Node to Node copy) utilities and configuration";
 
-    group = mkOption {
-      type = types.str;
+    group = lib.mkOption {
+      type = lib.types.str;
       default = "uucp";
       description = ''
         The group under which NNCP files shall be owned.
@@ -23,10 +22,10 @@ in {
       '';
     };
 
-    package = mkPackageOption pkgs "nncp" { };
+    package = lib.mkPackageOption pkgs "nncp" { };
 
-    secrets = mkOption {
-      type = with types; listOf str;
+    secrets = lib.mkOption {
+      type = with lib.types; listOf str;
       example = [ "/run/keys/nncp.hjson" ];
       description = ''
         A list of paths to NNCP configuration files that should not be
@@ -35,7 +34,7 @@ in {
       '';
     };
 
-    settings = mkOption {
+    settings = lib.mkOption {
       type = settingsFormat.type;
       description = ''
         NNCP configuration, see
@@ -52,7 +51,7 @@ in {
 
   };
 
-  config = mkIf programCfg.enable {
+  config = lib.mkIf programCfg.enable {
 
     environment = {
       systemPackages = [ pkg ];
@@ -60,8 +59,8 @@ in {
     };
 
     programs.nncp.settings = {
-      spool = mkDefault "/var/spool/nncp";
-      log = mkDefault "/var/spool/nncp/log";
+      spool = lib.mkDefault "/var/spool/nncp";
+      log = lib.mkDefault "/var/spool/nncp/log";
     };
 
     systemd.tmpfiles.rules = [
@@ -77,7 +76,7 @@ in {
       script = ''
         umask u=rw
         nncpCfgDir=$(mktemp --directory nncp.XXX)
-        for f in ${jsonCfgFile} ${toString config.programs.nncp.secrets}; do
+        for f in ${jsonCfgFile} ${builtins.toString config.programs.nncp.secrets}; do
           tmpdir=$(mktemp --directory nncp.XXX)
           nncp-cfgdir -cfg $f -dump $tmpdir
           find $tmpdir -size 1c -delete
diff --git a/nixos/modules/programs/noisetorch.nix b/nixos/modules/programs/noisetorch.nix
index 70a0441bd7677..5e37061d9a1d4 100644
--- a/nixos/modules/programs/noisetorch.nix
+++ b/nixos/modules/programs/noisetorch.nix
@@ -1,17 +1,15 @@
 { config, pkgs, lib, ... }:
 
-with lib;
-
 let cfg = config.programs.noisetorch;
 in
 {
   options.programs.noisetorch = {
-    enable = mkEnableOption "noisetorch (+ setcap wrapper), a virtual microphone device with noise suppression";
+    enable = lib.mkEnableOption "noisetorch (+ setcap wrapper), a virtual microphone device with noise suppression";
 
-    package = mkPackageOption pkgs "noisetorch" { };
+    package = lib.mkPackageOption pkgs "noisetorch" { };
   };
 
-  config = mkIf cfg.enable {
+  config = lib.mkIf cfg.enable {
     security.wrappers.noisetorch = {
       owner = "root";
       group = "root";
diff --git a/nixos/modules/programs/npm.nix b/nixos/modules/programs/npm.nix
index b379f0165bfed..470188b879b6a 100644
--- a/nixos/modules/programs/npm.nix
+++ b/nixos/modules/programs/npm.nix
@@ -1,7 +1,5 @@
 { config, lib, pkgs, ... }:
 
-with lib;
-
 let
   cfg = config.programs.npm;
 in
@@ -11,13 +9,13 @@ in
 
   options = {
     programs.npm = {
-      enable = mkEnableOption "{command}`npm` global config";
+      enable = lib.mkEnableOption "{command}`npm` global config";
 
-      package = mkPackageOption pkgs [ "nodePackages" "npm" ] {
+      package = lib.mkPackageOption pkgs [ "nodePackages" "npm" ] {
         example = "nodePackages_13_x.npm";
       };
 
-      npmrc = mkOption {
+      npmrc = lib.mkOption {
         type = lib.types.lines;
         description = ''
           The system-wide npm configuration.
diff --git a/nixos/modules/programs/oblogout.nix b/nixos/modules/programs/oblogout.nix
index a039b0623b52c..f09fbdc062423 100644
--- a/nixos/modules/programs/oblogout.nix
+++ b/nixos/modules/programs/oblogout.nix
@@ -1,11 +1,9 @@
 { config, lib, pkgs, ... }:
 
-with lib;
-
 {
 
   imports = [
-    (mkRemovedOptionModule [ "programs" "oblogout" ] "programs.oblogout has been removed from NixOS. This is because the oblogout repository has been archived upstream.")
+    (lib.mkRemovedOptionModule [ "programs" "oblogout" ] "programs.oblogout has been removed from NixOS. This is because the oblogout repository has been archived upstream.")
   ];
 
 }
diff --git a/nixos/modules/programs/openvpn3.nix b/nixos/modules/programs/openvpn3.nix
index 6415cccecb4ff..10042b44471ff 100644
--- a/nixos/modules/programs/openvpn3.nix
+++ b/nixos/modules/programs/openvpn3.nix
@@ -1,19 +1,17 @@
 { config, lib, pkgs, ... }:
 
-with lib;
-
 let
   cfg = config.programs.openvpn3;
 in
 {
   options.programs.openvpn3 = {
-    enable = mkEnableOption "the openvpn3 client";
-    package = mkOption {
-      type = types.package;
+    enable = lib.mkEnableOption "the openvpn3 client";
+    package = lib.mkOption {
+      type = lib.types.package;
       default = pkgs.openvpn3.override {
         enableSystemdResolved = config.services.resolved.enable;
       };
-      defaultText = literalExpression ''pkgs.openvpn3.override {
+      defaultText = lib.literalExpression ''pkgs.openvpn3.override {
         enableSystemdResolved = config.services.resolved.enable;
       }'';
       description = ''
@@ -22,7 +20,7 @@ in
     };
   };
 
-  config = mkIf cfg.enable {
+  config = lib.mkIf cfg.enable {
     services.dbus.packages = [
       cfg.package
     ];
diff --git a/nixos/modules/programs/pantheon-tweaks.nix b/nixos/modules/programs/pantheon-tweaks.nix
deleted file mode 100644
index 0b8a19ea22c01..0000000000000
--- a/nixos/modules/programs/pantheon-tweaks.nix
+++ /dev/null
@@ -1,19 +0,0 @@
-{ config, lib, pkgs, ... }:
-
-with lib;
-
-{
-  meta = {
-    maintainers = teams.pantheon.members;
-  };
-
-  ###### interface
-  options = {
-    programs.pantheon-tweaks.enable = mkEnableOption "Pantheon Tweaks, an unofficial system settings panel for Pantheon";
-  };
-
-  ###### implementation
-  config = mkIf config.programs.pantheon-tweaks.enable {
-    services.xserver.desktopManager.pantheon.extraSwitchboardPlugs = [ pkgs.pantheon-tweaks ];
-  };
-}
diff --git a/nixos/modules/programs/plotinus.nix b/nixos/modules/programs/plotinus.nix
index 41c75b69a2d2f..835db049d8628 100644
--- a/nixos/modules/programs/plotinus.nix
+++ b/nixos/modules/programs/plotinus.nix
@@ -1,7 +1,5 @@
 { config, lib, pkgs, ... }:
 
-with lib;
-
 let
   cfg = config.programs.plotinus;
 in
@@ -15,21 +13,21 @@ in
 
   options = {
     programs.plotinus = {
-      enable = mkOption {
+      enable = lib.mkOption {
         default = false;
         description = ''
           Whether to enable the Plotinus GTK 3 plugin. Plotinus provides a
           popup (triggered by Ctrl-Shift-P) to search the menus of a
           compatible application.
         '';
-        type = types.bool;
+        type = lib.types.bool;
       };
     };
   };
 
   ###### implementation
 
-  config = mkIf cfg.enable {
+  config = lib.mkIf cfg.enable {
     environment.sessionVariables.XDG_DATA_DIRS = [ "${pkgs.plotinus}/share/gsettings-schemas/${pkgs.plotinus.name}" ];
     environment.variables.GTK3_MODULES = [ "${pkgs.plotinus}/lib/libplotinus.so" ];
   };
diff --git a/nixos/modules/programs/pqos-wrapper.nix b/nixos/modules/programs/pqos-wrapper.nix
new file mode 100644
index 0000000000000..82023e67a2ae2
--- /dev/null
+++ b/nixos/modules/programs/pqos-wrapper.nix
@@ -0,0 +1,27 @@
+{ config
+, lib
+, pkgs
+, ...
+}:
+let
+  cfg = config.programs.pqos-wrapper;
+in
+{
+  options.programs.pqos-wrapper = {
+    enable = lib.mkEnableOption "PQoS Wrapper for BenchExec";
+    package = lib.mkPackageOption pkgs "pqos-wrapper" { };
+  };
+
+  config = lib.mkIf cfg.enable {
+    hardware.cpu.x86.msr.enable = true;
+
+    security.wrappers.${cfg.package.meta.mainProgram} = {
+      owner = "nobody";
+      group = config.hardware.cpu.x86.msr.group;
+      source = lib.getExe cfg.package;
+      capabilities = "cap_sys_rawio=eip";
+    };
+  };
+
+  meta.maintainers = with lib.maintainers; [ lorenzleutgeb ];
+}
diff --git a/nixos/modules/programs/proxychains.nix b/nixos/modules/programs/proxychains.nix
index b15475dac075b..86bbf16a64ce1 100644
--- a/nixos/modules/programs/proxychains.nix
+++ b/nixos/modules/programs/proxychains.nix
@@ -1,15 +1,14 @@
 { config, lib, pkgs, ... }:
-with lib;
 let
 
   cfg = config.programs.proxychains;
 
   configFile = ''
     ${cfg.chain.type}_chain
-    ${optionalString (cfg.chain.type == "random")
+    ${lib.optionalString (cfg.chain.type == "random")
     "chain_len = ${builtins.toString cfg.chain.length}"}
-    ${optionalString cfg.proxyDNS "proxy_dns"}
-    ${optionalString cfg.quietMode "quiet_mode"}
+    ${lib.optionalString cfg.proxyDNS "proxy_dns"}
+    ${lib.optionalString cfg.quietMode "quiet_mode"}
     remote_dns_subnet ${builtins.toString cfg.remoteDNSSubnet}
     tcp_read_time_out ${builtins.toString cfg.tcpReadTimeOut}
     tcp_connect_time_out ${builtins.toString cfg.tcpConnectTimeOut}
@@ -22,20 +21,20 @@ let
 
   proxyOptions = {
     options = {
-      enable = mkEnableOption "this proxy";
+      enable = lib.mkEnableOption "this proxy";
 
-      type = mkOption {
-        type = types.enum [ "http" "socks4" "socks5" ];
+      type = lib.mkOption {
+        type = lib.types.enum [ "http" "socks4" "socks5" ];
         description = "Proxy type.";
       };
 
-      host = mkOption {
-        type = types.str;
+      host = lib.mkOption {
+        type = lib.types.str;
         description = "Proxy host or IP address.";
       };
 
-      port = mkOption {
-        type = types.port;
+      port = lib.mkOption {
+        type = lib.types.port;
         description = "Proxy port";
       };
     };
@@ -49,15 +48,15 @@ in {
 
     programs.proxychains = {
 
-      enable = mkEnableOption "proxychains configuration";
+      enable = lib.mkEnableOption "proxychains configuration";
 
-      package = mkPackageOption pkgs "proxychains" {
+      package = lib.mkPackageOption pkgs "proxychains" {
         example = "proxychains-ng";
       };
 
       chain = {
-        type = mkOption {
-          type = types.enum [ "dynamic" "strict" "random" ];
+        type = lib.mkOption {
+          type = lib.types.enum [ "dynamic" "strict" "random" ];
           default = "strict";
           description = ''
             `dynamic` - Each connection will be done via chained proxies
@@ -75,8 +74,8 @@ in {
             (or proxy chain, see {option}`programs.proxychains.chain.length`) from the list.
           '';
         };
-        length = mkOption {
-          type = types.nullOr types.int;
+        length = lib.mkOption {
+          type = lib.types.nullOr lib.types.int;
           default = null;
           description = ''
             Chain length for random chain.
@@ -84,47 +83,47 @@ in {
         };
       };
 
-      proxyDNS = mkOption {
-        type = types.bool;
+      proxyDNS = lib.mkOption {
+        type = lib.types.bool;
         default = true;
         description = "Proxy DNS requests - no leak for DNS data.";
       };
 
-      quietMode = mkEnableOption "Quiet mode (no output from the library)";
+      quietMode = lib.mkEnableOption "Quiet mode (no output from the library)";
 
-      remoteDNSSubnet = mkOption {
-        type = types.enum [ 10 127 224 ];
+      remoteDNSSubnet = lib.mkOption {
+        type = lib.types.enum [ 10 127 224 ];
         default = 224;
         description = ''
           Set the class A subnet number to use for the internal remote DNS mapping, uses the reserved 224.x.x.x range by default.
         '';
       };
 
-      tcpReadTimeOut = mkOption {
-        type = types.int;
+      tcpReadTimeOut = lib.mkOption {
+        type = lib.types.int;
         default = 15000;
         description = "Connection read time-out in milliseconds.";
       };
 
-      tcpConnectTimeOut = mkOption {
-        type = types.int;
+      tcpConnectTimeOut = lib.mkOption {
+        type = lib.types.int;
         default = 8000;
         description = "Connection time-out in milliseconds.";
       };
 
-      localnet = mkOption {
-        type = types.str;
+      localnet = lib.mkOption {
+        type = lib.types.str;
         default = "127.0.0.0/255.0.0.0";
         description = "By default enable localnet for loopback address ranges.";
       };
 
-      proxies = mkOption {
-        type = types.attrsOf (types.submodule proxyOptions);
+      proxies = lib.mkOption {
+        type = lib.types.attrsOf (lib.types.submodule proxyOptions);
         description = ''
           Proxies to be used by proxychains.
         '';
 
-        example = literalExpression ''
+        example = lib.literalExpression ''
           { myproxy =
             { type = "socks4";
               host = "127.0.0.1";
@@ -140,11 +139,11 @@ in {
 
   ###### implementation
 
-  meta.maintainers = with maintainers; [ sorki ];
+  meta.maintainers = with lib.maintainers; [ sorki ];
 
-  config = mkIf cfg.enable {
+  config = lib.mkIf cfg.enable {
 
-    assertions = singleton {
+    assertions = lib.singleton {
       assertion = cfg.chain.type != "random" && cfg.chain.length == null;
       message = ''
         Option `programs.proxychains.chain.length`
@@ -152,9 +151,9 @@ in {
       '';
     };
 
-    programs.proxychains.proxies = mkIf config.services.tor.client.enable
+    programs.proxychains.proxies = lib.mkIf config.services.tor.client.enable
       {
-        torproxy = mkDefault {
+        torproxy = lib.mkDefault {
           enable = true;
           type = "socks4";
           host = "127.0.0.1";
diff --git a/nixos/modules/programs/qt5ct.nix b/nixos/modules/programs/qt5ct.nix
index 3ff47b355915b..bc7b28b9c6e92 100644
--- a/nixos/modules/programs/qt5ct.nix
+++ b/nixos/modules/programs/qt5ct.nix
@@ -1,9 +1,7 @@
 { lib, ... }:
 
-with lib;
-
 {
   imports = [
-    (mkRemovedOptionModule [ "programs" "qt5ct" "enable" ] "Use qt5.platformTheme = \"qt5ct\" instead.")
+    (lib.mkRemovedOptionModule [ "programs" "qt5ct" "enable" ] "Use qt5.platformTheme = \"qt5ct\" instead.")
   ];
 }
diff --git a/nixos/modules/programs/rust-motd.nix b/nixos/modules/programs/rust-motd.nix
index 93240fcdd85ee..301b7cebb7f8a 100644
--- a/nixos/modules/programs/rust-motd.nix
+++ b/nixos/modules/programs/rust-motd.nix
@@ -1,7 +1,5 @@
 { config, lib, pkgs, ... }:
 
-with lib;
-
 let
   cfg = config.programs.rust-motd;
   format = pkgs.formats.toml { };
@@ -24,10 +22,10 @@ let
     '';
 in {
   options.programs.rust-motd = {
-    enable = mkEnableOption "rust-motd, a Message Of The Day (MOTD) generator";
-    enableMotdInSSHD = mkOption {
+    enable = lib.mkEnableOption "rust-motd, a Message Of The Day (MOTD) generator";
+    enableMotdInSSHD = lib.mkOption {
       default = true;
-      type = types.bool;
+      type = lib.types.bool;
       description = ''
         Whether to let `openssh` print the
         result when entering a new `ssh`-session.
@@ -36,18 +34,18 @@ in {
         the latter option is incompatible with this module.
       '';
     };
-    refreshInterval = mkOption {
+    refreshInterval = lib.mkOption {
       default = "*:0/5";
-      type = types.str;
+      type = lib.types.str;
       description = ''
         Interval in which the {manpage}`motd(5)` file is refreshed.
         For possible formats, please refer to {manpage}`systemd.time(7)`.
       '';
     };
-    order = mkOption {
-      type = types.listOf types.str;
-      default = attrNames cfg.settings;
-      defaultText = literalExpression "attrNames cfg.settings";
+    order = lib.mkOption {
+      type = lib.types.listOf lib.types.str;
+      default = builtins.attrNames cfg.settings;
+      defaultText = lib.literalExpression "attrNames cfg.settings";
       description = ''
         The order of the sections in [](#opt-programs.rust-motd.settings).
         By default they are ordered alphabetically.
@@ -79,8 +77,8 @@ in {
         makes sure that `uptime` is placed before `banner` in the motd.
       '';
     };
-    settings = mkOption {
-      type = types.attrsOf format.type;
+    settings = lib.mkOption {
+      type = lib.types.attrsOf format.type;
       description = ''
         Settings on what to generate. Please read the
         [upstream documentation](https://github.com/rust-motd/rust-motd/blob/main/README.md#configuration)
@@ -88,14 +86,14 @@ in {
       '';
     };
   };
-  config = mkIf cfg.enable {
+  config = lib.mkIf cfg.enable {
     assertions = [
       { assertion = config.users.motd == null;
         message = ''
           `programs.rust-motd` is incompatible with `users.motd`!
         '';
       }
-      { assertion = sort (a: b: a < b) cfg.order == attrNames cfg.settings;
+      { assertion = builtins.sort (a: b: a < b) cfg.order == builtins.attrNames cfg.settings;
         message = ''
           Please ensure that every section from `programs.rust-motd.settings` is present in
           `programs.rust-motd.order`.
@@ -138,12 +136,12 @@ in {
       wantedBy = [ "timers.target" ];
       timerConfig.OnCalendar = cfg.refreshInterval;
     };
-    security.pam.services.sshd.text = mkIf cfg.enableMotdInSSHD (mkDefault (mkAfter ''
+    security.pam.services.sshd.text = lib.mkIf cfg.enableMotdInSSHD (lib.mkDefault (lib.mkAfter ''
       session optional ${pkgs.pam}/lib/security/pam_motd.so motd=/var/lib/rust-motd/motd
     ''));
-    services.openssh.extraConfig = mkIf (cfg.settings ? last_login && cfg.settings.last_login != {}) ''
+    services.openssh.extraConfig = lib.mkIf (cfg.settings ? last_login && cfg.settings.last_login != {}) ''
       PrintLastLog no
     '';
   };
-  meta.maintainers = with maintainers; [ ma27 ];
+  meta.maintainers = with lib.maintainers; [ ma27 ];
 }
diff --git a/nixos/modules/programs/screen.nix b/nixos/modules/programs/screen.nix
index 01af5b4c9597a..4f3cd9fcf9a56 100644
--- a/nixos/modules/programs/screen.nix
+++ b/nixos/modules/programs/screen.nix
@@ -12,7 +12,8 @@ in
       package = lib.mkPackageOptionMD pkgs "screen" { };
 
       screenrc = lib.mkOption {
-        type = with lib.types; nullOr lines;
+        type = lib.types.lines;
+        default = "";
         example = ''
           defscrollback 10000
           startup_message off
@@ -22,20 +23,22 @@ in
     };
   };
 
-  config = {
-    # TODO: Added in 24.05, remove before 24.11
-    assertions = [
-      {
-        assertion = cfg.screenrc != null -> cfg.enable;
-        message = "`programs.screen.screenrc` has been configured, but `programs.screen.enable` is not true";
-      }
-    ];
-  } // lib.mkIf cfg.enable {
-    environment.etc.screenrc = {
-      enable = cfg.screenrc != null;
-      text = cfg.screenrc;
-    };
-    environment.systemPackages = [ cfg.package ];
-    security.pam.services.screen = {};
-  };
+  config = lib.mkMerge [
+    {
+      # TODO: Added in 24.05, remove before 24.11
+      assertions = [
+        {
+          assertion = cfg.screenrc != "" -> cfg.enable;
+          message = "`programs.screen.screenrc` has been configured, but `programs.screen.enable` is not true";
+        }
+      ];
+    }
+    (lib.mkIf cfg.enable {
+      environment.etc.screenrc = {
+        text = cfg.screenrc;
+      };
+      environment.systemPackages = [ cfg.package ];
+      security.pam.services.screen = {};
+    })
+  ];
 }
diff --git a/nixos/modules/programs/sedutil.nix b/nixos/modules/programs/sedutil.nix
index c62ca24eaa012..978aaa5c82d5a 100644
--- a/nixos/modules/programs/sedutil.nix
+++ b/nixos/modules/programs/sedutil.nix
@@ -1,14 +1,12 @@
 { config, lib, pkgs, ... }:
 
-with lib;
-
 let
   cfg = config.programs.sedutil;
 
 in {
-  options.programs.sedutil.enable = mkEnableOption "sedutil, to manage self encrypting drives that conform to the Trusted Computing Group OPAL 2.0 SSC specification";
+  options.programs.sedutil.enable = lib.mkEnableOption "sedutil, to manage self encrypting drives that conform to the Trusted Computing Group OPAL 2.0 SSC specification";
 
-  config = mkIf cfg.enable {
+  config = lib.mkIf cfg.enable {
     boot.kernelParams = [
       "libata.allow_tpm=1"
     ];
diff --git a/nixos/modules/programs/shadow.nix b/nixos/modules/programs/shadow.nix
index 2d20644ec51ed..f09bfaa5393d7 100644
--- a/nixos/modules/programs/shadow.nix
+++ b/nixos/modules/programs/shadow.nix
@@ -1,15 +1,14 @@
 # Configuration for the pwdutils suite of tools: passwd, useradd, etc.
 { config, lib, utils, pkgs, ... }:
-with lib;
 let
   cfg = config.security.loginDefs;
 in
 {
-  options = with types; {
+  options = with lib.types; {
     security.loginDefs = {
-      package = mkPackageOption pkgs "shadow" { };
+      package = lib.mkPackageOption pkgs "shadow" { };
 
-      chfnRestrict = mkOption {
+      chfnRestrict = lib.mkOption {
         description = ''
           Use chfn SUID to allow non-root users to change their account GECOS information.
         '';
@@ -17,7 +16,7 @@ in
         default = null;
       };
 
-      settings = mkOption {
+      settings = lib.mkOption {
         description = ''
           Config options for the /etc/login.defs file, that defines
           the site-specific configuration for the shadow password suite.
@@ -35,68 +34,68 @@ in
                by systemd for features like ConditionUser=@system and systemd-sysusers
               */
           options = {
-            DEFAULT_HOME = mkOption {
+            DEFAULT_HOME = lib.mkOption {
               description = "Indicate if login is allowed if we can't cd to the home directory.";
               default = "yes";
               type = enum [ "yes" "no" ];
             };
 
-            ENCRYPT_METHOD = mkOption {
+            ENCRYPT_METHOD = lib.mkOption {
               description = "This defines the system default encryption algorithm for encrypting passwords.";
               # The default crypt() method, keep in sync with the PAM default
               default = "YESCRYPT";
               type = enum [ "YESCRYPT" "SHA512" "SHA256" "MD5" "DES"];
             };
 
-            SYS_UID_MIN = mkOption {
+            SYS_UID_MIN = lib.mkOption {
               description = "Range of user IDs used for the creation of system users by useradd or newusers.";
               default = 400;
               type = int;
             };
 
-            SYS_UID_MAX = mkOption {
+            SYS_UID_MAX = lib.mkOption {
               description = "Range of user IDs used for the creation of system users by useradd or newusers.";
               default = 999;
               type = int;
             };
 
-            UID_MIN = mkOption {
+            UID_MIN = lib.mkOption {
               description = "Range of user IDs used for the creation of regular users by useradd or newusers.";
               default = 1000;
               type = int;
             };
 
-            UID_MAX = mkOption {
+            UID_MAX = lib.mkOption {
               description = "Range of user IDs used for the creation of regular users by useradd or newusers.";
               default = 29999;
               type = int;
             };
 
-            SYS_GID_MIN = mkOption {
+            SYS_GID_MIN = lib.mkOption {
               description = "Range of group IDs used for the creation of system groups by useradd, groupadd, or newusers";
               default = 400;
               type = int;
             };
 
-            SYS_GID_MAX = mkOption {
+            SYS_GID_MAX = lib.mkOption {
               description = "Range of group IDs used for the creation of system groups by useradd, groupadd, or newusers";
               default = 999;
               type = int;
             };
 
-            GID_MIN = mkOption {
+            GID_MIN = lib.mkOption {
               description = "Range of group IDs used for the creation of regular groups by useradd, groupadd, or newusers.";
               default = 1000;
               type = int;
             };
 
-            GID_MAX = mkOption {
+            GID_MAX = lib.mkOption {
               description = "Range of group IDs used for the creation of regular groups by useradd, groupadd, or newusers.";
               default = 29999;
               type = int;
             };
 
-            TTYGROUP = mkOption {
+            TTYGROUP = lib.mkOption {
               description = ''
                 The terminal permissions: the login tty will be owned by the TTYGROUP group,
                 and the permissions will be set to TTYPERM'';
@@ -104,7 +103,7 @@ in
               type = str;
             };
 
-            TTYPERM = mkOption {
+            TTYPERM = lib.mkOption {
               description = ''
                 The terminal permissions: the login tty will be owned by the TTYGROUP group,
                 and the permissions will be set to TTYPERM'';
@@ -113,7 +112,7 @@ in
             };
 
             # Ensure privacy for newly created home directories.
-            UMASK = mkOption {
+            UMASK = lib.mkOption {
               description = "The file mode creation mask is initialized to this value.";
               default = "077";
               type = str;
@@ -124,7 +123,7 @@ in
       };
     };
 
-    users.defaultUserShell = mkOption {
+    users.defaultUserShell = lib.mkOption {
       description = ''
         This option defines the default shell assigned to user
         accounts. This can be either a full system path or a shell package.
@@ -132,7 +131,7 @@ in
         This must not be a store path, since the path is
         used outside the store (in particular in /etc/passwd).
       '';
-      example = literalExpression "pkgs.zsh";
+      example = lib.literalExpression "pkgs.zsh";
       type = either path shellPackage;
     };
   };
@@ -160,18 +159,18 @@ in
     ];
 
     security.loginDefs.settings.CHFN_RESTRICT =
-      mkIf (cfg.chfnRestrict != null) cfg.chfnRestrict;
+      lib.mkIf (cfg.chfnRestrict != null) cfg.chfnRestrict;
 
-    environment.systemPackages = optional config.users.mutableUsers cfg.package
-      ++ optional (types.shellPackage.check config.users.defaultUserShell) config.users.defaultUserShell
-      ++ optional (cfg.chfnRestrict != null) pkgs.util-linux;
+    environment.systemPackages = lib.optional config.users.mutableUsers cfg.package
+      ++ lib.optional (lib.types.shellPackage.check config.users.defaultUserShell) config.users.defaultUserShell
+      ++ lib.optional (cfg.chfnRestrict != null) pkgs.util-linux;
 
     environment.etc =
       # Create custom toKeyValue generator
       # see https://man7.org/linux/man-pages/man5/login.defs.5.html for config specification
       let
-        toKeyValue = generators.toKeyValue {
-          mkKeyValue = generators.mkKeyValueDefault { } " ";
+        toKeyValue = lib.generators.toKeyValue {
+          mkKeyValue = lib.generators.mkKeyValueDefault { } " ";
         };
       in
       {
@@ -231,7 +230,7 @@ in
         newuidmap = mkSetuidRoot "${cfg.package.out}/bin/newuidmap";
         newgidmap = mkSetuidRoot "${cfg.package.out}/bin/newgidmap";
       }
-      // optionalAttrs config.users.mutableUsers {
+      // lib.optionalAttrs config.users.mutableUsers {
         chsh = mkSetuidRoot "${cfg.package.out}/bin/chsh";
         passwd = mkSetuidRoot "${cfg.package.out}/bin/passwd";
       };
diff --git a/nixos/modules/programs/sharing.nix b/nixos/modules/programs/sharing.nix
index 211dc9815166e..0fe8100bbc569 100644
--- a/nixos/modules/programs/sharing.nix
+++ b/nixos/modules/programs/sharing.nix
@@ -1,8 +1,7 @@
 { config, pkgs, lib, ... }:
-with lib;
 {
   options.programs.sharing = {
-    enable = mkEnableOption ''
+    enable = lib.mkEnableOption ''
       sharing, a CLI tool for sharing files.
 
       Note that it will opens the 7478 port for TCP in the firewall, which is needed for it to function properly
@@ -12,7 +11,7 @@ with lib;
     let
       cfg = config.programs.sharing;
     in
-      mkIf cfg.enable {
+      lib.mkIf cfg.enable {
         environment.systemPackages = [ pkgs.sharing ];
         networking.firewall.allowedTCPPorts = [ 7478 ];
       };
diff --git a/nixos/modules/programs/singularity.nix b/nixos/modules/programs/singularity.nix
index f4c0a6fe487e6..bc989ad2dbaf5 100644
--- a/nixos/modules/programs/singularity.nix
+++ b/nixos/modules/programs/singularity.nix
@@ -5,21 +5,20 @@
   ...
 }:
 
-with lib;
 let
   cfg = config.programs.singularity;
 in
 {
 
   options.programs.singularity = {
-    enable = mkEnableOption "singularity" // {
+    enable = lib.mkEnableOption "singularity" // {
       description = ''
         Whether to install Singularity/Apptainer with system-level overriding such as SUID support.
       '';
     };
-    package = mkPackageOption pkgs "singularity" { example = "apptainer"; };
-    packageOverriden = mkOption {
-      type = types.nullOr types.package;
+    package = lib.mkPackageOption pkgs "singularity" { example = "apptainer"; };
+    packageOverriden = lib.mkOption {
+      type = lib.types.nullOr lib.types.package;
       default = null;
       description = ''
         This option provides access to the overridden result of `programs.singularity.package`.
@@ -42,8 +41,8 @@ in
         Use `lib.mkForce` to forcefully specify the overridden package.
       '';
     };
-    enableExternalLocalStateDir = mkOption {
-      type = types.bool;
+    enableExternalLocalStateDir = lib.mkOption {
+      type = lib.types.bool;
       default = true;
       example = false;
       description = ''
@@ -54,22 +53,22 @@ in
         `/var/lib/''${projectName}/mnt/session`.
       '';
     };
-    enableFakeroot = mkOption {
-      type = types.bool;
+    enableFakeroot = lib.mkOption {
+      type = lib.types.bool;
       default = true;
       example = false;
       description = ''
         Whether to enable the `--fakeroot` support of Singularity/Apptainer.
       '';
     };
-    enableSuid = mkOption {
-      type = types.bool;
+    enableSuid = lib.mkOption {
+      type = lib.types.bool;
       # SingularityCE requires SETUID for most things. Apptainer prefers user
       # namespaces, e.g. `apptainer exec --nv` would fail if built
       # `--with-suid`:
       # > `FATAL: nvidia-container-cli not allowed in setuid mode`
       default = cfg.package.projectName != "apptainer";
-      defaultText = literalExpression ''config.services.singularity.package.projectName != "apptainer"'';
+      defaultText = lib.literalExpression ''config.services.singularity.package.projectName != "apptainer"'';
       example = false;
       description = ''
         Whether to enable the SUID support of Singularity/Apptainer.
@@ -77,28 +76,28 @@ in
     };
   };
 
-  config = mkIf cfg.enable {
+  config = lib.mkIf cfg.enable {
     programs.singularity.packageOverriden = (
       cfg.package.override (
-        optionalAttrs cfg.enableExternalLocalStateDir { externalLocalStateDir = "/var/lib"; }
-        // optionalAttrs cfg.enableFakeroot {
+        lib.optionalAttrs cfg.enableExternalLocalStateDir { externalLocalStateDir = "/var/lib"; }
+        // lib.optionalAttrs cfg.enableFakeroot {
           newuidmapPath = "/run/wrappers/bin/newuidmap";
           newgidmapPath = "/run/wrappers/bin/newgidmap";
         }
-        // optionalAttrs cfg.enableSuid {
+        // lib.optionalAttrs cfg.enableSuid {
           enableSuid = true;
           starterSuidPath = "/run/wrappers/bin/${cfg.package.projectName}-suid";
         }
       )
     );
     environment.systemPackages = [ cfg.packageOverriden ];
-    security.wrappers."${cfg.packageOverriden.projectName}-suid" = mkIf cfg.enableSuid {
+    security.wrappers."${cfg.packageOverriden.projectName}-suid" = lib.mkIf cfg.enableSuid {
       setuid = true;
       owner = "root";
       group = "root";
       source = "${cfg.packageOverriden}/libexec/${cfg.packageOverriden.projectName}/bin/starter-suid.orig";
     };
-    systemd.tmpfiles.rules = mkIf cfg.enableExternalLocalStateDir [
+    systemd.tmpfiles.rules = lib.mkIf cfg.enableExternalLocalStateDir [
       "d /var/lib/${cfg.packageOverriden.projectName}/mnt/session 0770 root root -"
     ];
   };
diff --git a/nixos/modules/programs/slock.nix b/nixos/modules/programs/slock.nix
index f39b4d5e9280e..ce24f662f218c 100644
--- a/nixos/modules/programs/slock.nix
+++ b/nixos/modules/programs/slock.nix
@@ -1,7 +1,5 @@
 { config, lib, pkgs, ... }:
 
-with lib;
-
 let
   cfg = config.programs.slock;
 
@@ -9,18 +7,18 @@ in
 {
   options = {
     programs.slock = {
-      enable = mkOption {
+      enable = lib.mkOption {
         default = false;
-        type = types.bool;
+        type = lib.types.bool;
         description = ''
           Whether to install slock screen locker with setuid wrapper.
         '';
       };
-      package = mkPackageOption pkgs "slock" {};
+      package = lib.mkPackageOption pkgs "slock" {};
     };
   };
 
-  config = mkIf cfg.enable {
+  config = lib.mkIf cfg.enable {
     environment.systemPackages = [ cfg.package ];
     security.wrappers.slock =
       { setuid = true;
diff --git a/nixos/modules/programs/soundmodem.nix b/nixos/modules/programs/soundmodem.nix
index ab992c63c6088..5f57e24a4524a 100644
--- a/nixos/modules/programs/soundmodem.nix
+++ b/nixos/modules/programs/soundmodem.nix
@@ -1,26 +1,24 @@
 { config, lib, pkgs, ... }:
 
-with lib;
-
 let
   cfg = config.programs.soundmodem;
 in
 {
   options = {
     programs.soundmodem = {
-      enable = mkOption {
-        type = types.bool;
+      enable = lib.mkOption {
+        type = lib.types.bool;
         default = false;
         description = ''
           Whether to add Soundmodem to the global environment and configure a
           wrapper for 'soundmodemconfig' for users in the 'soundmodem' group.
         '';
       };
-      package = mkPackageOption pkgs "soundmodem" { };
+      package = lib.mkPackageOption pkgs "soundmodem" { };
     };
   };
 
-  config = mkIf cfg.enable {
+  config = lib.mkIf cfg.enable {
     environment.systemPackages = [ cfg.package ];
     users.groups.soundmodem = { };
 
diff --git a/nixos/modules/programs/spacefm.nix b/nixos/modules/programs/spacefm.nix
index fec14fca48e1e..73d48cf6a3a83 100644
--- a/nixos/modules/programs/spacefm.nix
+++ b/nixos/modules/programs/spacefm.nix
@@ -2,8 +2,6 @@
 
 { config, lib, pkgs, ... }:
 
-with lib;
-
 let cfg = config.programs.spacefm;
 
 in
@@ -14,21 +12,21 @@ in
 
     programs.spacefm = {
 
-      enable = mkOption {
-        type = types.bool;
+      enable = lib.mkOption {
+        type = lib.types.bool;
         default = false;
         description = ''
           Whether to install SpaceFM and create {file}`/etc/spacefm/spacefm.conf`.
         '';
       };
 
-      settings = mkOption {
-        type = types.attrs;
+      settings = lib.mkOption {
+        type = lib.types.attrs;
         default = {
           tmp_dir = "/tmp";
           terminal_su = "${pkgs.sudo}/bin/sudo";
         };
-        defaultText = literalExpression ''
+        defaultText = lib.literalExpression ''
           {
             tmp_dir = "/tmp";
             terminal_su = "''${pkgs.sudo}/bin/sudo";
@@ -46,10 +44,10 @@ in
 
   ###### implementation
 
-  config = mkIf cfg.enable {
+  config = lib.mkIf cfg.enable {
     environment.systemPackages = [ pkgs.spaceFM ];
 
     environment.etc."spacefm/spacefm.conf".text =
-      concatStrings (mapAttrsToList (n: v: "${n}=${toString v}\n") cfg.settings);
+      lib.concatStrings (lib.mapAttrsToList (n: v: "${n}=${builtins.toString v}\n") cfg.settings);
   };
 }
diff --git a/nixos/modules/programs/ssh.nix b/nixos/modules/programs/ssh.nix
index 2d25c7a936623..0692dd46f7d04 100644
--- a/nixos/modules/programs/ssh.nix
+++ b/nixos/modules/programs/ssh.nix
@@ -2,8 +2,6 @@
 
 { config, lib, pkgs, ... }:
 
-with lib;
-
 let
 
   cfg  = config.programs.ssh;
@@ -17,16 +15,16 @@ let
       exec ${cfg.askPassword} "$@"
     '';
 
-  knownHosts = attrValues cfg.knownHosts;
+  knownHosts = builtins.attrValues cfg.knownHosts;
 
-  knownHostsText = (flip (concatMapStringsSep "\n") knownHosts
+  knownHostsText = (lib.flip (lib.concatMapStringsSep "\n") knownHosts
     (h: assert h.hostNames != [];
-      optionalString h.certAuthority "@cert-authority " + concatStringsSep "," h.hostNames + " "
-      + (if h.publicKey != null then h.publicKey else readFile h.publicKeyFile)
+      lib.optionalString h.certAuthority "@cert-authority " + builtins.concatStringsSep "," h.hostNames + " "
+      + (if h.publicKey != null then h.publicKey else builtins.readFile h.publicKeyFile)
     )) + "\n";
 
   knownHostsFiles = [ "/etc/ssh/ssh_known_hosts" ]
-    ++ map pkgs.copyPathToStore cfg.knownHostsFiles;
+    ++ builtins.map pkgs.copyPathToStore cfg.knownHostsFiles;
 
 in
 {
@@ -36,21 +34,21 @@ in
 
     programs.ssh = {
 
-      enableAskPassword = mkOption {
-        type = types.bool;
+      enableAskPassword = lib.mkOption {
+        type = lib.types.bool;
         default = config.services.xserver.enable;
-        defaultText = literalExpression "config.services.xserver.enable";
+        defaultText = lib.literalExpression "config.services.xserver.enable";
         description = "Whether to configure SSH_ASKPASS in the environment.";
       };
 
-      askPassword = mkOption {
-        type = types.str;
+      askPassword = lib.mkOption {
+        type = lib.types.str;
         default = "${pkgs.x11_ssh_askpass}/libexec/x11-ssh-askpass";
-        defaultText = literalExpression ''"''${pkgs.x11_ssh_askpass}/libexec/x11-ssh-askpass"'';
+        defaultText = lib.literalExpression ''"''${pkgs.x11_ssh_askpass}/libexec/x11-ssh-askpass"'';
         description = "Program used by SSH to ask for passwords.";
       };
 
-      forwardX11 = mkOption {
+      forwardX11 = lib.mkOption {
         type = with lib.types; nullOr bool;
         default = false;
         description = ''
@@ -65,25 +63,25 @@ in
         '';
       };
 
-      setXAuthLocation = mkOption {
-        type = types.bool;
+      setXAuthLocation = lib.mkOption {
+        type = lib.types.bool;
         description = ''
           Whether to set the path to {command}`xauth` for X11-forwarded connections.
           This causes a dependency on X11 packages.
         '';
       };
 
-      pubkeyAcceptedKeyTypes = mkOption {
-        type = types.listOf types.str;
+      pubkeyAcceptedKeyTypes = lib.mkOption {
+        type = lib.types.listOf lib.types.str;
         default = [];
         example = [ "ssh-ed25519" "ssh-rsa" ];
         description = ''
-          Specifies the key types that will be used for public key authentication.
+          Specifies the key lib.types that will be used for public key authentication.
         '';
       };
 
-      hostKeyAlgorithms = mkOption {
-        type = types.listOf types.str;
+      hostKeyAlgorithms = lib.mkOption {
+        type = lib.types.listOf lib.types.str;
         default = [];
         example = [ "ssh-ed25519" "ssh-rsa" ];
         description = ''
@@ -91,8 +89,8 @@ in
         '';
       };
 
-      extraConfig = mkOption {
-        type = types.lines;
+      extraConfig = lib.mkOption {
+        type = lib.types.lines;
         default = "";
         description = ''
           Extra configuration text prepended to {file}`ssh_config`. Other generated
@@ -102,8 +100,8 @@ in
         '';
       };
 
-      startAgent = mkOption {
-        type = types.bool;
+      startAgent = lib.mkOption {
+        type = lib.types.bool;
         default = false;
         description = ''
           Whether to start the OpenSSH agent when you log in.  The OpenSSH agent
@@ -113,8 +111,8 @@ in
         '';
       };
 
-      agentTimeout = mkOption {
-        type = types.nullOr types.str;
+      agentTimeout = lib.mkOption {
+        type = lib.types.nullOr lib.types.str;
         default = null;
         example = "1h";
         description = ''
@@ -122,34 +120,34 @@ in
         '';
       };
 
-      agentPKCS11Whitelist = mkOption {
-        type = types.nullOr types.str;
+      agentPKCS11Whitelist = lib.mkOption {
+        type = lib.types.nullOr lib.types.str;
         default = null;
-        example = literalExpression ''"''${pkgs.opensc}/lib/opensc-pkcs11.so"'';
+        example = lib.literalExpression ''"''${pkgs.opensc}/lib/opensc-pkcs11.so"'';
         description = ''
           A pattern-list of acceptable paths for PKCS#11 shared libraries
           that may be used with the -s option to ssh-add.
         '';
       };
 
-      package = mkPackageOption pkgs "openssh" { };
+      package = lib.mkPackageOption pkgs "openssh" { };
 
-      knownHosts = mkOption {
+      knownHosts = lib.mkOption {
         default = {};
-        type = types.attrsOf (types.submodule ({ name, config, options, ... }: {
+        type = lib.types.attrsOf (lib.types.submodule ({ name, config, options, ... }: {
           options = {
-            certAuthority = mkOption {
-              type = types.bool;
+            certAuthority = lib.mkOption {
+              type = lib.types.bool;
               default = false;
               description = ''
                 This public key is an SSH certificate authority, rather than an
                 individual host's key.
               '';
             };
-            hostNames = mkOption {
-              type = types.listOf types.str;
+            hostNames = lib.mkOption {
+              type = lib.types.listOf lib.types.str;
               default = [ name ] ++ config.extraHostNames;
-              defaultText = literalExpression "[ ${name} ] ++ config.${options.extraHostNames}";
+              defaultText = lib.literalExpression "[ ${name} ] ++ config.${options.extraHostNames}";
               description = ''
                 A list of host names and/or IP numbers used for accessing
                 the host's ssh service. This list includes the name of the
@@ -160,8 +158,8 @@ in
                 `hostNames` list.
               '';
             };
-            extraHostNames = mkOption {
-              type = types.listOf types.str;
+            extraHostNames = lib.mkOption {
+              type = lib.types.listOf lib.types.str;
               default = [];
               description = ''
                 A list of additional host names and/or IP numbers used for
@@ -169,9 +167,9 @@ in
                 `hostNames` is set explicitly.
               '';
             };
-            publicKey = mkOption {
+            publicKey = lib.mkOption {
               default = null;
-              type = types.nullOr types.str;
+              type = lib.types.nullOr lib.types.str;
               example = "ecdsa-sha2-nistp521 AAAAE2VjZHN...UEPg==";
               description = ''
                 The public key data for the host. You can fetch a public key
@@ -180,9 +178,9 @@ in
                 the key type and the key itself.
               '';
             };
-            publicKeyFile = mkOption {
+            publicKeyFile = lib.mkOption {
               default = null;
-              type = types.nullOr types.path;
+              type = lib.types.nullOr lib.types.path;
               description = ''
                 The path to the public key file for the host. The public
                 key file is read at build time and saved in the Nix store.
@@ -204,7 +202,7 @@ in
           `extraHostNames` to add additional host names without
           disabling this default.
         '';
-        example = literalExpression ''
+        example = lib.literalExpression ''
           {
             myhost = {
               extraHostNames = [ "myhost.mydomain.com" "10.10.1.4" ];
@@ -219,16 +217,16 @@ in
         '';
       };
 
-      knownHostsFiles = mkOption {
+      knownHostsFiles = lib.mkOption {
         default = [];
-        type = with types; listOf path;
+        type = with lib.types; listOf path;
         description = ''
           Files containing SSH host keys to set as global known hosts.
           `/etc/ssh/ssh_known_hosts` (which is
           generated by {option}`programs.ssh.knownHosts`) is
           always included.
         '';
-        example = literalExpression ''
+        example = lib.literalExpression ''
           [
             ./known_hosts
             (writeText "github.keys" '''
@@ -240,8 +238,8 @@ in
         '';
       };
 
-      kexAlgorithms = mkOption {
-        type = types.nullOr (types.listOf types.str);
+      kexAlgorithms = lib.mkOption {
+        type = lib.types.nullOr (lib.types.listOf lib.types.str);
         default = null;
         example = [ "curve25519-sha256@libssh.org" "diffie-hellman-group-exchange-sha256" ];
         description = ''
@@ -249,8 +247,8 @@ in
         '';
       };
 
-      ciphers = mkOption {
-        type = types.nullOr (types.listOf types.str);
+      ciphers = lib.mkOption {
+        type = lib.types.nullOr (lib.types.listOf lib.types.str);
         default = null;
         example = [ "chacha20-poly1305@openssh.com" "aes256-gcm@openssh.com" ];
         description = ''
@@ -258,8 +256,8 @@ in
         '';
       };
 
-      macs = mkOption {
-        type = types.nullOr (types.listOf types.str);
+      macs = lib.mkOption {
+        type = lib.types.nullOr (lib.types.listOf lib.types.str);
         default = null;
         example = [ "hmac-sha2-512-etm@openssh.com" "hmac-sha1" ];
         description = ''
@@ -274,13 +272,13 @@ in
   config = {
 
     programs.ssh.setXAuthLocation =
-      mkDefault (config.services.xserver.enable || config.programs.ssh.forwardX11 == true || config.services.openssh.settings.X11Forwarding);
+      lib.mkDefault (config.services.xserver.enable || config.programs.ssh.forwardX11 == true || config.services.openssh.settings.X11Forwarding);
 
     assertions =
       [ { assertion = cfg.forwardX11 == true -> cfg.setXAuthLocation;
           message = "cannot enable X11 forwarding without setting XAuth location";
         }
-      ] ++ flip mapAttrsToList cfg.knownHosts (name: data: {
+      ] ++ lib.flip lib.mapAttrsToList cfg.knownHosts (name: data: {
         assertion = (data.publicKey == null && data.publicKeyFile != null) ||
                     (data.publicKey != null && data.publicKeyFile == null);
         message = "knownHost ${name} must contain either a publicKey or publicKeyFile";
@@ -296,22 +294,22 @@ in
         # Generated options from other settings
         Host *
         AddressFamily ${if config.networking.enableIPv6 then "any" else "inet"}
-        GlobalKnownHostsFile ${concatStringsSep " " knownHostsFiles}
+        GlobalKnownHostsFile ${builtins.concatStringsSep " " knownHostsFiles}
 
-        ${optionalString cfg.setXAuthLocation "XAuthLocation ${pkgs.xorg.xauth}/bin/xauth"}
+        ${lib.optionalString cfg.setXAuthLocation "XAuthLocation ${pkgs.xorg.xauth}/bin/xauth"}
         ${lib.optionalString (cfg.forwardX11 != null) "ForwardX11 ${if cfg.forwardX11 then "yes" else "no"}"}
 
-        ${optionalString (cfg.pubkeyAcceptedKeyTypes != []) "PubkeyAcceptedKeyTypes ${concatStringsSep "," cfg.pubkeyAcceptedKeyTypes}"}
-        ${optionalString (cfg.hostKeyAlgorithms != []) "HostKeyAlgorithms ${concatStringsSep "," cfg.hostKeyAlgorithms}"}
-        ${optionalString (cfg.kexAlgorithms != null) "KexAlgorithms ${concatStringsSep "," cfg.kexAlgorithms}"}
-        ${optionalString (cfg.ciphers != null) "Ciphers ${concatStringsSep "," cfg.ciphers}"}
-        ${optionalString (cfg.macs != null) "MACs ${concatStringsSep "," cfg.macs}"}
+        ${lib.optionalString (cfg.pubkeyAcceptedKeyTypes != []) "PubkeyAcceptedKeyTypes ${builtins.concatStringsSep "," cfg.pubkeyAcceptedKeyTypes}"}
+        ${lib.optionalString (cfg.hostKeyAlgorithms != []) "HostKeyAlgorithms ${builtins.concatStringsSep "," cfg.hostKeyAlgorithms}"}
+        ${lib.optionalString (cfg.kexAlgorithms != null) "KexAlgorithms ${builtins.concatStringsSep "," cfg.kexAlgorithms}"}
+        ${lib.optionalString (cfg.ciphers != null) "Ciphers ${builtins.concatStringsSep "," cfg.ciphers}"}
+        ${lib.optionalString (cfg.macs != null) "MACs ${builtins.concatStringsSep "," cfg.macs}"}
       '';
 
     environment.etc."ssh/ssh_known_hosts".text = knownHostsText;
 
     # FIXME: this should really be socket-activated for über-awesomeness.
-    systemd.user.services.ssh-agent = mkIf cfg.startAgent
+    systemd.user.services.ssh-agent = lib.mkIf cfg.startAgent
       { description = "SSH Agent";
         wantedBy = [ "default.target" ];
         unitConfig.ConditionUser = "!@system";
@@ -319,8 +317,8 @@ in
           { ExecStartPre = "${pkgs.coreutils}/bin/rm -f %t/ssh-agent";
             ExecStart =
                 "${cfg.package}/bin/ssh-agent " +
-                optionalString (cfg.agentTimeout != null) ("-t ${cfg.agentTimeout} ") +
-                optionalString (cfg.agentPKCS11Whitelist != null) ("-P ${cfg.agentPKCS11Whitelist} ") +
+                lib.optionalString (cfg.agentTimeout != null) ("-t ${cfg.agentTimeout} ") +
+                lib.optionalString (cfg.agentPKCS11Whitelist != null) ("-P ${cfg.agentPKCS11Whitelist} ") +
                 "-a %t/ssh-agent";
             StandardOutput = "null";
             Type = "forking";
@@ -330,18 +328,18 @@ in
         # Allow ssh-agent to ask for confirmation. This requires the
         # unit to know about the user's $DISPLAY (via ‘systemctl
         # import-environment’).
-        environment.SSH_ASKPASS = optionalString cfg.enableAskPassword askPasswordWrapper;
+        environment.SSH_ASKPASS = lib.optionalString cfg.enableAskPassword askPasswordWrapper;
         environment.DISPLAY = "fake"; # required to make ssh-agent start $SSH_ASKPASS
       };
 
-    environment.extraInit = optionalString cfg.startAgent
+    environment.extraInit = lib.optionalString cfg.startAgent
       ''
         if [ -z "$SSH_AUTH_SOCK" -a -n "$XDG_RUNTIME_DIR" ]; then
           export SSH_AUTH_SOCK="$XDG_RUNTIME_DIR/ssh-agent"
         fi
       '';
 
-    environment.variables.SSH_ASKPASS = optionalString cfg.enableAskPassword cfg.askPassword;
+    environment.variables.SSH_ASKPASS = lib.optionalString cfg.enableAskPassword cfg.askPassword;
 
   };
 }
diff --git a/nixos/modules/programs/steam.nix b/nixos/modules/programs/steam.nix
index 58aa0aa25b082..31577ac2de454 100644
--- a/nixos/modules/programs/steam.nix
+++ b/nixos/modules/programs/steam.nix
@@ -1,17 +1,17 @@
 { config, lib, pkgs, ... }:
 
-with lib;
-
 let
   cfg = config.programs.steam;
   gamescopeCfg = config.programs.gamescope;
 
+  extraCompatPaths = lib.makeSearchPathOutput "steamcompattool" "" cfg.extraCompatPackages;
+
   steam-gamescope = let
     exports = builtins.attrValues (builtins.mapAttrs (n: v: "export ${n}=${v}") cfg.gamescopeSession.env);
   in
     pkgs.writeShellScriptBin "steam-gamescope" ''
       ${builtins.concatStringsSep "\n" exports}
-      gamescope --steam ${toString cfg.gamescopeSession.args} -- steam -tenfoot -pipewire-dmabuf
+      gamescope --steam ${builtins.toString cfg.gamescopeSession.args} -- steam -tenfoot -pipewire-dmabuf
     '';
 
   gamescopeSessionFile =
@@ -24,13 +24,13 @@ let
     '').overrideAttrs (_: { passthru.providedSessions = [ "steam" ]; });
 in {
   options.programs.steam = {
-    enable = mkEnableOption "steam";
+    enable = lib.mkEnableOption "steam";
 
-    package = mkOption {
-      type = types.package;
+    package = lib.mkOption {
+      type = lib.types.package;
       default = pkgs.steam;
-      defaultText = literalExpression "pkgs.steam";
-      example = literalExpression ''
+      defaultText = lib.literalExpression "pkgs.steam";
+      example = lib.literalExpression ''
         pkgs.steam-small.override {
           extraEnv = {
             MANGOHUD = true;
@@ -44,8 +44,8 @@ in {
       '';
       apply = steam: steam.override (prev: {
         extraEnv = (lib.optionalAttrs (cfg.extraCompatPackages != [ ]) {
-          STEAM_EXTRA_COMPAT_TOOLS_PATHS = makeSearchPathOutput "steamcompattool" "" cfg.extraCompatPackages;
-        }) // (optionalAttrs cfg.extest.enable {
+          STEAM_EXTRA_COMPAT_TOOLS_PATHS = extraCompatPaths;
+        }) // (lib.optionalAttrs cfg.extest.enable {
           LD_PRELOAD = "${pkgs.pkgsi686Linux.extest}/lib/libextest.so";
         }) // (prev.extraEnv or {});
         extraLibraries = pkgs: let
@@ -55,7 +55,7 @@ in {
             then [ package ] ++ extraPackages
             else [ package32 ] ++ extraPackages32;
         in prevLibs ++ additionalLibs;
-      } // optionalAttrs (cfg.gamescopeSession.enable && gamescopeCfg.capSysNice)
+      } // lib.optionalAttrs (cfg.gamescopeSession.enable && gamescopeCfg.capSysNice)
       {
         buildFHSEnv = pkgs.buildFHSEnv.override {
           # use the setuid wrapped bubblewrap
@@ -71,10 +71,10 @@ in {
       '';
     };
 
-    extraCompatPackages = mkOption {
-      type = types.listOf types.package;
+    extraCompatPackages = lib.mkOption {
+      type = lib.types.listOf lib.types.package;
       default = [ ];
-      example = literalExpression ''
+      example = lib.literalExpression ''
         with pkgs; [
           proton-ge-bin
         ]
@@ -88,46 +88,46 @@ in {
       '';
     };
 
-    remotePlay.openFirewall = mkOption {
-      type = types.bool;
+    remotePlay.openFirewall = lib.mkOption {
+      type = lib.types.bool;
       default = false;
       description = ''
         Open ports in the firewall for Steam Remote Play.
       '';
     };
 
-    dedicatedServer.openFirewall = mkOption {
-      type = types.bool;
+    dedicatedServer.openFirewall = lib.mkOption {
+      type = lib.types.bool;
       default = false;
       description = ''
         Open ports in the firewall for Source Dedicated Server.
       '';
     };
 
-    localNetworkGameTransfers.openFirewall = mkOption {
-      type = types.bool;
+    localNetworkGameTransfers.openFirewall = lib.mkOption {
+      type = lib.types.bool;
       default = false;
       description = ''
         Open ports in the firewall for Steam Local Network Game Transfers.
       '';
     };
 
-    gamescopeSession = mkOption {
+    gamescopeSession = lib.mkOption {
       description = "Run a GameScope driven Steam session from your display-manager";
       default = {};
-      type = types.submodule {
+      type = lib.types.submodule {
         options = {
-          enable = mkEnableOption "GameScope Session";
-          args = mkOption {
-            type = types.listOf types.str;
+          enable = lib.mkEnableOption "GameScope Session";
+          args = lib.mkOption {
+            type = lib.types.listOf lib.types.str;
             default = [ ];
             description = ''
               Arguments to be passed to GameScope for the session.
             '';
           };
 
-          env = mkOption {
-            type = types.attrsOf types.str;
+          env = lib.mkOption {
+            type = lib.types.attrsOf lib.types.str;
             default = { };
             description = ''
               Environmental variables to be passed to GameScope for the session.
@@ -137,20 +137,25 @@ in {
       };
     };
 
-    extest.enable = mkEnableOption ''
+    extest.enable = lib.mkEnableOption ''
       Load the extest library into Steam, to translate X11 input events to
       uinput events (e.g. for using Steam Input on Wayland)
     '';
+
+    protontricks = {
+      enable = lib.mkEnableOption "protontricks, a simple wrapper for running Winetricks commands for Proton-enabled games";
+      package = lib.mkPackageOption pkgs "protontricks" { };
+    };
   };
 
-  config = mkIf cfg.enable {
+  config = lib.mkIf cfg.enable {
     hardware.opengl = { # this fixes the "glXChooseVisual failed" bug, context: https://github.com/NixOS/nixpkgs/issues/47932
       enable = true;
       driSupport = true;
       driSupport32Bit = true;
     };
 
-    security.wrappers = mkIf (cfg.gamescopeSession.enable && gamescopeCfg.capSysNice) {
+    security.wrappers = lib.mkIf (cfg.gamescopeSession.enable && gamescopeCfg.capSysNice) {
       # needed or steam fails
       bwrap = {
         owner = "root";
@@ -160,8 +165,8 @@ in {
       };
     };
 
-    programs.gamescope.enable = mkDefault cfg.gamescopeSession.enable;
-    services.displayManager.sessionPackages = mkIf cfg.gamescopeSession.enable [ gamescopeSessionFile ];
+    programs.gamescope.enable = lib.mkDefault cfg.gamescopeSession.enable;
+    services.displayManager.sessionPackages = lib.mkIf cfg.gamescopeSession.enable [ gamescopeSessionFile ];
 
     # optionally enable 32bit pulseaudio support if pulseaudio is enabled
     hardware.pulseaudio.support32Bit = config.hardware.pulseaudio.enable;
@@ -171,28 +176,29 @@ in {
     environment.systemPackages = [
       cfg.package
       cfg.package.run
-    ] ++ lib.optional cfg.gamescopeSession.enable steam-gamescope;
+    ] ++ lib.optional cfg.gamescopeSession.enable steam-gamescope
+    ++ lib.optional cfg.protontricks.enable (cfg.protontricks.package.override { inherit extraCompatPaths; });
 
     networking.firewall = lib.mkMerge [
-      (mkIf (cfg.remotePlay.openFirewall || cfg.localNetworkGameTransfers.openFirewall) {
+      (lib.mkIf (cfg.remotePlay.openFirewall || cfg.localNetworkGameTransfers.openFirewall) {
         allowedUDPPorts = [ 27036 ]; # Peer discovery
       })
 
-      (mkIf cfg.remotePlay.openFirewall {
+      (lib.mkIf cfg.remotePlay.openFirewall {
         allowedTCPPorts = [ 27036 ];
         allowedUDPPortRanges = [ { from = 27031; to = 27035; } ];
       })
 
-      (mkIf cfg.dedicatedServer.openFirewall {
+      (lib.mkIf cfg.dedicatedServer.openFirewall {
         allowedTCPPorts = [ 27015 ]; # SRCDS Rcon port
         allowedUDPPorts = [ 27015 ]; # Gameplay traffic
       })
 
-      (mkIf cfg.localNetworkGameTransfers.openFirewall {
+      (lib.mkIf cfg.localNetworkGameTransfers.openFirewall {
         allowedTCPPorts = [ 27040 ]; # Data transfers
       })
     ];
   };
 
-  meta.maintainers = teams.steam;
+  meta.maintainers = lib.teams.steam.members;
 }
diff --git a/nixos/modules/programs/streamdeck-ui.nix b/nixos/modules/programs/streamdeck-ui.nix
index 6bec2abdfbec6..a1366c42181c2 100644
--- a/nixos/modules/programs/streamdeck-ui.nix
+++ b/nixos/modules/programs/streamdeck-ui.nix
@@ -1,34 +1,32 @@
 { config, lib, pkgs, ... }:
 
-with lib;
-
 let
   cfg = config.programs.streamdeck-ui;
 in
 {
   options.programs.streamdeck-ui = {
-    enable = mkEnableOption "streamdeck-ui";
+    enable = lib.mkEnableOption "streamdeck-ui";
 
-    autoStart = mkOption {
+    autoStart = lib.mkOption {
       default = true;
-      type = types.bool;
+      type = lib.types.bool;
       description = "Whether streamdeck-ui should be started automatically.";
     };
 
-    package = mkPackageOption pkgs "streamdeck-ui" {
+    package = lib.mkPackageOption pkgs "streamdeck-ui" {
       default = [ "streamdeck-ui" ];
     };
 
   };
 
-  config = mkIf cfg.enable {
-    environment.systemPackages = with pkgs; [
+  config = lib.mkIf cfg.enable {
+    environment.systemPackages = [
       cfg.package
-      (mkIf cfg.autoStart (makeAutostartItem { name = "streamdeck-ui-noui"; package = cfg.package; }))
+      (lib.mkIf cfg.autoStart (pkgs.makeAutostartItem { name = "streamdeck-ui-noui"; package = cfg.package; }))
     ];
 
     services.udev.packages = [ cfg.package ];
   };
 
-  meta.maintainers = with maintainers; [ majiir ];
+  meta.maintainers = with lib.maintainers; [ majiir ];
 }
diff --git a/nixos/modules/programs/sysdig.nix b/nixos/modules/programs/sysdig.nix
index cf2cbab5cf6e5..47b95ef64e97f 100644
--- a/nixos/modules/programs/sysdig.nix
+++ b/nixos/modules/programs/sysdig.nix
@@ -1,13 +1,11 @@
 { config, lib, pkgs, ... }:
 
-with lib;
-
 let
   cfg = config.programs.sysdig;
 in {
-  options.programs.sysdig.enable = mkEnableOption "sysdig, a tracing tool";
+  options.programs.sysdig.enable = lib.mkEnableOption "sysdig, a tracing tool";
 
-  config = mkIf cfg.enable {
+  config = lib.mkIf cfg.enable {
     environment.systemPackages = [ pkgs.sysdig ];
     boot.extraModulePackages = [ config.boot.kernelPackages.sysdig ];
   };
diff --git a/nixos/modules/programs/system-config-printer.nix b/nixos/modules/programs/system-config-printer.nix
index 34592dd7064b4..68b7897d64c24 100644
--- a/nixos/modules/programs/system-config-printer.nix
+++ b/nixos/modules/programs/system-config-printer.nix
@@ -1,7 +1,5 @@
 { config, pkgs, lib, ... }:
 
-with lib;
-
 {
 
   ###### interface
@@ -10,7 +8,7 @@ with lib;
 
     programs.system-config-printer = {
 
-      enable = mkEnableOption "system-config-printer, a Graphical user interface for CUPS administration";
+      enable = lib.mkEnableOption "system-config-printer, a Graphical user interface for CUPS administration";
 
     };
 
@@ -19,7 +17,7 @@ with lib;
 
   ###### implementation
 
-  config = mkIf config.programs.system-config-printer.enable {
+  config = lib.mkIf config.programs.system-config-printer.enable {
 
     environment.systemPackages = [
       pkgs.system-config-printer
diff --git a/nixos/modules/programs/systemtap.nix b/nixos/modules/programs/systemtap.nix
index d23bd13fdd85d..e61e255e52217 100644
--- a/nixos/modules/programs/systemtap.nix
+++ b/nixos/modules/programs/systemtap.nix
@@ -1,14 +1,12 @@
 { config, lib, ... }:
 
-with lib;
-
 let cfg = config.programs.systemtap;
 in {
 
   options = {
     programs.systemtap = {
-      enable = mkOption {
-        type = types.bool;
+      enable = lib.mkOption {
+        type = lib.types.bool;
         default = false;
         description = ''
           Install {command}`systemtap` along with necessary kernel options.
@@ -16,7 +14,7 @@ in {
       };
     };
   };
-  config = mkIf cfg.enable {
+  config = lib.mkIf cfg.enable {
     system.requiredKernelConfig = with config.lib.kernelConfig; [
       (isYes "DEBUG")
     ];
diff --git a/nixos/modules/programs/thefuck.nix b/nixos/modules/programs/thefuck.nix
index ba2e39c013aeb..0e65352a1f216 100644
--- a/nixos/modules/programs/thefuck.nix
+++ b/nixos/modules/programs/thefuck.nix
@@ -1,7 +1,5 @@
 { config, pkgs, lib, ... }:
 
-with lib;
-
 let
   prg = config.programs;
   cfg = prg.thefuck;
@@ -16,11 +14,11 @@ in
   {
     options = {
       programs.thefuck = {
-        enable = mkEnableOption "thefuck, an app which corrects your previous console command";
+        enable = lib.mkEnableOption "thefuck, an app which corrects your previous console command";
 
-        alias = mkOption {
+        alias = lib.mkOption {
           default = "fuck";
-          type = types.str;
+          type = lib.types.str;
 
           description = ''
             `thefuck` needs an alias to be configured.
@@ -30,11 +28,11 @@ in
       };
     };
 
-    config = mkIf cfg.enable {
+    config = lib.mkIf cfg.enable {
       environment.systemPackages = with pkgs; [ thefuck ];
 
       programs.bash.interactiveShellInit = bashAndZshInitScript;
-      programs.zsh.interactiveShellInit = mkIf prg.zsh.enable bashAndZshInitScript;
-      programs.fish.interactiveShellInit = mkIf prg.fish.enable fishInitScript;
+      programs.zsh.interactiveShellInit = lib.mkIf prg.zsh.enable bashAndZshInitScript;
+      programs.fish.interactiveShellInit = lib.mkIf prg.fish.enable fishInitScript;
     };
   }
diff --git a/nixos/modules/programs/thunar.nix b/nixos/modules/programs/thunar.nix
index 5ea2982dd93cf..76fcc9d8298f4 100644
--- a/nixos/modules/programs/thunar.nix
+++ b/nixos/modules/programs/thunar.nix
@@ -1,29 +1,27 @@
 { config, lib, pkgs, ... }:
 
-with lib;
-
 let cfg = config.programs.thunar;
 
 in {
   meta = {
-    maintainers = teams.xfce.members;
+    maintainers = lib.teams.xfce.members;
   };
 
   options = {
     programs.thunar = {
-      enable = mkEnableOption "Thunar, the Xfce file manager";
+      enable = lib.mkEnableOption "Thunar, the Xfce file manager";
 
-      plugins = mkOption {
+      plugins = lib.mkOption {
         default = [];
-        type = types.listOf types.package;
+        type = lib.types.listOf lib.types.package;
         description = "List of thunar plugins to install.";
-        example = literalExpression "with pkgs.xfce; [ thunar-archive-plugin thunar-volman ]";
+        example = lib.literalExpression "with pkgs.xfce; [ thunar-archive-plugin thunar-volman ]";
       };
 
     };
   };
 
-  config = mkIf cfg.enable (
+  config = lib.mkIf cfg.enable (
     let package = pkgs.xfce.thunar.override { thunarPlugins = cfg.plugins; };
 
     in {
diff --git a/nixos/modules/programs/traceroute.nix b/nixos/modules/programs/traceroute.nix
index 6e04057ac5034..0864dbe79db6b 100644
--- a/nixos/modules/programs/traceroute.nix
+++ b/nixos/modules/programs/traceroute.nix
@@ -1,14 +1,12 @@
 { config, lib, pkgs, ... }:
 
-with lib;
-
 let
   cfg = config.programs.traceroute;
 in {
   options = {
     programs.traceroute = {
-      enable = mkOption {
-        type = types.bool;
+      enable = lib.mkOption {
+        type = lib.types.bool;
         default = false;
         description = ''
           Whether to configure a setcap wrapper for traceroute.
@@ -17,7 +15,7 @@ in {
     };
   };
 
-  config = mkIf cfg.enable {
+  config = lib.mkIf cfg.enable {
     security.wrappers.traceroute = {
       owner = "root";
       group = "root";
diff --git a/nixos/modules/programs/turbovnc.nix b/nixos/modules/programs/turbovnc.nix
index fbb3a7bf22e99..c28b7f7d79910 100644
--- a/nixos/modules/programs/turbovnc.nix
+++ b/nixos/modules/programs/turbovnc.nix
@@ -2,8 +2,6 @@
 
 { config, lib, pkgs, ... }:
 
-with lib;
-
 let
   cfg = config.programs.turbovnc;
 in
@@ -12,8 +10,8 @@ in
 
     programs.turbovnc = {
 
-      ensureHeadlessSoftwareOpenGL = mkOption {
-        type = types.bool;
+      ensureHeadlessSoftwareOpenGL = lib.mkOption {
+        type = lib.types.bool;
         default = false;
         description = ''
           Whether to set up NixOS such that TurboVNC's built-in software OpenGL
@@ -36,7 +34,7 @@ in
 
   };
 
-  config = mkIf cfg.ensureHeadlessSoftwareOpenGL {
+  config = lib.mkIf cfg.ensureHeadlessSoftwareOpenGL {
 
     # TurboVNC has builtin support for Mesa llvmpipe's `swrast`
     # software rendering to implement GLX (OpenGL on Xorg).
diff --git a/nixos/modules/programs/udevil.nix b/nixos/modules/programs/udevil.nix
index 44b9dd9234b38..e4c0daea72c1b 100644
--- a/nixos/modules/programs/udevil.nix
+++ b/nixos/modules/programs/udevil.nix
@@ -1,14 +1,12 @@
 { config, lib, pkgs, ... }:
 
-with lib;
-
 let
   cfg = config.programs.udevil;
 
 in {
-  options.programs.udevil.enable = mkEnableOption "udevil, to mount filesystems without password";
+  options.programs.udevil.enable = lib.mkEnableOption "udevil, to mount filesystems without password";
 
-  config = mkIf cfg.enable {
+  config = lib.mkIf cfg.enable {
     security.wrappers.udevil =
       { setuid = true;
         owner = "root";
diff --git a/nixos/modules/programs/usbtop.nix b/nixos/modules/programs/usbtop.nix
index 4f13ce5f6262d..8b77b2bf51c43 100644
--- a/nixos/modules/programs/usbtop.nix
+++ b/nixos/modules/programs/usbtop.nix
@@ -1,15 +1,13 @@
 { config, pkgs, lib, ... }:
 
-with lib;
-
 let
   cfg = config.programs.usbtop;
 in {
   options = {
-    programs.usbtop.enable = mkEnableOption "usbtop and required kernel module, to show estimated USB bandwidth";
+    programs.usbtop.enable = lib.mkEnableOption "usbtop and required kernel module, to show estimated USB bandwidth";
   };
 
-  config = mkIf cfg.enable {
+  config = lib.mkIf cfg.enable {
     environment.systemPackages = with pkgs; [
       usbtop
     ];
diff --git a/nixos/modules/programs/vim.nix b/nixos/modules/programs/vim.nix
index eb3499fd243f5..8232340ddebbf 100644
--- a/nixos/modules/programs/vim.nix
+++ b/nixos/modules/programs/vim.nix
@@ -1,13 +1,11 @@
 { config, lib, pkgs, ... }:
 
-with lib;
-
 let
   cfg = config.programs.vim;
 in {
   options.programs.vim = {
-    defaultEditor = mkOption {
-      type = types.bool;
+    defaultEditor = lib.mkOption {
+      type = lib.types.bool;
       default = false;
       description = ''
         When enabled, installs vim and configures vim to be the default editor
@@ -15,13 +13,13 @@ in {
       '';
     };
 
-    package = mkPackageOption pkgs "vim" {
+    package = lib.mkPackageOption pkgs "vim" {
       example = "vim-full";
     };
   };
 
-  config = mkIf cfg.defaultEditor {
+  config = lib.mkIf cfg.defaultEditor {
     environment.systemPackages = [ cfg.package ];
-    environment.variables = { EDITOR = mkOverride 900 "vim"; };
+    environment.variables = { EDITOR = lib.mkOverride 900 "vim"; };
   };
 }
diff --git a/nixos/modules/programs/virt-manager.nix b/nixos/modules/programs/virt-manager.nix
index 095db7586a034..9b5fa22268ae9 100644
--- a/nixos/modules/programs/virt-manager.nix
+++ b/nixos/modules/programs/virt-manager.nix
@@ -2,15 +2,27 @@
 
 let
   cfg = config.programs.virt-manager;
-in {
+in
+{
   options.programs.virt-manager = {
     enable = lib.mkEnableOption "virt-manager, an UI for managing virtual machines in libvirt";
 
-    package = lib.mkPackageOption pkgs "virt-manager" {};
+    package = lib.mkPackageOption pkgs "virt-manager" { };
   };
 
   config = lib.mkIf cfg.enable {
     environment.systemPackages = [ cfg.package ];
-    programs.dconf.enable = true;
+    programs.dconf = {
+      profiles.user.databases = [
+        {
+          settings = {
+            "org/virt-manager/virt-manager/connections" = {
+              autoconnect = [ "qemu:///system" ];
+              uris = [ "qemu:///system" ];
+            };
+          };
+        }
+      ];
+    };
   };
 }
diff --git a/nixos/modules/programs/wavemon.nix b/nixos/modules/programs/wavemon.nix
index e5ccacba75d4a..86bc7cc097954 100644
--- a/nixos/modules/programs/wavemon.nix
+++ b/nixos/modules/programs/wavemon.nix
@@ -1,14 +1,12 @@
 { config, lib, pkgs, ... }:
 
-with lib;
-
 let
   cfg = config.programs.wavemon;
 in {
   options = {
     programs.wavemon = {
-      enable = mkOption {
-        type = types.bool;
+      enable = lib.mkOption {
+        type = lib.types.bool;
         default = false;
         description = ''
           Whether to add wavemon to the global environment and configure a
@@ -18,7 +16,7 @@ in {
     };
   };
 
-  config = mkIf cfg.enable {
+  config = lib.mkIf cfg.enable {
     environment.systemPackages = with pkgs; [ wavemon ];
     security.wrappers.wavemon = {
       owner = "root";
diff --git a/nixos/modules/programs/wayland/hyprland.nix b/nixos/modules/programs/wayland/hyprland.nix
index 5891ff25e4375..c963429f2e2a9 100644
--- a/nixos/modules/programs/wayland/hyprland.nix
+++ b/nixos/modules/programs/wayland/hyprland.nix
@@ -3,7 +3,7 @@
 , pkgs
 , ...
 }:
-with lib; let
+let
   cfg = config.programs.hyprland;
 
   finalPortalPackage = cfg.portalPackage.override {
@@ -12,7 +12,7 @@ with lib; let
 in
 {
   options.programs.hyprland = {
-    enable = mkEnableOption null // {
+    enable = lib.mkEnableOption null // {
       description = ''
         Whether to enable Hyprland, the dynamic tiling Wayland compositor that doesn't sacrifice on its looks.
 
@@ -23,26 +23,26 @@ in
       '';
     };
 
-    package = mkPackageOption pkgs "hyprland" { };
+    package = lib.mkPackageOption pkgs "hyprland" { };
 
-    finalPackage = mkOption {
-      type = types.package;
+    finalPackage = lib.mkOption {
+      type = lib.types.package;
       readOnly = true;
       default = cfg.package.override {
         enableXWayland = cfg.xwayland.enable;
       };
-      defaultText = literalExpression
+      defaultText = lib.literalExpression
         "`programs.hyprland.package` with applied configuration";
       description = ''
         The Hyprland package after applying configuration.
       '';
     };
 
-    portalPackage = mkPackageOption pkgs "xdg-desktop-portal-hyprland" { };
+    portalPackage = lib.mkPackageOption pkgs "xdg-desktop-portal-hyprland" { };
 
-    xwayland.enable = mkEnableOption ("XWayland") // { default = true; };
+    xwayland.enable = lib.mkEnableOption ("XWayland") // { default = true; };
 
-    systemd.setPath.enable = mkEnableOption null // {
+    systemd.setPath.enable = lib.mkEnableOption null // {
       default = true;
       example = false;
       description = ''
@@ -53,15 +53,15 @@ in
     };
   };
 
-  config = mkIf cfg.enable {
+  config = lib.mkIf cfg.enable {
     environment.systemPackages = [ cfg.finalPackage ];
 
-    fonts.enableDefaultPackages = mkDefault true;
-    hardware.opengl.enable = mkDefault true;
+    fonts.enableDefaultPackages = lib.mkDefault true;
+    hardware.opengl.enable = lib.mkDefault true;
 
     programs = {
-      dconf.enable = mkDefault true;
-      xwayland.enable = mkDefault cfg.xwayland.enable;
+      dconf.enable = lib.mkDefault true;
+      xwayland.enable = lib.mkDefault cfg.xwayland.enable;
     };
 
     security.polkit.enable = true;
@@ -69,28 +69,28 @@ in
     services.displayManager.sessionPackages = [ cfg.finalPackage ];
 
     xdg.portal = {
-      enable = mkDefault true;
+      enable = lib.mkDefault true;
       extraPortals = [ finalPortalPackage ];
-      configPackages = mkDefault [ cfg.finalPackage ];
+      configPackages = lib.mkDefault [ cfg.finalPackage ];
     };
 
-    systemd = mkIf cfg.systemd.setPath.enable {
+    systemd = lib.mkIf cfg.systemd.setPath.enable {
       user.extraConfig = ''
         DefaultEnvironment="PATH=$PATH:/run/current-system/sw/bin:/etc/profiles/per-user/%u/bin:/run/wrappers/bin"
       '';
     };
   };
 
-  imports = with lib; [
-    (mkRemovedOptionModule
+  imports = [
+    (lib.mkRemovedOptionModule
       [ "programs" "hyprland" "xwayland" "hidpi" ]
       "XWayland patches are deprecated. Refer to https://wiki.hyprland.org/Configuring/XWayland"
     )
-    (mkRemovedOptionModule
+    (lib.mkRemovedOptionModule
       [ "programs" "hyprland" "enableNvidiaPatches" ]
       "Nvidia patches are no longer needed"
     )
-    (mkRemovedOptionModule
+    (lib.mkRemovedOptionModule
       [ "programs" "hyprland" "nvidiaPatches" ]
       "Nvidia patches are no longer needed"
     )
diff --git a/nixos/modules/programs/wayland/river.nix b/nixos/modules/programs/wayland/river.nix
index d0e309646b0ef..6f8bafb155064 100644
--- a/nixos/modules/programs/wayland/river.nix
+++ b/nixos/modules/programs/wayland/river.nix
@@ -4,13 +4,13 @@
   lib,
   ...
 }:
-with lib; let
+let
   cfg = config.programs.river;
 in {
   options.programs.river = {
-    enable = mkEnableOption "river, a dynamic tiling Wayland compositor";
+    enable = lib.mkEnableOption "river, a dynamic tiling Wayland compositor";
 
-    package = mkPackageOption pkgs "river" {
+    package = lib.mkPackageOption pkgs "river" {
       nullable = true;
       extraDescription = ''
         Set to `null` to not add any River package to your path.
@@ -18,17 +18,17 @@ in {
       '';
     };
 
-    extraPackages = mkOption {
-      type = with types; listOf package;
+    extraPackages = lib.mkOption {
+      type = with lib.types; listOf package;
       default = with pkgs; [
         swaylock
         foot
         dmenu
       ];
-      defaultText = literalExpression ''
+      defaultText = lib.literalExpression ''
         with pkgs; [ swaylock foot dmenu ];
       '';
-      example = literalExpression ''
+      example = lib.literalExpression ''
         with pkgs; [
           termite rofi light
         ]
@@ -42,15 +42,15 @@ in {
   };
 
   config =
-    mkIf cfg.enable (mkMerge [
+    lib.mkIf cfg.enable (lib.mkMerge [
       {
-        environment.systemPackages = optional (cfg.package != null) cfg.package ++ cfg.extraPackages;
+        environment.systemPackages = lib.optional (cfg.package != null) cfg.package ++ cfg.extraPackages;
 
         # To make a river session available if a display manager like SDDM is enabled:
-        services.displayManager.sessionPackages = optionals (cfg.package != null) [ cfg.package ];
+        services.displayManager.sessionPackages = lib.optionals (cfg.package != null) [ cfg.package ];
 
         # https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1050913
-        xdg.portal.config.river.default = mkDefault [ "wlr" "gtk" ];
+        xdg.portal.config.river.default = lib.mkDefault [ "wlr" "gtk" ];
       }
       (import ./wayland-session.nix { inherit lib pkgs; })
     ]);
diff --git a/nixos/modules/programs/wayland/sway.nix b/nixos/modules/programs/wayland/sway.nix
index 348e1db7cdc1c..cec634b6b0338 100644
--- a/nixos/modules/programs/wayland/sway.nix
+++ b/nixos/modules/programs/wayland/sway.nix
@@ -1,15 +1,13 @@
 { config, pkgs, lib, ... }:
 
-with lib;
-
 let
   cfg = config.programs.sway;
 
-  wrapperOptions = types.submodule {
+  wrapperOptions = lib.types.submodule {
     options =
       let
-        mkWrapperFeature  = default: description: mkOption {
-          type = types.bool;
+        mkWrapperFeature  = default: description: lib.mkOption {
+          type = lib.types.bool;
           inherit default;
           example = !default;
           description = "Whether to make use of the ${description}";
@@ -50,18 +48,18 @@ let
       };
 in {
   options.programs.sway = {
-    enable = mkEnableOption ''
+    enable = lib.mkEnableOption ''
       Sway, the i3-compatible tiling Wayland compositor. You can manually launch
       Sway by executing "exec sway" on a TTY. Copy /etc/sway/config to
       ~/.config/sway/config to modify the default configuration. See
       <https://github.com/swaywm/sway/wiki> and
       "man 5 sway" for more information'';
 
-    package = mkOption {
-      type = with types; nullOr package;
+    package = lib.mkOption {
+      type = with lib.types; nullOr package;
       default = pkgs.sway;
       apply = p: if p == null then null else genFinalPackage p;
-      defaultText = literalExpression "pkgs.sway";
+      defaultText = lib.literalExpression "pkgs.sway";
       description = ''
         Sway package to use. If the package does not contain the override arguments
         `extraSessionCommands`, `extraOptions`, `withBaseWrapper`, `withGtkWrapper`,
@@ -72,7 +70,7 @@ in {
       '';
     };
 
-    wrapperFeatures = mkOption {
+    wrapperFeatures = lib.mkOption {
       type = wrapperOptions;
       default = { };
       example = { gtk = true; };
@@ -81,8 +79,8 @@ in {
       '';
     };
 
-    extraSessionCommands = mkOption {
-      type = types.lines;
+    extraSessionCommands = lib.mkOption {
+      type = lib.types.lines;
       default = "";
       example = ''
         # SDL:
@@ -102,8 +100,8 @@ in {
       '';
     };
 
-    extraOptions = mkOption {
-      type = types.listOf types.str;
+    extraOptions = lib.mkOption {
+      type = lib.types.listOf lib.types.str;
       default = [];
       example = [
         "--verbose"
@@ -116,15 +114,15 @@ in {
       '';
     };
 
-    extraPackages = mkOption {
-      type = with types; listOf package;
+    extraPackages = lib.mkOption {
+      type = with lib.types; listOf package;
       default = with pkgs; [
         swaylock swayidle foot dmenu wmenu
       ];
-      defaultText = literalExpression ''
+      defaultText = lib.literalExpression ''
         with pkgs; [ swaylock swayidle foot dmenu wmenu ];
       '';
-      example = literalExpression ''
+      example = lib.literalExpression ''
         with pkgs; [
           i3status i3status-rust
           termite rofi light
@@ -140,8 +138,8 @@ in {
 
   };
 
-  config = mkIf cfg.enable
-    (mkMerge [
+  config = lib.mkIf cfg.enable
+    (lib.mkMerge [
       {
         assertions = [
           {
@@ -154,27 +152,27 @@ in {
         ];
 
         environment = {
-          systemPackages = optional (cfg.package != null) cfg.package ++ cfg.extraPackages;
+          systemPackages = lib.optional (cfg.package != null) cfg.package ++ cfg.extraPackages;
           # Needed for the default wallpaper:
-          pathsToLink = optionals (cfg.package != null) [ "/share/backgrounds/sway" ];
+          pathsToLink = lib.optionals (cfg.package != null) [ "/share/backgrounds/sway" ];
           etc = {
             "sway/config.d/nixos.conf".source = pkgs.writeText "nixos.conf" ''
               # Import the most important environment variables into the D-Bus and systemd
               # user environments (e.g. required for screen sharing and Pinentry prompts):
               exec dbus-update-activation-environment --systemd DISPLAY WAYLAND_DISPLAY SWAYSOCK XDG_CURRENT_DESKTOP
             '';
-          } // optionalAttrs (cfg.package != null) {
-            "sway/config".source = mkOptionDefault "${cfg.package}/etc/sway/config";
+          } // lib.optionalAttrs (cfg.package != null) {
+            "sway/config".source = lib.mkOptionDefault "${cfg.package}/etc/sway/config";
           };
         };
 
         programs.gnupg.agent.pinentryPackage = lib.mkDefault pkgs.pinentry-gnome3;
 
         # https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1050913
-        xdg.portal.config.sway.default = mkDefault [ "wlr" "gtk" ];
+        xdg.portal.config.sway.default = lib.mkDefault [ "wlr" "gtk" ];
 
         # To make a Sway session available if a display manager like SDDM is enabled:
-        services.displayManager.sessionPackages = optionals (cfg.package != null) [ cfg.package ]; }
+        services.displayManager.sessionPackages = lib.optionals (cfg.package != null) [ cfg.package ]; }
       (import ./wayland-session.nix { inherit lib pkgs; })
     ]);
 
diff --git a/nixos/modules/programs/wayland/waybar.nix b/nixos/modules/programs/wayland/waybar.nix
index ffe889504cd39..ab811994be073 100644
--- a/nixos/modules/programs/wayland/waybar.nix
+++ b/nixos/modules/programs/wayland/waybar.nix
@@ -1,17 +1,15 @@
 { lib, pkgs, config, ... }:
 
-with lib;
-
 let
   cfg = config.programs.waybar;
 in
 {
   options.programs.waybar = {
-    enable = mkEnableOption "waybar, a highly customizable Wayland bar for Sway and Wlroots based compositors";
-    package = mkPackageOption pkgs "waybar" { };
+    enable = lib.mkEnableOption "waybar, a highly customizable Wayland bar for Sway and Wlroots based compositors";
+    package = lib.mkPackageOption pkgs "waybar" { };
   };
 
-  config = mkIf cfg.enable {
+  config = lib.mkIf cfg.enable {
     environment.systemPackages = [ cfg.package ];
     systemd.user.services.waybar = {
       description = "Waybar as systemd service";
@@ -21,5 +19,5 @@ in
     };
   };
 
-  meta.maintainers = [ maintainers.FlorianFranzen ];
+  meta.maintainers = [ lib.maintainers.FlorianFranzen ];
 }
diff --git a/nixos/modules/programs/wayland/wayland-session.nix b/nixos/modules/programs/wayland/wayland-session.nix
index da117ceae0ad6..47ee0788e0f38 100644
--- a/nixos/modules/programs/wayland/wayland-session.nix
+++ b/nixos/modules/programs/wayland/wayland-session.nix
@@ -1,19 +1,19 @@
-{ lib, pkgs, ... }: with lib; {
+{ lib, pkgs, ... }: {
     security = {
       polkit.enable = true;
       pam.services.swaylock = {};
     };
 
-    hardware.opengl.enable = mkDefault true;
-    fonts.enableDefaultPackages = mkDefault true;
+    hardware.opengl.enable = lib.mkDefault true;
+    fonts.enableDefaultPackages = lib.mkDefault true;
 
     programs = {
-      dconf.enable = mkDefault true;
-      xwayland.enable = mkDefault true;
+      dconf.enable = lib.mkDefault true;
+      xwayland.enable = lib.mkDefault true;
     };
 
     xdg.portal = {
-      enable = mkDefault true;
+      enable = lib.mkDefault true;
 
       extraPortals = [
         # For screen sharing
diff --git a/nixos/modules/programs/weylus.nix b/nixos/modules/programs/weylus.nix
index a47dccb95cd98..d76e2f81b2c94 100644
--- a/nixos/modules/programs/weylus.nix
+++ b/nixos/modules/programs/weylus.nix
@@ -1,15 +1,13 @@
 { config, lib, pkgs, ... }:
 
-with lib;
-
 let
   cfg = config.programs.weylus;
 in
 {
-  options.programs.weylus = with types; {
-    enable = mkEnableOption "weylus, which turns your smart phone into a graphic tablet/touch screen for your computer";
+  options.programs.weylus = with lib.types; {
+    enable = lib.mkEnableOption "weylus, which turns your smart phone into a graphic tablet/touch screen for your computer";
 
-    openFirewall = mkOption {
+    openFirewall = lib.mkOption {
       type = bool;
       default = false;
       description = ''
@@ -17,7 +15,7 @@ in
       '';
     };
 
-     users = mkOption {
+     users = lib.mkOption {
       type = listOf str;
       default = [ ];
       description = ''
@@ -26,10 +24,10 @@ in
       '';
     };
 
-    package = mkPackageOption pkgs "weylus" { };
+    package = lib.mkPackageOption pkgs "weylus" { };
   };
-  config = mkIf cfg.enable {
-    networking.firewall = mkIf cfg.openFirewall {
+  config = lib.mkIf cfg.enable {
+    networking.firewall = lib.mkIf cfg.openFirewall {
       allowedTCPPorts = [ 1701 9001 ];
     };
 
diff --git a/nixos/modules/programs/wireshark.nix b/nixos/modules/programs/wireshark.nix
index 2d947154e8224..f5673e5940fea 100644
--- a/nixos/modules/programs/wireshark.nix
+++ b/nixos/modules/programs/wireshark.nix
@@ -1,28 +1,26 @@
 { config, lib, pkgs, ... }:
 
-with lib;
-
 let
   cfg = config.programs.wireshark;
   wireshark = cfg.package;
 in {
   options = {
     programs.wireshark = {
-      enable = mkOption {
-        type = types.bool;
+      enable = lib.mkOption {
+        type = lib.types.bool;
         default = false;
         description = ''
           Whether to add Wireshark to the global environment and configure a
           setcap wrapper for 'dumpcap' for users in the 'wireshark' group.
         '';
       };
-      package = mkPackageOption pkgs "wireshark-cli" {
+      package = lib.mkPackageOption pkgs "wireshark-cli" {
         example = "wireshark";
       };
     };
   };
 
-  config = mkIf cfg.enable {
+  config = lib.mkIf cfg.enable {
     environment.systemPackages = [ wireshark ];
     users.groups.wireshark = {};
 
diff --git a/nixos/modules/programs/xastir.nix b/nixos/modules/programs/xastir.nix
index d9c687289ec2c..96201eb5455d0 100644
--- a/nixos/modules/programs/xastir.nix
+++ b/nixos/modules/programs/xastir.nix
@@ -1,17 +1,15 @@
 { config, lib, pkgs, ... }:
 
-with lib;
-
 let
   cfg = config.programs.xastir;
 in {
-  meta.maintainers = with maintainers; [ melling ];
+  meta.maintainers = with lib.maintainers; [ melling ];
 
   options.programs.xastir = {
-    enable = mkEnableOption "Xastir Graphical APRS client";
+    enable = lib.mkEnableOption "Xastir Graphical APRS client";
   };
 
-  config = mkIf cfg.enable {
+  config = lib.mkIf cfg.enable {
     environment.systemPackages = with pkgs; [ xastir ];
     security.wrappers.xastir = {
       source = "${pkgs.xastir}/bin/xastir";
diff --git a/nixos/modules/programs/xfconf.nix b/nixos/modules/programs/xfconf.nix
index 8e854b40e513d..f2fda3b692d37 100644
--- a/nixos/modules/programs/xfconf.nix
+++ b/nixos/modules/programs/xfconf.nix
@@ -1,21 +1,19 @@
 { config, lib, pkgs, ... }:
 
-with lib;
-
 let cfg = config.programs.xfconf;
 
 in {
   meta = {
-    maintainers = teams.xfce.members;
+    maintainers = lib.teams.xfce.members;
   };
 
   options = {
     programs.xfconf = {
-      enable = mkEnableOption "Xfconf, the Xfce configuration storage system";
+      enable = lib.mkEnableOption "Xfconf, the Xfce configuration storage system";
     };
   };
 
-  config = mkIf cfg.enable {
+  config = lib.mkIf cfg.enable {
     environment.systemPackages = [
       pkgs.xfce.xfconf
     ];
diff --git a/nixos/modules/programs/xfs_quota.nix b/nixos/modules/programs/xfs_quota.nix
index 8f70cc2d94163..5ca05f4dc297e 100644
--- a/nixos/modules/programs/xfs_quota.nix
+++ b/nixos/modules/programs/xfs_quota.nix
@@ -2,15 +2,13 @@
 
 { config, lib, pkgs, ... }:
 
-with lib;
-
 let
 
   cfg = config.programs.xfs_quota;
 
-  limitOptions = opts: concatStringsSep " " [
-    (optionalString (opts.sizeSoftLimit != null) "bsoft=${opts.sizeSoftLimit}")
-    (optionalString (opts.sizeHardLimit != null) "bhard=${opts.sizeHardLimit}")
+  limitOptions = opts: builtins.concatStringsSep " " [
+    (lib.optionalString (opts.sizeSoftLimit != null) "bsoft=${opts.sizeSoftLimit}")
+    (lib.optionalString (opts.sizeHardLimit != null) "bhard=${opts.sizeHardLimit}")
   ];
 
 in
@@ -22,35 +20,35 @@ in
   options = {
 
     programs.xfs_quota = {
-      projects = mkOption {
+      projects = lib.mkOption {
         default = {};
-        type = types.attrsOf (types.submodule {
+        type = lib.types.attrsOf (lib.types.submodule {
           options = {
-            id = mkOption {
-              type = types.int;
+            id = lib.mkOption {
+              type = lib.types.int;
               description = "Project ID.";
             };
 
-            fileSystem = mkOption {
-              type = types.str;
+            fileSystem = lib.mkOption {
+              type = lib.types.str;
               description = "XFS filesystem hosting the xfs_quota project.";
               default = "/";
             };
 
-            path = mkOption {
-              type = types.str;
+            path = lib.mkOption {
+              type = lib.types.str;
               description = "Project directory.";
             };
 
-            sizeSoftLimit = mkOption {
-              type = types.nullOr types.str;
+            sizeSoftLimit = lib.mkOption {
+              type = lib.types.nullOr lib.types.str;
               default = null;
               example = "30g";
               description = "Soft limit of the project size";
             };
 
-            sizeHardLimit = mkOption {
-              type = types.nullOr types.str;
+            sizeHardLimit = lib.mkOption {
+              type = lib.types.nullOr lib.types.str;
               default = null;
               example = "50g";
               description = "Hard limit of the project size.";
@@ -75,18 +73,18 @@ in
 
   ###### implementation
 
-  config = mkIf (cfg.projects != {}) {
+  config = lib.mkIf (cfg.projects != {}) {
 
     environment.etc.projects.source = pkgs.writeText "etc-project"
-      (concatStringsSep "\n" (mapAttrsToList
-        (name: opts: "${toString opts.id}:${opts.path}") cfg.projects));
+      (builtins.concatStringsSep "\n" (lib.mapAttrsToList
+        (name: opts: "${builtins.toString opts.id}:${opts.path}") cfg.projects));
 
     environment.etc.projid.source = pkgs.writeText "etc-projid"
-      (concatStringsSep "\n" (mapAttrsToList
-        (name: opts: "${name}:${toString opts.id}") cfg.projects));
+      (builtins.concatStringsSep "\n" (lib.mapAttrsToList
+        (name: opts: "${name}:${builtins.toString opts.id}") cfg.projects));
 
-    systemd.services = mapAttrs' (name: opts:
-      nameValuePair "xfs_quota-${name}" {
+    systemd.services = lib.mapAttrs' (name: opts:
+      lib.nameValuePair "xfs_quota-${name}" {
         description = "Setup xfs_quota for project ${name}";
         script = ''
           ${pkgs.xfsprogs.bin}/bin/xfs_quota -x -c 'project -s ${name}' ${opts.fileSystem}
@@ -94,7 +92,7 @@ in
         '';
 
         wantedBy = [ "multi-user.target" ];
-        after = [ ((replaceStrings [ "/" ] [ "-" ] opts.fileSystem) + ".mount") ];
+        after = [ ((builtins.replaceStrings [ "/" ] [ "-" ] opts.fileSystem) + ".mount") ];
 
         restartTriggers = [ config.environment.etc.projects.source ];
 
diff --git a/nixos/modules/programs/xonsh.nix b/nixos/modules/programs/xonsh.nix
index fefe6b456c960..eed5152ba69a5 100644
--- a/nixos/modules/programs/xonsh.nix
+++ b/nixos/modules/programs/xonsh.nix
@@ -2,8 +2,6 @@
 
 { config, lib, pkgs, ... }:
 
-with lib;
-
 let
 
   cfg = config.programs.xonsh;
@@ -16,29 +14,29 @@ in
 
     programs.xonsh = {
 
-      enable = mkOption {
+      enable = lib.mkOption {
         default = false;
         description = ''
           Whether to configure xonsh as an interactive shell.
         '';
-        type = types.bool;
+        type = lib.types.bool;
       };
 
-      package = mkPackageOption pkgs "xonsh" {
+      package = lib.mkPackageOption pkgs "xonsh" {
         example = "xonsh.override { extraPackages = ps: [ ps.requests ]; }";
       };
 
-      config = mkOption {
+      config = lib.mkOption {
         default = "";
         description = "Control file to customize your shell behavior.";
-        type = types.lines;
+        type = lib.types.lines;
       };
 
     };
 
   };
 
-  config = mkIf cfg.enable {
+  config = lib.mkIf cfg.enable {
 
     environment.etc."xonsh/xonshrc".text = ''
       # /etc/xonsh/xonshrc: DO NOT EDIT -- this file has been generated automatically.
diff --git a/nixos/modules/programs/xss-lock.nix b/nixos/modules/programs/xss-lock.nix
index 1bb73905599f8..b818c52e1442d 100644
--- a/nixos/modules/programs/xss-lock.nix
+++ b/nixos/modules/programs/xss-lock.nix
@@ -1,26 +1,24 @@
 { config, pkgs, lib, ... }:
 
-with lib;
-
 let
   cfg = config.programs.xss-lock;
 in
 {
   options.programs.xss-lock = {
-    enable = mkEnableOption "xss-lock";
+    enable = lib.mkEnableOption "xss-lock";
 
-    lockerCommand = mkOption {
+    lockerCommand = lib.mkOption {
       default = "${pkgs.i3lock}/bin/i3lock";
-      defaultText = literalExpression ''"''${pkgs.i3lock}/bin/i3lock"'';
-      example = literalExpression ''"''${pkgs.i3lock-fancy}/bin/i3lock-fancy"'';
-      type = types.separatedString " ";
+      defaultText = lib.literalExpression ''"''${pkgs.i3lock}/bin/i3lock"'';
+      example = lib.literalExpression ''"''${pkgs.i3lock-fancy}/bin/i3lock-fancy"'';
+      type = lib.types.separatedString " ";
       description = "Locker to be used with xsslock";
     };
 
-    extraOptions = mkOption {
+    extraOptions = lib.mkOption {
       default = [ ];
       example = [ "--ignore-sleep" ];
-      type = types.listOf types.str;
+      type = lib.types.listOf lib.types.str;
       description = ''
         Additional command-line arguments to pass to
         {command}`xss-lock`.
@@ -28,19 +26,24 @@ in
     };
   };
 
-  config = mkIf cfg.enable {
+  config = lib.mkIf cfg.enable {
     systemd.user.services.xss-lock = {
       description = "XSS Lock Daemon";
       wantedBy = [ "graphical-session.target" ];
       partOf = [ "graphical-session.target" ];
-      serviceConfig.ExecStart = with lib;
-        strings.concatStringsSep " " ([
+      serviceConfig.ExecStart =
+        builtins.concatStringsSep " " ([
             "${pkgs.xss-lock}/bin/xss-lock" "--session \${XDG_SESSION_ID}"
-          ] ++ (map escapeShellArg cfg.extraOptions) ++ [
+          ] ++ (builtins.map lib.escapeShellArg cfg.extraOptions) ++ [
             "--"
             cfg.lockerCommand
         ]);
       serviceConfig.Restart = "always";
     };
+
+    warnings = lib.mkIf (config.services.xserver.displayManager.startx.enable) [
+      "xss-lock service only works if a displayManager is set; it doesn't work when services.xserver.displayManager.startx.enable = true"
+    ];
+
   };
 }
diff --git a/nixos/modules/programs/xwayland.nix b/nixos/modules/programs/xwayland.nix
index 3a8080fa4c4d8..3df3dbf3783f3 100644
--- a/nixos/modules/programs/xwayland.nix
+++ b/nixos/modules/programs/xwayland.nix
@@ -1,7 +1,5 @@
 { config, lib, pkgs, ... }:
 
-with lib;
-
 let
   cfg = config.programs.xwayland;
 
@@ -10,13 +8,13 @@ in
 {
   options.programs.xwayland = {
 
-    enable = mkEnableOption "Xwayland (an X server for interfacing X11 apps with the Wayland protocol)";
+    enable = lib.mkEnableOption "Xwayland (an X server for interfacing X11 apps with the Wayland protocol)";
 
-    defaultFontPath = mkOption {
-      type = types.str;
-      default = optionalString config.fonts.fontDir.enable
+    defaultFontPath = lib.mkOption {
+      type = lib.types.str;
+      default = lib.optionalString config.fonts.fontDir.enable
         "/run/current-system/sw/share/X11/fonts";
-      defaultText = literalExpression ''
+      defaultText = lib.literalExpression ''
         optionalString config.fonts.fontDir.enable "/run/current-system/sw/share/X11/fonts"
       '';
       description = ''
@@ -24,12 +22,12 @@ in
       '';
     };
 
-    package = mkOption {
-      type = types.path;
+    package = lib.mkOption {
+      type = lib.types.path;
       default = pkgs.xwayland.override (oldArgs: {
         inherit (cfg) defaultFontPath;
       });
-      defaultText = literalExpression ''
+      defaultText = lib.literalExpression ''
         pkgs.xwayland.override (oldArgs: {
           inherit (config.programs.xwayland) defaultFontPath;
         })
@@ -39,7 +37,7 @@ in
 
   };
 
-  config = mkIf cfg.enable {
+  config = lib.mkIf cfg.enable {
 
     # Needed by some applications for fonts and default settings
     environment.pathsToLink = [ "/share/X11" ];
diff --git a/nixos/modules/programs/yabar.nix b/nixos/modules/programs/yabar.nix
index 6e117506a2dc4..0457f8e76655b 100644
--- a/nixos/modules/programs/yabar.nix
+++ b/nixos/modules/programs/yabar.nix
@@ -1,18 +1,16 @@
 { lib, pkgs, config, ... }:
 
-with lib;
-
 let
   cfg = config.programs.yabar;
 
-  mapExtra = v: lib.concatStringsSep "\n" (mapAttrsToList (
-    key: val: "${key} = ${if (isString val) then "\"${val}\"" else "${builtins.toString val}"};"
+  mapExtra = v: lib.concatStringsSep "\n" (lib.mapAttrsToList (
+    key: val: "${key} = ${if (builtins.isString val) then "\"${val}\"" else "${builtins.toString val}"};"
   ) v);
 
-  listKeys = r: concatStringsSep "," (map (n: "\"${n}\"") (attrNames r));
+  listKeys = r: builtins.concatStringsSep "," (builtins.map (n: "\"${n}\"") (builtins.attrNames r));
 
   configFile = let
-    bars = mapAttrsToList (
+    bars = lib.mapAttrsToList (
       name: cfg: ''
         ${name}: {
           font: "${cfg.font}";
@@ -22,7 +20,7 @@ let
 
           block-list: [${listKeys cfg.indicators}]
 
-          ${concatStringsSep "\n" (mapAttrsToList (
+          ${builtins.concatStringsSep "\n" (lib.mapAttrsToList (
             name: cfg: ''
               ${name}: {
                 exec: "${cfg.exec}";
@@ -36,21 +34,21 @@ let
     ) cfg.bars;
   in pkgs.writeText "yabar.conf" ''
     bar-list = [${listKeys cfg.bars}];
-    ${concatStringsSep "\n" bars}
+    ${builtins.concatStringsSep "\n" bars}
   '';
 in
   {
     options.programs.yabar = {
-      enable = mkEnableOption "yabar, a status bar for X window managers";
+      enable = lib.mkEnableOption "yabar, a status bar for X window managers";
 
-      package = mkOption {
+      package = lib.mkOption {
         default = pkgs.yabar-unstable;
-        defaultText = literalExpression "pkgs.yabar-unstable";
-        example = literalExpression "pkgs.yabar";
-        type = types.package;
+        defaultText = lib.literalExpression "pkgs.yabar-unstable";
+        example = lib.literalExpression "pkgs.yabar";
+        type = lib.types.package;
 
         # `yabar-stable` segfaults under certain conditions.
-        apply = x: if x == pkgs.yabar-unstable then x else flip warn x ''
+        apply = x: if x == pkgs.yabar-unstable then x else lib.flip lib.warn x ''
           It's not recommended to use `yabar' with `programs.yabar', the (old) stable release
           tends to segfault under certain circumstances:
 
@@ -70,63 +68,63 @@ in
         '';
       };
 
-      bars = mkOption {
+      bars = lib.mkOption {
         default = {};
-        type = types.attrsOf(types.submodule {
+        type = lib.types.attrsOf(lib.types.submodule {
           options = {
-            font = mkOption {
+            font = lib.mkOption {
               default = "sans bold 9";
               example = "Droid Sans, FontAwesome Bold 9";
-              type = types.str;
+              type = lib.types.str;
 
               description = ''
                 The font that will be used to draw the status bar.
               '';
             };
 
-            position = mkOption {
+            position = lib.mkOption {
               default = "top";
               example = "bottom";
-              type = types.enum [ "top" "bottom" ];
+              type = lib.types.enum [ "top" "bottom" ];
 
               description = ''
                 The position where the bar will be rendered.
               '';
             };
 
-            extra = mkOption {
+            extra = lib.mkOption {
               default = {};
-              type = types.attrsOf types.str;
+              type = lib.types.attrsOf lib.types.str;
 
               description = ''
                 An attribute set which contains further attributes of a bar.
               '';
             };
 
-            indicators = mkOption {
+            indicators = lib.mkOption {
               default = {};
-              type = types.attrsOf(types.submodule {
-                options.exec = mkOption {
+              type = lib.types.attrsOf(lib.types.submodule {
+                options.exec = lib.mkOption {
                   example = "YABAR_DATE";
-                  type = types.str;
+                  type = lib.types.str;
                   description = ''
                      The type of the indicator to be executed.
                   '';
                 };
 
-                options.align = mkOption {
+                options.align = lib.mkOption {
                   default = "left";
                   example = "right";
-                  type = types.enum [ "left" "center" "right" ];
+                  type = lib.types.enum [ "left" "center" "right" ];
 
                   description = ''
                     Whether to align the indicator at the left or right of the bar.
                   '';
                 };
 
-                options.extra = mkOption {
+                options.extra = lib.mkOption {
                   default = {};
-                  type = types.attrsOf (types.either types.str types.int);
+                  type = lib.types.attrsOf (lib.types.either lib.types.str lib.types.int);
 
                   description = ''
                     An attribute set which contains further attributes of a indicator.
@@ -147,7 +145,7 @@ in
       };
     };
 
-    config = mkIf cfg.enable {
+    config = lib.mkIf cfg.enable {
       systemd.user.services.yabar = {
         description = "yabar service";
         wantedBy = [ "graphical-session.target" ];
diff --git a/nixos/modules/programs/yazi.nix b/nixos/modules/programs/yazi.nix
index 5905f2afb946d..d9f38d8d81185 100644
--- a/nixos/modules/programs/yazi.nix
+++ b/nixos/modules/programs/yazi.nix
@@ -5,7 +5,7 @@ let
 
   settingsFormat = pkgs.formats.toml { };
 
-  names = [ "yazi" "theme" "keymap" ];
+  files = [ "yazi" "theme" "keymap" ];
 in
 {
   options.programs.yazi = {
@@ -15,7 +15,7 @@ in
 
     settings = lib.mkOption {
       type = with lib.types; submodule {
-        options = lib.listToAttrs (map
+        options = (lib.listToAttrs (map
           (name: lib.nameValuePair name (lib.mkOption {
             inherit (settingsFormat) type;
             default = { };
@@ -25,26 +25,65 @@ in
               See https://yazi-rs.github.io/docs/configuration/${name}/ for documentation.
             '';
           }))
-          names);
+          files));
       };
       default = { };
       description = ''
         Configuration included in `$YAZI_CONFIG_HOME`.
       '';
     };
+
+    initLua = lib.mkOption {
+      type = with lib.types; nullOr path;
+      default = null;
+      description = ''
+        The init.lua for Yazi itself.
+      '';
+      example = lib.literalExpression "./init.lua";
+    };
+
+    plugins = lib.mkOption {
+      type = with lib.types; attrsOf (oneOf [ path package ]);
+      default = { };
+      description = ''
+        Lua plugins.
+
+        See https://yazi-rs.github.io/docs/plugins/overview/ for documentation.
+      '';
+      example = lib.literalExpression ''
+        {
+          foo = ./foo;
+          bar = pkgs.bar;
+        }
+      '';
+    };
+
+    flavors = lib.mkOption {
+      type = with lib.types; attrsOf (oneOf [ path package ]);
+      default = { };
+      description = ''
+        Pre-made themes.
+
+        See https://yazi-rs.github.io/docs/flavors/overview/ for documentation.
+      '';
+      example = lib.literalExpression ''
+        {
+          foo = ./foo;
+          bar = pkgs.bar;
+        }
+      '';
+    };
+
   };
 
   config = lib.mkIf cfg.enable {
-    environment = {
-      systemPackages = [ cfg.package ];
-      variables.YAZI_CONFIG_HOME = "/etc/yazi/";
-      etc = lib.attrsets.mergeAttrsList (map
-        (name: lib.optionalAttrs (cfg.settings.${name} != { }) {
-          "yazi/${name}.toml".source = settingsFormat.generate "${name}.toml" cfg.settings.${name};
-        })
-        names);
-    };
+    environment.systemPackages = [
+      (cfg.package.override {
+        inherit (cfg) settings initLua plugins flavors;
+      })
+    ];
   };
+
   meta = {
     maintainers = with lib.maintainers; [ linsui ];
   };
diff --git a/nixos/modules/programs/ydotool.nix b/nixos/modules/programs/ydotool.nix
new file mode 100644
index 0000000000000..f639e9283de42
--- /dev/null
+++ b/nixos/modules/programs/ydotool.nix
@@ -0,0 +1,83 @@
+{
+  config,
+  lib,
+  pkgs,
+  ...
+}:
+let
+  cfg = config.programs.ydotool;
+in
+{
+  meta = {
+    maintainers = with lib.maintainers; [ quantenzitrone ];
+  };
+
+  options.programs.ydotool = {
+    enable = lib.mkEnableOption ''
+      ydotoold system service and install ydotool.
+      Add yourself to the 'ydotool' group to be able to use it.
+    '';
+  };
+
+  config = lib.mkIf cfg.enable {
+    users.groups.ydotool = { };
+
+    systemd.services.ydotoold = {
+      description = "ydotoold - backend for ydotool";
+      wantedBy = [ "multi-user.target" ];
+      partOf = [ "multi-user.target" ];
+      serviceConfig = {
+        Group = "ydotool";
+        RuntimeDirectory = "ydotoold";
+        RuntimeDirectoryMode = "0750";
+        ExecStart = "${lib.getExe' pkgs.ydotool "ydotoold"} --socket-path=/run/ydotoold/socket --socket-perm=0660";
+
+        # hardening
+
+        ## allow access to uinput
+        DeviceAllow = [ "/dev/uinput" ];
+        DevicePolicy = "closed";
+
+        ## allow creation of unix sockets
+        RestrictAddressFamilies = [ "AF_UNIX" ];
+
+        CapabilityBoundingSet = "";
+        IPAddressDeny = "any";
+        LockPersonality = true;
+        MemoryDenyWriteExecute = true;
+        NoNewPrivileges = true;
+        PrivateNetwork = true;
+        PrivateTmp = true;
+        PrivateUsers = true;
+        ProcSubset = "pid";
+        ProtectClock = true;
+        ProtectControlGroups = true;
+        ProtectHome = true;
+        ProtectHostname = true;
+        ProtectKernelLogs = true;
+        ProtectKernelModules = true;
+        ProtectKernelTunables = true;
+        ProtectProc = "invisible";
+        ProtectSystem = "strict";
+        ProtectUser = true;
+        RestrictNamespaces = true;
+        RestrictRealtime = true;
+        RestrictSUIDSGID = true;
+        SystemCallArchitectures = "native";
+        SystemCallFilter = [
+          "@system-service"
+          "~@privileged"
+          "~@resources"
+        ];
+        UMask = "0077";
+
+        # -> systemd-analyze security score 0.7 SAFE 😀
+      };
+    };
+
+    environment.variables = {
+      YDOTOOL_SOCKET = "/run/ydotoold/socket";
+    };
+    environment.systemPackages = with pkgs; [ ydotool ];
+  };
+}
diff --git a/nixos/modules/programs/zmap.nix b/nixos/modules/programs/zmap.nix
index 827d9bedca13e..4f31d42c4add7 100644
--- a/nixos/modules/programs/zmap.nix
+++ b/nixos/modules/programs/zmap.nix
@@ -1,15 +1,13 @@
 { pkgs, config, lib, ... }:
 
-with lib;
-
 let
   cfg = config.programs.zmap;
 in {
   options.programs.zmap = {
-    enable = mkEnableOption "ZMap, a network scanner designed for Internet-wide network surveys";
+    enable = lib.mkEnableOption "ZMap, a network scanner designed for Internet-wide network surveys";
   };
 
-  config = mkIf cfg.enable {
+  config = lib.mkIf cfg.enable {
     environment.systemPackages = [ pkgs.zmap ];
 
     environment.etc."zmap/blacklist.conf".source = "${pkgs.zmap}/etc/zmap/blacklist.conf";
diff --git a/nixos/modules/programs/zsh/oh-my-zsh.nix b/nixos/modules/programs/zsh/oh-my-zsh.nix
index f2a5a7560e409..2120cf1af07e1 100644
--- a/nixos/modules/programs/zsh/oh-my-zsh.nix
+++ b/nixos/modules/programs/zsh/oh-my-zsh.nix
@@ -1,7 +1,5 @@
 { config, lib, pkgs, ... }:
 
-with lib;
-
 let
 
   cfg = config.programs.zsh.ohMyZsh;
@@ -20,7 +18,7 @@ let
 
   custom =
     if cfg.custom != null then cfg.custom
-    else if length cfg.customPkgs == 0 then null
+    else if builtins.length cfg.customPkgs == 0 then null
     else pkgs.linkFarm "oh-my-zsh-custom" [
       (mkLinkFarmEntry' "themes")
       (mkLinkFarmEntry "completions" "site-functions")
@@ -30,60 +28,60 @@ let
 in
   {
     imports = [
-      (mkRenamedOptionModule [ "programs" "zsh" "oh-my-zsh" "enable" ] [ "programs" "zsh" "ohMyZsh" "enable" ])
-      (mkRenamedOptionModule [ "programs" "zsh" "oh-my-zsh" "theme" ] [ "programs" "zsh" "ohMyZsh" "theme" ])
-      (mkRenamedOptionModule [ "programs" "zsh" "oh-my-zsh" "custom" ] [ "programs" "zsh" "ohMyZsh" "custom" ])
-      (mkRenamedOptionModule [ "programs" "zsh" "oh-my-zsh" "plugins" ] [ "programs" "zsh" "ohMyZsh" "plugins" ])
+      (lib.mkRenamedOptionModule [ "programs" "zsh" "oh-my-zsh" "enable" ] [ "programs" "zsh" "ohMyZsh" "enable" ])
+      (lib.mkRenamedOptionModule [ "programs" "zsh" "oh-my-zsh" "theme" ] [ "programs" "zsh" "ohMyZsh" "theme" ])
+      (lib.mkRenamedOptionModule [ "programs" "zsh" "oh-my-zsh" "custom" ] [ "programs" "zsh" "ohMyZsh" "custom" ])
+      (lib.mkRenamedOptionModule [ "programs" "zsh" "oh-my-zsh" "plugins" ] [ "programs" "zsh" "ohMyZsh" "plugins" ])
     ];
 
     options = {
       programs.zsh.ohMyZsh = {
-        enable = mkOption {
-          type = types.bool;
+        enable = lib.mkOption {
+          type = lib.types.bool;
           default = false;
           description = ''
             Enable oh-my-zsh.
           '';
         };
 
-        package = mkPackageOption pkgs "oh-my-zsh" { };
+        package = lib.mkPackageOption pkgs "oh-my-zsh" { };
 
-        plugins = mkOption {
+        plugins = lib.mkOption {
           default = [];
-          type = types.listOf(types.str);
+          type = lib.types.listOf(lib.types.str);
           description = ''
             List of oh-my-zsh plugins
           '';
         };
 
-        custom = mkOption {
+        custom = lib.mkOption {
           default = null;
-          type = with types; nullOr str;
+          type = with lib.types; nullOr str;
           description = ''
             Path to a custom oh-my-zsh package to override config of oh-my-zsh.
             (Can't be used along with `customPkgs`).
           '';
         };
 
-        customPkgs = mkOption {
+        customPkgs = lib.mkOption {
           default = [];
-          type = types.listOf types.package;
+          type = lib.types.listOf lib.types.package;
           description = ''
             List of custom packages that should be loaded into `oh-my-zsh`.
           '';
         };
 
-        theme = mkOption {
+        theme = lib.mkOption {
           default = "";
-          type = types.str;
+          type = lib.types.str;
           description = ''
             Name of the theme to be used by oh-my-zsh.
           '';
         };
 
-        cacheDir = mkOption {
+        cacheDir = lib.mkOption {
           default = "$HOME/.cache/oh-my-zsh";
-          type = types.str;
+          type = lib.types.str;
           description = ''
             Cache directory to be used by `oh-my-zsh`.
             Without this option it would default to the read-only nix store.
@@ -92,10 +90,10 @@ in
       };
     };
 
-    config = mkIf cfg.enable {
+    config = lib.mkIf cfg.enable {
 
       # Prevent zsh from overwriting oh-my-zsh's prompt
-      programs.zsh.promptInit = mkDefault "";
+      programs.zsh.promptInit = lib.mkDefault "";
 
       environment.systemPackages = [ cfg.package ];
 
@@ -103,19 +101,19 @@ in
         # oh-my-zsh configuration generated by NixOS
         export ZSH=${cfg.package}/share/oh-my-zsh
 
-        ${optionalString (length(cfg.plugins) > 0)
-          "plugins=(${concatStringsSep " " cfg.plugins})"
+        ${lib.optionalString (builtins.length(cfg.plugins) > 0)
+          "plugins=(${builtins.concatStringsSep " " cfg.plugins})"
         }
 
-        ${optionalString (custom != null)
+        ${lib.optionalString (custom != null)
           "ZSH_CUSTOM=\"${custom}\""
         }
 
-        ${optionalString (stringLength(cfg.theme) > 0)
+        ${lib.optionalString (builtins.stringLength(cfg.theme) > 0)
           "ZSH_THEME=\"${cfg.theme}\""
         }
 
-        ${optionalString (cfg.cacheDir != null) ''
+        ${lib.optionalString (cfg.cacheDir != null) ''
           if [[ ! -d "${cfg.cacheDir}" ]]; then
             mkdir -p "${cfg.cacheDir}"
           fi
diff --git a/nixos/modules/programs/zsh/zsh-autoenv.nix b/nixos/modules/programs/zsh/zsh-autoenv.nix
index f07fb5c24d7b3..8e0c19f1afea0 100644
--- a/nixos/modules/programs/zsh/zsh-autoenv.nix
+++ b/nixos/modules/programs/zsh/zsh-autoenv.nix
@@ -1,18 +1,16 @@
 { config, lib, pkgs, ... }:
 
-with lib;
-
 let
   cfg = config.programs.zsh.zsh-autoenv;
 in {
   options = {
     programs.zsh.zsh-autoenv = {
-      enable = mkEnableOption "zsh-autoenv";
-      package = mkPackageOption pkgs "zsh-autoenv" { };
+      enable = lib.mkEnableOption "zsh-autoenv";
+      package = lib.mkPackageOption pkgs "zsh-autoenv" { };
     };
   };
 
-  config = mkIf cfg.enable {
+  config = lib.mkIf cfg.enable {
     programs.zsh.interactiveShellInit = ''
       source ${cfg.package}/share/zsh-autoenv/autoenv.zsh
     '';
diff --git a/nixos/modules/programs/zsh/zsh-autosuggestions.nix b/nixos/modules/programs/zsh/zsh-autosuggestions.nix
index 2e53e907d547a..e046c21025002 100644
--- a/nixos/modules/programs/zsh/zsh-autosuggestions.nix
+++ b/nixos/modules/programs/zsh/zsh-autosuggestions.nix
@@ -1,28 +1,26 @@
 { config, pkgs, lib, ... }:
 
-with lib;
-
 let
   cfg = config.programs.zsh.autosuggestions;
 in
 {
   imports = [
-    (mkRenamedOptionModule [ "programs" "zsh" "enableAutosuggestions" ] [ "programs" "zsh" "autosuggestions" "enable" ])
+    (lib.mkRenamedOptionModule [ "programs" "zsh" "enableAutosuggestions" ] [ "programs" "zsh" "autosuggestions" "enable" ])
   ];
 
   options.programs.zsh.autosuggestions = {
 
-    enable = mkEnableOption "zsh-autosuggestions";
+    enable = lib.mkEnableOption "zsh-autosuggestions";
 
-    highlightStyle = mkOption {
-      type = types.str;
+    highlightStyle = lib.mkOption {
+      type = lib.types.str;
       default = "fg=8"; # https://github.com/zsh-users/zsh-autosuggestions/tree/v0.4.3#suggestion-highlight-style
       description = "Highlight style for suggestions ({fore,back}ground color)";
       example = "fg=cyan";
     };
 
-    strategy = mkOption {
-      type = types.listOf (types.enum [ "history" "completion" "match_prev_cmd" ]);
+    strategy = lib.mkOption {
+      type = lib.types.listOf (lib.types.enum [ "history" "completion" "match_prev_cmd" ]);
       default = [ "history" ];
       description = ''
         `ZSH_AUTOSUGGEST_STRATEGY` is an array that specifies how suggestions should be generated.
@@ -37,18 +35,18 @@ in
       '';
     };
 
-    async = mkOption {
-      type = types.bool;
+    async = lib.mkOption {
+      type = lib.types.bool;
       default = true;
       description = "Whether to fetch suggestions asynchronously";
       example = false;
     };
 
-    extraConfig = mkOption {
-      type = with types; attrsOf str;
+    extraConfig = lib.mkOption {
+      type = lib.types.attrsOf lib.types.str;
       default = {};
       description = "Attribute set with additional configuration values";
-      example = literalExpression ''
+      example = lib.literalExpression ''
         {
           "ZSH_AUTOSUGGEST_BUFFER_MAX_SIZE" = "20";
         }
@@ -57,16 +55,16 @@ in
 
   };
 
-  config = mkIf cfg.enable {
+  config = lib.mkIf cfg.enable {
 
     programs.zsh.interactiveShellInit = ''
       source ${pkgs.zsh-autosuggestions}/share/zsh-autosuggestions/zsh-autosuggestions.zsh
 
       export ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE="${cfg.highlightStyle}"
-      export ZSH_AUTOSUGGEST_STRATEGY=(${concatStringsSep " " cfg.strategy})
-      ${optionalString (!cfg.async) "unset ZSH_AUTOSUGGEST_USE_ASYNC"}
+      export ZSH_AUTOSUGGEST_STRATEGY=(${builtins.concatStringsSep " " cfg.strategy})
+      ${lib.optionalString (!cfg.async) "unset ZSH_AUTOSUGGEST_USE_ASYNC"}
 
-      ${concatStringsSep "\n" (mapAttrsToList (key: value: ''export ${key}="${value}"'') cfg.extraConfig)}
+      ${builtins.concatStringsSep "\n" (lib.mapAttrsToList (key: value: ''export ${key}="${value}"'') cfg.extraConfig)}
     '';
 
   };
diff --git a/nixos/modules/programs/zsh/zsh-syntax-highlighting.nix b/nixos/modules/programs/zsh/zsh-syntax-highlighting.nix
index 46bc4fcb87f4f..3f70c14048c75 100644
--- a/nixos/modules/programs/zsh/zsh-syntax-highlighting.nix
+++ b/nixos/modules/programs/zsh/zsh-syntax-highlighting.nix
@@ -1,27 +1,25 @@
 { config, lib, pkgs, ... }:
 
-with lib;
-
 let
   cfg = config.programs.zsh.syntaxHighlighting;
 in
 {
   imports = [
-    (mkRenamedOptionModule [ "programs" "zsh" "enableSyntaxHighlighting" ] [ "programs" "zsh" "syntaxHighlighting" "enable" ])
-    (mkRenamedOptionModule [ "programs" "zsh" "syntax-highlighting" "enable" ] [ "programs" "zsh" "syntaxHighlighting" "enable" ])
-    (mkRenamedOptionModule [ "programs" "zsh" "syntax-highlighting" "highlighters" ] [ "programs" "zsh" "syntaxHighlighting" "highlighters" ])
-    (mkRenamedOptionModule [ "programs" "zsh" "syntax-highlighting" "patterns" ] [ "programs" "zsh" "syntaxHighlighting" "patterns" ])
+    (lib.mkRenamedOptionModule [ "programs" "zsh" "enableSyntaxHighlighting" ] [ "programs" "zsh" "syntaxHighlighting" "enable" ])
+    (lib.mkRenamedOptionModule [ "programs" "zsh" "syntax-highlighting" "enable" ] [ "programs" "zsh" "syntaxHighlighting" "enable" ])
+    (lib.mkRenamedOptionModule [ "programs" "zsh" "syntax-highlighting" "highlighters" ] [ "programs" "zsh" "syntaxHighlighting" "highlighters" ])
+    (lib.mkRenamedOptionModule [ "programs" "zsh" "syntax-highlighting" "patterns" ] [ "programs" "zsh" "syntaxHighlighting" "patterns" ])
   ];
 
   options = {
     programs.zsh.syntaxHighlighting = {
-      enable = mkEnableOption "zsh-syntax-highlighting";
+      enable = lib.mkEnableOption "zsh-syntax-highlighting";
 
-      highlighters = mkOption {
+      highlighters = lib.mkOption {
         default = [ "main" ];
 
         # https://github.com/zsh-users/zsh-syntax-highlighting/blob/master/docs/highlighters.md
-        type = types.listOf(types.enum([
+        type = lib.types.listOf(lib.types.enum([
           "main"
           "brackets"
           "pattern"
@@ -39,11 +37,11 @@ in
         '';
       };
 
-      patterns = mkOption {
+      patterns = lib.mkOption {
         default = {};
-        type = types.attrsOf types.str;
+        type = lib.types.attrsOf lib.types.str;
 
-        example = literalExpression ''
+        example = lib.literalExpression ''
           {
             "rm -rf *" = "fg=white,bold,bg=red";
           }
@@ -56,11 +54,11 @@ in
           https://github.com/zsh-users/zsh-syntax-highlighting/blob/master/docs/highlighters/pattern.md
         '';
       };
-      styles = mkOption {
+      styles = lib.mkOption {
         default = {};
-        type = types.attrsOf types.str;
+        type = lib.types.attrsOf lib.types.str;
 
-        example = literalExpression ''
+        example = lib.literalExpression ''
           {
             "alias" = "fg=magenta,bold";
           }
@@ -76,30 +74,30 @@ in
     };
   };
 
-  config = mkIf cfg.enable {
-    environment.systemPackages = with pkgs; [ zsh-syntax-highlighting ];
+  config = lib.mkIf cfg.enable {
+    environment.systemPackages = [ pkgs.zsh-syntax-highlighting ];
 
     assertions = [
       {
-        assertion = length(attrNames cfg.patterns) > 0 -> elem "pattern" cfg.highlighters;
+        assertion = builtins.length(builtins.attrNames cfg.patterns) > 0 -> builtins.elem "pattern" cfg.highlighters;
         message = ''
           When highlighting patterns, "pattern" needs to be included in the list of highlighters.
         '';
       }
     ];
 
-    programs.zsh.interactiveShellInit = with pkgs;
+    programs.zsh.interactiveShellInit =
       lib.mkAfter (lib.concatStringsSep "\n" ([
-        "source ${zsh-syntax-highlighting}/share/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh"
-      ] ++ optional (length(cfg.highlighters) > 0)
-        "ZSH_HIGHLIGHT_HIGHLIGHTERS=(${concatStringsSep " " cfg.highlighters})"
-        ++ optionals (length(attrNames cfg.patterns) > 0)
-          (mapAttrsToList (
+        "source ${pkgs.zsh-syntax-highlighting}/share/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh"
+      ] ++ lib.optional (builtins.length(cfg.highlighters) > 0)
+        "ZSH_HIGHLIGHT_HIGHLIGHTERS=(${builtins.concatStringsSep " " cfg.highlighters})"
+        ++ lib.optionals (builtins.length(builtins.attrNames cfg.patterns) > 0)
+          (lib.mapAttrsToList (
             pattern: design:
             "ZSH_HIGHLIGHT_PATTERNS+=('${pattern}' '${design}')"
           ) cfg.patterns)
-        ++ optionals (length(attrNames cfg.styles) > 0)
-          (mapAttrsToList (
+        ++ lib.optionals (builtins.length(builtins.attrNames cfg.styles) > 0)
+          (lib.mapAttrsToList (
             styles: design:
             "ZSH_HIGHLIGHT_STYLES[${styles}]='${design}'"
           ) cfg.styles)
diff --git a/nixos/modules/programs/zsh/zsh.nix b/nixos/modules/programs/zsh/zsh.nix
index d7e300b50136a..35d2cf4610563 100644
--- a/nixos/modules/programs/zsh/zsh.nix
+++ b/nixos/modules/programs/zsh/zsh.nix
@@ -2,8 +2,6 @@
 
 { config, lib, options, pkgs, ... }:
 
-with lib;
-
 let
 
   cfge = config.environment;
@@ -11,9 +9,9 @@ let
   cfg = config.programs.zsh;
   opt = options.programs.zsh;
 
-  zshAliases = concatStringsSep "\n" (
-    mapAttrsFlatten (k: v: "alias -- ${k}=${escapeShellArg v}")
-      (filterAttrs (k: v: v != null) cfg.shellAliases)
+  zshAliases = builtins.concatStringsSep "\n" (
+    lib.mapAttrsFlatten (k: v: "alias -- ${k}=${lib.escapeShellArg v}")
+      (lib.filterAttrs (k: v: v != null) cfg.shellAliases)
   );
 
   zshStartupNotes = ''
@@ -42,7 +40,7 @@ in
 
     programs.zsh = {
 
-      enable = mkOption {
+      enable = lib.mkOption {
         default = false;
         description = ''
           Whether to configure zsh as an interactive shell. To enable zsh for
@@ -50,43 +48,43 @@ in
           option for that user. To enable zsh system-wide use the
           {option}`users.defaultUserShell` option.
         '';
-        type = types.bool;
+        type = lib.types.bool;
       };
 
-      shellAliases = mkOption {
+      shellAliases = lib.mkOption {
         default = { };
         description = ''
           Set of aliases for zsh shell, which overrides {option}`environment.shellAliases`.
           See {option}`environment.shellAliases` for an option format description.
         '';
-        type = with types; attrsOf (nullOr (either str path));
+        type = with lib.types; attrsOf (nullOr (either str path));
       };
 
-      shellInit = mkOption {
+      shellInit = lib.mkOption {
         default = "";
         description = ''
           Shell script code called during zsh shell initialisation.
         '';
-        type = types.lines;
+        type = lib.types.lines;
       };
 
-      loginShellInit = mkOption {
+      loginShellInit = lib.mkOption {
         default = "";
         description = ''
           Shell script code called during zsh login shell initialisation.
         '';
-        type = types.lines;
+        type = lib.types.lines;
       };
 
-      interactiveShellInit = mkOption {
+      interactiveShellInit = lib.mkOption {
         default = "";
         description = ''
           Shell script code called during interactive zsh shell initialisation.
         '';
-        type = types.lines;
+        type = lib.types.lines;
       };
 
-      promptInit = mkOption {
+      promptInit = lib.mkOption {
         default = ''
           # Note that to manually override this in ~/.zshrc you should run `prompt off`
           # before setting your PS1 and etc. Otherwise this will likely to interact with
@@ -97,27 +95,27 @@ in
         description = ''
           Shell script code used to initialise the zsh prompt.
         '';
-        type = types.lines;
+        type = lib.types.lines;
       };
 
-      histSize = mkOption {
+      histSize = lib.mkOption {
         default = 2000;
         description = ''
           Change history size.
         '';
-        type = types.int;
+        type = lib.types.int;
       };
 
-      histFile = mkOption {
+      histFile = lib.mkOption {
         default = "$HOME/.zsh_history";
         description = ''
           Change history file.
         '';
-        type = types.str;
+        type = lib.types.str;
       };
 
-      setOptions = mkOption {
-        type = types.listOf types.str;
+      setOptions = lib.mkOption {
+        type = lib.types.listOf lib.types.str;
         default = [
           "HIST_IGNORE_DUPS"
           "SHARE_HISTORY"
@@ -130,25 +128,25 @@ in
         '';
       };
 
-      enableCompletion = mkOption {
+      enableCompletion = lib.mkOption {
         default = true;
         description = ''
           Enable zsh completion for all interactive zsh shells.
         '';
-        type = types.bool;
+        type = lib.types.bool;
       };
 
-      enableBashCompletion = mkOption {
+      enableBashCompletion = lib.mkOption {
         default = false;
         description = ''
           Enable compatibility with bash's programmable completion system.
         '';
-        type = types.bool;
+        type = lib.types.bool;
       };
 
-      enableGlobalCompInit = mkOption {
+      enableGlobalCompInit = lib.mkOption {
         default = cfg.enableCompletion;
-        defaultText = literalExpression "config.${opt.enableCompletion}";
+        defaultText = lib.literalExpression "config.${opt.enableCompletion}";
         description = ''
           Enable execution of compinit call for all interactive zsh shells.
 
@@ -156,24 +154,24 @@ in
           `fpath` and a custom `compinit`
           call in the local config is required.
         '';
-        type = types.bool;
+        type = lib.types.bool;
       };
 
-      enableLsColors = mkOption {
+      enableLsColors = lib.mkOption {
         default = true;
         description = ''
           Enable extra colors in directory listings (used by `ls` and `tree`).
         '';
-        type = types.bool;
+        type = lib.types.bool;
       };
 
     };
 
   };
 
-  config = mkIf cfg.enable {
+  config = lib.mkIf cfg.enable {
 
-    programs.zsh.shellAliases = mapAttrs (name: mkDefault) cfge.shellAliases;
+    programs.zsh.shellAliases = builtins.mapAttrs (name: lib.mkDefault) cfge.shellAliases;
 
     environment.etc.zshenv.text =
       ''
@@ -239,9 +237,9 @@ in
         if [ -n "$__ETC_ZSHRC_SOURCED" -o -n "$NOSYSZSHRC" ]; then return; fi
         __ETC_ZSHRC_SOURCED=1
 
-        ${optionalString (cfg.setOptions != []) ''
+        ${lib.optionalString (cfg.setOptions != []) ''
           # Set zsh options.
-          setopt ${concatStringsSep " " cfg.setOptions}
+          setopt ${builtins.concatStringsSep " " cfg.setOptions}
         ''}
 
         # Alternative method of determining short and full hostname.
@@ -249,19 +247,19 @@ in
 
         # Setup command line history.
         # Don't export these, otherwise other shells (bash) will try to use same HISTFILE.
-        SAVEHIST=${toString cfg.histSize}
-        HISTSIZE=${toString cfg.histSize}
+        SAVEHIST=${builtins.toString cfg.histSize}
+        HISTSIZE=${builtins.toString cfg.histSize}
         HISTFILE=${cfg.histFile}
 
         # Configure sane keyboard defaults.
         . /etc/zinputrc
 
-        ${optionalString cfg.enableGlobalCompInit ''
+        ${lib.optionalString cfg.enableGlobalCompInit ''
           # Enable autocompletion.
           autoload -U compinit && compinit
         ''}
 
-        ${optionalString cfg.enableBashCompletion ''
+        ${lib.optionalString cfg.enableBashCompletion ''
           # Enable compatibility with bash's completion system.
           autoload -U bashcompinit && bashcompinit
         ''}
@@ -271,7 +269,7 @@ in
 
         ${cfg.interactiveShellInit}
 
-        ${optionalString cfg.enableLsColors ''
+        ${lib.optionalString cfg.enableLsColors ''
           # Extra colors for directory listings.
           eval "$(${pkgs.coreutils}/bin/dircolors -b)"
         ''}
@@ -302,11 +300,11 @@ in
     environment.etc.zinputrc.text = builtins.readFile ./zinputrc;
 
     environment.systemPackages = [ pkgs.zsh ]
-      ++ optional cfg.enableCompletion pkgs.nix-zsh-completions;
+      ++ lib.optional cfg.enableCompletion pkgs.nix-zsh-completions;
 
-    environment.pathsToLink = optional cfg.enableCompletion "/share/zsh";
+    environment.pathsToLink = lib.optional cfg.enableCompletion "/share/zsh";
 
-    #users.defaultUserShell = mkDefault "/run/current-system/sw/bin/zsh";
+    #users.defaultUserShell = lib.mkDefault "/run/current-system/sw/bin/zsh";
 
     environment.shells =
       [
diff --git a/nixos/modules/rename.nix b/nixos/modules/rename.nix
index 01985995a651d..d4661a19188c8 100644
--- a/nixos/modules/rename.nix
+++ b/nixos/modules/rename.nix
@@ -40,12 +40,16 @@ in
     (mkRemovedOptionModule [ "networking" "vpnc" ] "Use environment.etc.\"vpnc/service.conf\" instead.")
     (mkRemovedOptionModule [ "networking" "wicd" ] "The corresponding package was removed from nixpkgs.")
     (mkRemovedOptionModule [ "programs" "gnome-documents" ] "The corresponding package was removed from nixpkgs.")
+    (mkRemovedOptionModule [ "programs" "pantheon-tweaks" ] ''
+      pantheon-tweaks is no longer a switchboard plugin but an independent app,
+      adding the package to environment.systemPackages is sufficient.
+    '')
     (mkRemovedOptionModule [ "programs" "tilp2" ] "The corresponding package was removed from nixpkgs.")
     (mkRemovedOptionModule [ "programs" "way-cooler" ] ("way-cooler is abandoned by its author: " +
       "https://way-cooler.org/blog/2020/01/09/way-cooler-post-mortem.html"))
     (mkRemovedOptionModule [ "security" "hideProcessInformation" ] ''
-        The hidepid module was removed, since the underlying machinery
-        is broken when using cgroups-v2.
+      The hidepid module was removed, since the underlying machinery
+      is broken when using cgroups-v2.
     '')
     (mkRemovedOptionModule [ "services" "baget" "enable" ] "The baget module was removed due to the upstream package being unmaintained.")
     (mkRemovedOptionModule [ "services" "beegfs" ] "The BeeGFS module has been removed")
diff --git a/nixos/modules/security/systemd-confinement.nix b/nixos/modules/security/systemd-confinement.nix
index 0304749b8d109..041c900338864 100644
--- a/nixos/modules/security/systemd-confinement.nix
+++ b/nixos/modules/security/systemd-confinement.nix
@@ -79,13 +79,20 @@ in {
         description = ''
           The value `full-apivfs` (the default) sets up
           private {file}`/dev`, {file}`/proc`,
-          {file}`/sys` and {file}`/tmp` file systems in a separate user
-          name space.
+          {file}`/sys`, {file}`/tmp` and {file}`/var/tmp` file systems
+          in a separate user name space.
 
           If this is set to `chroot-only`, only the file
           system name space is set up along with the call to
           {manpage}`chroot(2)`.
 
+          In all cases, unless `serviceConfig.PrivateTmp=true` is set,
+          both {file}`/tmp` and {file}`/var/tmp` paths are added to `InaccessiblePaths=`.
+          This is to overcome options like `DynamicUser=true`
+          implying `PrivateTmp=true` without letting it being turned off.
+          Beware however that giving processes the `CAP_SYS_ADMIN` and `@mount` privileges
+          can let them undo the effects of `InaccessiblePaths=`.
+
           ::: {.note}
           This doesn't cover network namespaces and is solely for
           file system level isolation.
@@ -98,8 +105,12 @@ in {
         wantsAPIVFS = lib.mkDefault (config.confinement.mode == "full-apivfs");
       in lib.mkIf config.confinement.enable {
         serviceConfig = {
-          RootDirectory = "/var/empty";
-          TemporaryFileSystem = "/";
+          ReadOnlyPaths = [ "+/" ];
+          RuntimeDirectory = [ "confinement/${mkPathSafeName name}" ];
+          RootDirectory = "/run/confinement/${mkPathSafeName name}";
+          InaccessiblePaths = [
+            "-+/run/confinement/${mkPathSafeName name}"
+          ];
           PrivateMounts = lib.mkDefault true;
 
           # https://github.com/NixOS/nixpkgs/issues/14645 is a future attempt
@@ -148,16 +159,6 @@ in {
               + " Please either define a separate service or find a way to run"
               + " commands other than ExecStart within the chroot.";
     }
-    { assertion = !cfg.serviceConfig.DynamicUser or false;
-      message = "${whatOpt "DynamicUser"}. Please create a dedicated user via"
-              + " the 'users.users' option instead as this combination is"
-              + " currently not supported.";
-    }
-    { assertion = cfg.serviceConfig ? ProtectSystem -> cfg.serviceConfig.ProtectSystem == false;
-      message = "${whatOpt "ProtectSystem"}. ProtectSystem is not compatible"
-              + " with service confinement as it fails to remount /usr within"
-              + " our chroot. Please disable the option.";
-    }
   ]) config.systemd.services);
 
   config.systemd.packages = lib.concatLists (lib.mapAttrsToList (name: cfg: let
@@ -183,6 +184,13 @@ in {
         echo "BindReadOnlyPaths=$realprog:/bin/sh" >> "$serviceFile"
       ''}
 
+      # If DynamicUser= is enabled, PrivateTmp=true is implied (and cannot be turned off).
+      # so disable them unless PrivateTmp=true is explicitely set.
+      ${lib.optionalString (!cfg.serviceConfig.PrivateTmp) ''
+        echo "InaccessiblePaths=-+/tmp" >> "$serviceFile"
+        echo "InaccessiblePaths=-+/var/tmp" >> "$serviceFile"
+      ''}
+
       while read storePath; do
         if [ -L "$storePath" ]; then
           # Currently, systemd can't cope with symlinks in Bind(ReadOnly)Paths,
diff --git a/nixos/modules/services/admin/pgadmin.nix b/nixos/modules/services/admin/pgadmin.nix
index ead0c3c6c9a34..b3dd3c78874c2 100644
--- a/nixos/modules/services/admin/pgadmin.nix
+++ b/nixos/modules/services/admin/pgadmin.nix
@@ -152,7 +152,8 @@ in
         # Check here for password length to prevent pgadmin from starting
         # and presenting a hard to find error message
         # see https://github.com/NixOS/nixpkgs/issues/270624
-        PW_LENGTH=$(wc -m < ${escapeShellArg cfg.initialPasswordFile})
+        PW_FILE="$CREDENTIALS_DIRECTORY/initial_password"
+        PW_LENGTH=$(wc -m < "$PW_FILE")
         if [ $PW_LENGTH -lt ${toString cfg.minimumPasswordLength} ]; then
             echo "Password must be at least ${toString cfg.minimumPasswordLength} characters long"
             exit 1
@@ -162,7 +163,7 @@ in
           echo ${escapeShellArg cfg.initialEmail}
 
           # file might not contain newline. echo hack fixes that.
-          PW=$(cat ${escapeShellArg cfg.initialPasswordFile})
+          PW=$(cat "$PW_FILE")
 
           # Password:
           echo "$PW"
@@ -181,6 +182,8 @@ in
         LogsDirectory = "pgadmin";
         StateDirectory = "pgadmin";
         ExecStart = "${cfg.package}/bin/pgadmin4";
+        LoadCredential = [ "initial_password:${cfg.initialPasswordFile}" ]
+          ++ optional cfg.emailServer.enable "email_password:${cfg.emailServer.passwordFile}";
       };
     };
 
@@ -193,7 +196,8 @@ in
 
     environment.etc."pgadmin/config_system.py" = {
       text = lib.optionalString cfg.emailServer.enable ''
-        with open("${cfg.emailServer.passwordFile}") as f:
+        import os
+        with open(os.path.join(os.environ['CREDENTIALS_DIRECTORY'], 'email_password')) as f:
           pw = f.read()
         MAIL_PASSWORD = pw
       '' + formatPy cfg.settings;
diff --git a/nixos/modules/services/audio/navidrome.nix b/nixos/modules/services/audio/navidrome.nix
index a5a7e805e3d61..a9db9228827a2 100644
--- a/nixos/modules/services/audio/navidrome.nix
+++ b/nixos/modules/services/audio/navidrome.nix
@@ -1,11 +1,27 @@
-{ config, lib, pkgs, ... }:
-
-with lib;
+{
+  config,
+  lib,
+  pkgs,
+  ...
+}:
 
 let
+  inherit (lib)
+    mkEnableOption
+    mkPackageOption
+    mkOption
+    maintainers
+    ;
+  inherit (lib.types)
+    bool
+    port
+    str
+    submodule
+    ;
   cfg = config.services.navidrome;
-  settingsFormat = pkgs.formats.json {};
-in {
+  settingsFormat = pkgs.formats.json { };
+in
+{
   options = {
     services.navidrome = {
 
@@ -13,72 +29,133 @@ in {
 
       package = mkPackageOption pkgs "navidrome" { };
 
-      settings = mkOption rec {
-        type = settingsFormat.type;
-        apply = recursiveUpdate default;
-        default = {
-          Address = "127.0.0.1";
-          Port = 4533;
+      settings = mkOption {
+        type = submodule {
+          freeformType = settingsFormat.type;
+
+          options = {
+            Address = mkOption {
+              default = "127.0.0.1";
+              description = "Address to run Navidrome on.";
+              type = str;
+            };
+
+            Port = mkOption {
+              default = 4533;
+              description = "Port to run Navidrome on.";
+              type = port;
+            };
+          };
         };
+        default = { };
         example = {
           MusicFolder = "/mnt/music";
         };
-        description = ''
-          Configuration for Navidrome, see <https://www.navidrome.org/docs/usage/configuration-options/> for supported values.
-        '';
+        description = "Configuration for Navidrome, see <https://www.navidrome.org/docs/usage/configuration-options/> for supported values.";
+      };
+
+      user = mkOption {
+        type = str;
+        default = "navidrome";
+        description = "User under which Navidrome runs.";
+      };
+
+      group = mkOption {
+        type = str;
+        default = "navidrome";
+        description = "Group under which Navidrome runs.";
       };
 
       openFirewall = mkOption {
-        type = types.bool;
+        type = bool;
         default = false;
         description = "Whether to open the TCP port in the firewall";
       };
     };
   };
 
-  config = mkIf cfg.enable {
-    networking.firewall.allowedTCPPorts = mkIf cfg.openFirewall [cfg.settings.Port];
+  config =
+    let
+      inherit (lib) mkIf optional getExe;
+      WorkingDirectory = "/var/lib/navidrome";
+    in
+    mkIf cfg.enable {
+      systemd = {
+        tmpfiles.settings.navidromeDirs = {
+          "${cfg.settings.DataFolder or WorkingDirectory}"."d" = {
+            mode = "700";
+            inherit (cfg) user group;
+          };
+          "${cfg.settings.CacheFolder or (WorkingDirectory + "/cache")}"."d" = {
+            mode = "700";
+            inherit (cfg) user group;
+          };
+        };
+        services.navidrome = {
+          description = "Navidrome Media Server";
+          after = [ "network.target" ];
+          wantedBy = [ "multi-user.target" ];
+          serviceConfig = {
+            ExecStart = ''
+              ${getExe cfg.package} --configfile ${settingsFormat.generate "navidrome.json" cfg.settings}
+            '';
+            User = cfg.user;
+            Group = cfg.group;
+            StateDirectory = "navidrome";
+            inherit WorkingDirectory;
+            RuntimeDirectory = "navidrome";
+            RootDirectory = "/run/navidrome";
+            ReadWritePaths = "";
+            BindPaths =
+              optional (cfg.settings ? DataFolder) cfg.settings.DataFolder
+              ++ optional (cfg.settings ? CacheFolder) cfg.settings.CacheFolder;
+            BindReadOnlyPaths = [
+              # navidrome uses online services to download additional album metadata / covers
+              "${
+                config.environment.etc."ssl/certs/ca-certificates.crt".source
+              }:/etc/ssl/certs/ca-certificates.crt"
+              builtins.storeDir
+              "/etc"
+            ] ++ optional (cfg.settings ? MusicFolder) cfg.settings.MusicFolder;
+            CapabilityBoundingSet = "";
+            RestrictAddressFamilies = [
+              "AF_UNIX"
+              "AF_INET"
+              "AF_INET6"
+            ];
+            RestrictNamespaces = true;
+            PrivateDevices = true;
+            PrivateUsers = true;
+            ProtectClock = true;
+            ProtectControlGroups = true;
+            ProtectHome = true;
+            ProtectKernelLogs = true;
+            ProtectKernelModules = true;
+            ProtectKernelTunables = true;
+            SystemCallArchitectures = "native";
+            SystemCallFilter = [
+              "@system-service"
+              "~@privileged"
+            ];
+            RestrictRealtime = true;
+            LockPersonality = true;
+            MemoryDenyWriteExecute = true;
+            UMask = "0066";
+            ProtectHostname = true;
+          };
+        };
+      };
 
-    systemd.services.navidrome = {
-      description = "Navidrome Media Server";
-      after = [ "network.target" ];
-      wantedBy = [ "multi-user.target" ];
-      serviceConfig = {
-        ExecStart = ''
-          ${cfg.package}/bin/navidrome --configfile ${settingsFormat.generate "navidrome.json" cfg.settings}
-        '';
-        DynamicUser = true;
-        StateDirectory = "navidrome";
-        WorkingDirectory = "/var/lib/navidrome";
-        RuntimeDirectory = "navidrome";
-        RootDirectory = "/run/navidrome";
-        ReadWritePaths = "";
-        BindPaths = lib.optional (cfg.settings ? DataFolder) cfg.settings.DataFolder;
-        BindReadOnlyPaths = [
-          # navidrome uses online services to download additional album metadata / covers
-          "${config.environment.etc."ssl/certs/ca-certificates.crt".source}:/etc/ssl/certs/ca-certificates.crt"
-          builtins.storeDir
-          "/etc"
-        ] ++ lib.optional (cfg.settings ? MusicFolder) cfg.settings.MusicFolder;
-        CapabilityBoundingSet = "";
-        RestrictAddressFamilies = [ "AF_UNIX" "AF_INET" "AF_INET6" ];
-        RestrictNamespaces = true;
-        PrivateDevices = true;
-        PrivateUsers = true;
-        ProtectClock = true;
-        ProtectControlGroups = true;
-        ProtectHome = true;
-        ProtectKernelLogs = true;
-        ProtectKernelModules = true;
-        ProtectKernelTunables = true;
-        SystemCallArchitectures = "native";
-        SystemCallFilter = [ "@system-service" "~@privileged" ];
-        RestrictRealtime = true;
-        LockPersonality = true;
-        MemoryDenyWriteExecute = true;
-        UMask = "0066";
-        ProtectHostname = true;
+      users.users = mkIf (cfg.user == "navidrome") {
+        navidrome = {
+          inherit (cfg) group;
+          isSystemUser = true;
+        };
       };
+
+      users.groups = mkIf (cfg.group == "navidrome") { navidrome = { }; };
+
+      networking.firewall.allowedTCPPorts = mkIf cfg.openFirewall [ cfg.settings.Port ];
     };
-  };
+  meta.maintainers = with maintainers; [ nu-nu-ko ];
 }
diff --git a/nixos/modules/services/backup/borgbackup.nix b/nixos/modules/services/backup/borgbackup.nix
index 570f8931bd9e9..a3c0715c9e607 100644
--- a/nixos/modules/services/backup/borgbackup.nix
+++ b/nixos/modules/services/backup/borgbackup.nix
@@ -33,13 +33,24 @@ let
     }
     trap on_exit EXIT
 
+    borgWrapper () {
+      local result
+      borg "$@" && result=$? || result=$?
+      if [[ -z "${toString cfg.failOnWarnings}" ]] && [[ "$result" == 1 ]]; then
+        echo "ignoring warning return value 1"
+        return 0
+      else
+        return "$result"
+      fi
+    }
+
     archiveName="${optionalString (cfg.archiveBaseName != null) (cfg.archiveBaseName + "-")}$(date ${cfg.dateFormat})"
     archiveSuffix="${optionalString cfg.appendFailedSuffix ".failed"}"
     ${cfg.preHook}
   '' + optionalString cfg.doInit ''
     # Run borg init if the repo doesn't exist yet
-    if ! borg list $extraArgs > /dev/null; then
-      borg init $extraArgs \
+    if ! borgWrapper list $extraArgs > /dev/null; then
+      borgWrapper init $extraArgs \
         --encryption ${cfg.encryption.mode} \
         $extraInitArgs
       ${cfg.postInit}
@@ -48,7 +59,7 @@ let
     (
       set -o pipefail
       ${optionalString (cfg.dumpCommand != null) ''${escapeShellArg cfg.dumpCommand} | \''}
-      borg create $extraArgs \
+      borgWrapper create $extraArgs \
         --compression ${cfg.compression} \
         --exclude-from ${mkExcludeFile cfg} \
         --patterns-from ${mkPatternsFile cfg} \
@@ -57,16 +68,16 @@ let
         ${if cfg.paths == null then "-" else escapeShellArgs cfg.paths}
     )
   '' + optionalString cfg.appendFailedSuffix ''
-    borg rename $extraArgs \
+    borgWrapper rename $extraArgs \
       "::$archiveName$archiveSuffix" "$archiveName"
   '' + ''
     ${cfg.postCreate}
   '' + optionalString (cfg.prune.keep != { }) ''
-    borg prune $extraArgs \
+    borgWrapper prune $extraArgs \
       ${mkKeepArgs cfg} \
       ${optionalString (cfg.prune.prefix != null) "--glob-archives ${escapeShellArg "${cfg.prune.prefix}*"}"} \
       $extraPruneArgs
-    borg compact $extraArgs $extraCompactArgs
+    borgWrapper compact $extraArgs $extraCompactArgs
     ${cfg.postPrune}
   '');
 
@@ -350,7 +361,7 @@ in {
             type = types.bool;
             example = true;
             description = ''
-              Set the `persistentTimer` option for the
+              Set the `Persistent` option for the
               {manpage}`systemd.timer(5)`
               which triggers the backup immediately if the last trigger
               was missed (e.g. if the system was powered down).
@@ -488,6 +499,15 @@ in {
             default = true;
           };
 
+          failOnWarnings = mkOption {
+            type = types.bool;
+            description = ''
+              Fail the whole backup job if any borg command returns a warning
+              (exit code 1), for example because a file changed during backup.
+            '';
+            default = true;
+          };
+
           doInit = mkOption {
             type = types.bool;
             description = ''
diff --git a/nixos/modules/services/cluster/k3s/default.nix b/nixos/modules/services/cluster/k3s/default.nix
index 040cf7640de16..4d18d378d7944 100644
--- a/nixos/modules/services/cluster/k3s/default.nix
+++ b/nixos/modules/services/cluster/k3s/default.nix
@@ -1,15 +1,25 @@
-{ config, lib, pkgs, ... }:
+{
+  config,
+  lib,
+  pkgs,
+  ...
+}:
 
 with lib;
 let
   cfg = config.services.k3s;
-  removeOption = config: instruction:
-    lib.mkRemovedOptionModule ([ "services" "k3s" ] ++ config) instruction;
+  removeOption =
+    config: instruction:
+    lib.mkRemovedOptionModule (
+      [
+        "services"
+        "k3s"
+      ]
+      ++ config
+    ) instruction;
 in
 {
-  imports = [
-    (removeOption [ "docker" ] "k3s docker option is no longer supported.")
-  ];
+  imports = [ (removeOption [ "docker" ] "k3s docker option is no longer supported.") ];
 
   # interface
   options.services.k3s = {
@@ -33,7 +43,10 @@ in
         - `serverAddr` is required.
       '';
       default = "server";
-      type = types.enum [ "server" "agent" ];
+      type = types.enum [
+        "server"
+        "agent"
+      ];
     };
 
     serverAddr = mkOption {
@@ -125,7 +138,8 @@ in
         message = "serverAddr or configPath (with 'server' key) should be set if role is 'agent'";
       }
       {
-        assertion = cfg.role == "agent" -> cfg.configPath != null || cfg.tokenFile != null || cfg.token != "";
+        assertion =
+          cfg.role == "agent" -> cfg.configPath != null || cfg.tokenFile != null || cfg.token != "";
         message = "token or tokenFile or configPath (with 'token' or 'token-file' keys) should be set if role is 'agent'";
       }
       {
@@ -142,8 +156,14 @@ in
 
     systemd.services.k3s = {
       description = "k3s service";
-      after = [ "firewall.service" "network-online.target" ];
-      wants = [ "firewall.service" "network-online.target" ];
+      after = [
+        "firewall.service"
+        "network-online.target"
+      ];
+      wants = [
+        "firewall.service"
+        "network-online.target"
+      ];
       wantedBy = [ "multi-user.target" ];
       path = optional config.boot.zfs.enabled config.boot.zfs.package;
       serviceConfig = {
@@ -159,9 +179,7 @@ in
         TasksMax = "infinity";
         EnvironmentFile = cfg.environmentFile;
         ExecStart = concatStringsSep " \\\n " (
-          [
-            "${cfg.package}/bin/k3s ${cfg.role}"
-          ]
+          [ "${cfg.package}/bin/k3s ${cfg.role}" ]
           ++ (optional cfg.clusterInit "--cluster-init")
           ++ (optional cfg.disableAgent "--disable-agent")
           ++ (optional (cfg.serverAddr != "") "--server ${cfg.serverAddr}")
diff --git a/nixos/modules/services/continuous-integration/hydra/default.nix b/nixos/modules/services/continuous-integration/hydra/default.nix
index 23f07eb64b92d..b516c3d6192cb 100644
--- a/nixos/modules/services/continuous-integration/hydra/default.nix
+++ b/nixos/modules/services/continuous-integration/hydra/default.nix
@@ -335,7 +335,7 @@ in
           mkdir -m 0700 -p ${baseDir}/queue-runner
           mkdir -m 0750 -p ${baseDir}/build-logs
           mkdir -m 0750 -p ${baseDir}/runcommand-logs
-          chown hydra-queue-runner.hydra \
+          chown hydra-queue-runner:hydra \
             ${baseDir}/queue-runner \
             ${baseDir}/build-logs \
             ${baseDir}/runcommand-logs
diff --git a/nixos/modules/services/desktop-managers/lomiri.nix b/nixos/modules/services/desktop-managers/lomiri.nix
index e11867b691071..06930b15a0084 100644
--- a/nixos/modules/services/desktop-managers/lomiri.nix
+++ b/nixos/modules/services/desktop-managers/lomiri.nix
@@ -38,6 +38,7 @@ in {
       ]);
     };
 
+    hardware.pulseaudio.enable = lib.mkDefault true;
     networking.networkmanager.enable = lib.mkDefault true;
 
     systemd.packages = with pkgs.lomiri; [
@@ -71,8 +72,12 @@ in {
       enable = true;
       packages = (with pkgs; [
         ayatana-indicator-datetime
+        ayatana-indicator-display
         ayatana-indicator-messages
+        ayatana-indicator-power
         ayatana-indicator-session
+      ] ++ lib.optionals (config.hardware.pulseaudio.enable || config.services.pipewire.pulse.enable) [
+        ayatana-indicator-sound
       ]) ++ (with pkgs.lomiri; [
         telephony-service
       ] ++ lib.optionals config.networking.networkmanager.enable [
diff --git a/nixos/modules/services/desktop-managers/plasma6.nix b/nixos/modules/services/desktop-managers/plasma6.nix
index 842b0716b928d..83f6b5bc0ea10 100644
--- a/nixos/modules/services/desktop-managers/plasma6.nix
+++ b/nixos/modules/services/desktop-managers/plasma6.nix
@@ -60,10 +60,8 @@ in {
     qt.enable = true;
     environment.systemPackages = with kdePackages; let
       requiredPackages = [
-        # Hack? To make everything run on Wayland
-        qtwayland
-        # Needed to render SVG icons
-        qtsvg
+        qtwayland # Hack? To make everything run on Wayland
+        qtsvg # Needed to render SVG icons
 
         # Frameworks with globally loadable bits
         frameworkintegration # provides Qt plugin
@@ -75,6 +73,9 @@ in {
         kiconthemes # provides Qt plugins
         kimageformats # provides Qt plugins
         kio # provides helper service + a bunch of other stuff
+        kio-admin # managing files as admin
+        kio-extras # stuff for MTP, AFC, etc
+        kio-fuse # fuse interface for KIO
         kpackage # provides kpackagetool tool
         kservice # provides kbuildsycoca6 tool
         kwallet # provides helper service
@@ -87,30 +88,26 @@ in {
         # Core Plasma parts
         kwin
         pkgs.xwayland
-
         kscreen
         libkscreen
-
         kscreenlocker
-
         kactivitymanagerd
         kde-cli-tools
-        kglobalacceld
+        kglobalacceld # keyboard shortcut daemon
         kwrited # wall message proxy, not to be confused with kwrite
-
-        milou
-        polkit-kde-agent-1
-
+        baloo # system indexer
+        milou # search engine atop baloo
+        kdegraphics-thumbnailers # pdf etc thumbnailer
+        polkit-kde-agent-1 # polkit auth ui
         plasma-desktop
         plasma-workspace
-
-        # Crash handler
-        drkonqi
+        drkonqi # crash handler
+        kde-inotify-survey # warns the user on low inotifywatch limits
 
         # Application integration
         libplasma # provides Kirigami platform theme
         plasma-integration # provides Qt platform theme
-        kde-gtk-config
+        kde-gtk-config # syncs KDE settings to GTK
 
         # Artwork + themes
         breeze
@@ -124,37 +121,21 @@ in {
 
         # misc Plasma extras
         kdeplasma-addons
-
         pkgs.xdg-user-dirs # recommended upstream
 
         # Plasma utilities
         kmenuedit
-
         kinfocenter
         plasma-systemmonitor
         ksystemstats
         libksysguard
-
-        spectacle
         systemsettings
         kcmutils
-
-        # Gear
-        baloo
-        dolphin
-        dolphin-plugins
-        ffmpegthumbs
-        kdegraphics-thumbnailers
-        kde-inotify-survey
-        kio-admin
-        kio-extras
-        kio-fuse
       ];
       optionalPackages = [
         plasma-browser-integration
         konsole
         (lib.getBin qttools) # Expose qdbus in PATH
-
         ark
         elisa
         gwenview
@@ -162,6 +143,10 @@ in {
         kate
         khelpcenter
         print-manager
+        dolphin
+        dolphin-plugins
+        spectacle
+        ffmpegthumbs
       ];
     in
       requiredPackages
diff --git a/nixos/modules/services/desktops/espanso.nix b/nixos/modules/services/desktops/espanso.nix
index 4ef6724dda0a0..a9b15b2659459 100644
--- a/nixos/modules/services/desktops/espanso.nix
+++ b/nixos/modules/services/desktops/espanso.nix
@@ -6,19 +6,25 @@ in {
   meta = { maintainers = with lib.maintainers; [ numkem ]; };
 
   options = {
-    services.espanso = { enable = options.mkEnableOption "Espanso"; };
+    services.espanso = {
+      enable = mkEnableOption "Espanso";
+      package = mkPackageOption pkgs "espanso" {
+        example = "pkgs.espanso-wayland";
+      };
+    };
   };
 
   config = mkIf cfg.enable {
+    services.espanso.package = mkIf cfg.wayland pkgs.espanso-wayland;
     systemd.user.services.espanso = {
       description = "Espanso daemon";
       serviceConfig = {
-        ExecStart = "${pkgs.espanso}/bin/espanso daemon";
+        ExecStart = "${lib.getExe cfg.package} daemon";
         Restart = "on-failure";
       };
       wantedBy = [ "default.target" ];
     };
 
-    environment.systemPackages = [ pkgs.espanso ];
+    environment.systemPackages = [ cfg.package ];
   };
 }
diff --git a/nixos/modules/services/display-managers/default.nix b/nixos/modules/services/display-managers/default.nix
index 6fa8556e39bee..feba4b163ccd2 100644
--- a/nixos/modules/services/display-managers/default.nix
+++ b/nixos/modules/services/display-managers/default.nix
@@ -113,7 +113,7 @@ in
         type = lib.types.nullOr lib.types.str // {
           description = "session name";
           check = d:
-            lib.assertMsg (d != null -> (lib.types.str.check d && lib.elem d config.services.displayManager.sessionData.sessionNames)) ''
+            lib.assertMsg (d != null -> (lib.types.str.check d && lib.elem d cfg.sessionData.sessionNames)) ''
                 Default graphical session, '${d}', not found.
                 Valid names for 'services.displayManager.defaultSession' are:
                   ${lib.concatStringsSep "\n  " cfg.sessionData.sessionNames}
@@ -187,7 +187,7 @@ in
 
     services.displayManager.sessionData = {
       desktops = installedSessions;
-      sessionNames = lib.concatMap (p: p.providedSessions) config.services.displayManager.sessionPackages;
+      sessionNames = lib.concatMap (p: p.providedSessions) cfg.sessionPackages;
       # We do not want to force users to set defaultSession when they have only single DE.
       autologinSession =
         if cfg.defaultSession != null then
diff --git a/nixos/modules/services/display-managers/greetd.nix b/nixos/modules/services/display-managers/greetd.nix
index c07b225fc4d95..118a3e1df378c 100644
--- a/nixos/modules/services/display-managers/greetd.nix
+++ b/nixos/modules/services/display-managers/greetd.nix
@@ -27,6 +27,17 @@ in
       '';
     };
 
+    greeterManagesPlymouth = mkOption {
+      type = types.bool;
+      internal = true;
+      default = false;
+      description = ''
+        Don't configure the greetd service to wait for Plymouth to exit.
+
+        Enable this if the greeter you're using can manage Plymouth itself to provide a smoother handoff.
+      '';
+    };
+
     vt = mkOption {
       type = types.int;
       default = 1;
@@ -72,8 +83,9 @@ in
         ];
         After = [
           "systemd-user-sessions.service"
-          "plymouth-quit-wait.service"
           "getty@${tty}.service"
+        ] ++ lib.optionals (!cfg.greeterManagesPlymouth) [
+          "plymouth-quit-wait.service"
         ];
         Conflicts = [
           "getty@${tty}.service"
diff --git a/nixos/modules/services/display-managers/sddm.nix b/nixos/modules/services/display-managers/sddm.nix
index a6bfa213fe380..54356f7bb6171 100644
--- a/nixos/modules/services/display-managers/sddm.nix
+++ b/nixos/modules/services/display-managers/sddm.nix
@@ -66,7 +66,14 @@ let
       HideShells = "/run/current-system/sw/bin/nologin";
     };
 
-    X11 = optionalAttrs xcfg.enable {
+    Wayland = {
+      EnableHiDPI = cfg.enableHidpi;
+      SessionDir = "${dmcfg.sessionData.desktops}/share/wayland-sessions";
+      CompositorCommand = lib.optionalString cfg.wayland.enable cfg.wayland.compositorCommand;
+    };
+
+  } // optionalAttrs xcfg.enable {
+    X11 = {
       MinimumVT = if xcfg.tty != null then xcfg.tty else 7;
       ServerPath = toString xserverWrapper;
       XephyrPath = "${pkgs.xorg.xorgserver.out}/bin/Xephyr";
@@ -77,12 +84,6 @@ let
       DisplayStopCommand = toString Xstop;
       EnableHiDPI = cfg.enableHidpi;
     };
-
-    Wayland = {
-      EnableHiDPI = cfg.enableHidpi;
-      SessionDir = "${dmcfg.sessionData.desktops}/share/wayland-sessions";
-      CompositorCommand = lib.optionalString cfg.wayland.enable cfg.wayland.compositorCommand;
-    };
   } // optionalAttrs dmcfg.autoLogin.enable {
     Autologin = {
       User = dmcfg.autoLogin.user;
diff --git a/nixos/modules/services/games/archisteamfarm.nix b/nixos/modules/services/games/archisteamfarm.nix
index 33898f8387e99..c9c41d6f4eb5e 100644
--- a/nixos/modules/services/games/archisteamfarm.nix
+++ b/nixos/modules/services/games/archisteamfarm.nix
@@ -164,8 +164,11 @@ in
   };
 
   config = lib.mkIf cfg.enable {
-    # TODO: drop with 24.11
-    services.archisteamfarm.dataDir = lib.mkIf (lib.versionAtLeast config.system.stateVersion "24.05") (lib.mkDefault "/var/lib/asf");
+    services.archisteamfarm = {
+      # TODO: drop with 24.11
+      dataDir = lib.mkIf (lib.versionAtLeast config.system.stateVersion "24.05") (lib.mkDefault "/var/lib/asf");
+      settings.IPC = lib.mkIf (!cfg.web-ui.enable) false;
+    };
 
     users = {
       users.archisteamfarm = {
diff --git a/nixos/modules/services/hardware/kanata.nix b/nixos/modules/services/hardware/kanata.nix
index 46af3e36b9859..60fb33881f256 100644
--- a/nixos/modules/services/hardware/kanata.nix
+++ b/nixos/modules/services/hardware/kanata.nix
@@ -7,7 +7,7 @@ let
 
   upstreamDoc = "See [the upstream documentation](https://github.com/jtroo/kanata/blob/main/docs/config.adoc) and [example config files](https://github.com/jtroo/kanata/tree/main/cfg_samples) for more information.";
 
-  keyboard = {
+  keyboard = { name, config, ... }: {
     options = {
       devices = mkOption {
         type = types.listOf types.str;
@@ -48,6 +48,21 @@ let
           ${upstreamDoc}
         '';
       };
+      configFile = mkOption {
+        type = types.path;
+        default = mkConfig name config;
+        defaultText =
+          "A config file generated by values from other kanata module options.";
+        description = ''
+          The config file.
+
+          By default, it is generated by values from other kanata
+          module options.
+
+          You can also set it to your own full config file which
+          overrides all other kanata module options.  ${upstreamDoc}
+        '';
+      };
       extraArgs = mkOption {
         type = types.listOf types.str;
         default = [ ];
@@ -85,6 +100,10 @@ let
 
       ${keyboard.config}
     '';
+    # Only the config file generated by this module is checked.  A
+    # user-provided one is not checked because it may not be available
+    # at build time.  I think this is a good balance between module
+    # complexity and functionality.
     checkPhase = ''
       ${getExe cfg.package} --cfg "$target" --check --debug
     '';
@@ -96,7 +115,7 @@ let
       Type = "notify";
       ExecStart = ''
         ${getExe cfg.package} \
-          --cfg ${mkConfig name keyboard} \
+          --cfg ${keyboard.configFile} \
           --symlink-path ''${RUNTIME_DIRECTORY}/${name} \
           ${optionalString (keyboard.port != null) "--port ${toString keyboard.port}"} \
           ${utils.escapeSystemdExecArgs keyboard.extraArgs}
diff --git a/nixos/modules/services/hardware/thermald.nix b/nixos/modules/services/hardware/thermald.nix
index 4f9202d13d903..fb7cf3735a7ea 100644
--- a/nixos/modules/services/hardware/thermald.nix
+++ b/nixos/modules/services/hardware/thermald.nix
@@ -28,7 +28,13 @@ in
       configFile = mkOption {
         type = types.nullOr types.path;
         default = null;
-        description = "the thermald manual configuration file.";
+        description = ''
+          The thermald manual configuration file.
+
+          Leave unspecified to run with the `--adaptive` flag instead which will have thermald use your computer's DPTF adaptive tables.
+
+          See `man thermald` for more information.
+        '';
       };
 
       package = mkPackageOption pkgs "thermald" { };
@@ -49,9 +55,8 @@ in
             --no-daemon \
             ${optionalString cfg.debug "--loglevel=debug"} \
             ${optionalString cfg.ignoreCpuidCheck "--ignore-cpuid-check"} \
-            ${optionalString (cfg.configFile != null) "--config-file ${cfg.configFile}"} \
-            --dbus-enable \
-            --adaptive
+            ${if cfg.configFile != null then "--config-file ${cfg.configFile}" else "--adaptive"} \
+            --dbus-enable
         '';
       };
     };
diff --git a/nixos/modules/services/home-automation/wyoming/faster-whisper.nix b/nixos/modules/services/home-automation/wyoming/faster-whisper.nix
index d0fca6a41c7b6..45664103665f7 100644
--- a/nixos/modules/services/home-automation/wyoming/faster-whisper.nix
+++ b/nixos/modules/services/home-automation/wyoming/faster-whisper.nix
@@ -113,6 +113,9 @@ in
       nameValuePair "wyoming-faster-whisper-${server}" {
         inherit (options) enable;
         description = "Wyoming faster-whisper server instance ${server}";
+        wants = [
+          "network-online.target"
+        ];
         after = [
           "network-online.target"
         ];
diff --git a/nixos/modules/services/home-automation/wyoming/openwakeword.nix b/nixos/modules/services/home-automation/wyoming/openwakeword.nix
index 856a4ef7366d0..f9848970bf734 100644
--- a/nixos/modules/services/home-automation/wyoming/openwakeword.nix
+++ b/nixos/modules/services/home-automation/wyoming/openwakeword.nix
@@ -108,6 +108,9 @@ in
   config = mkIf cfg.enable {
     systemd.services."wyoming-openwakeword" = {
       description = "Wyoming openWakeWord server";
+      wants = [
+        "network-online.target"
+      ];
       after = [
         "network-online.target"
       ];
diff --git a/nixos/modules/services/home-automation/wyoming/piper.nix b/nixos/modules/services/home-automation/wyoming/piper.nix
index 5b5f898d7ca35..a26fe8e84f609 100644
--- a/nixos/modules/services/home-automation/wyoming/piper.nix
+++ b/nixos/modules/services/home-automation/wyoming/piper.nix
@@ -117,6 +117,9 @@ in
       nameValuePair "wyoming-piper-${server}" {
         inherit (options) enable;
         description = "Wyoming Piper server instance ${server}";
+        wants = [
+          "network-online.target"
+        ];
         after = [
           "network-online.target"
         ];
diff --git a/nixos/modules/services/mail/stalwart-mail.nix b/nixos/modules/services/mail/stalwart-mail.nix
index 9cc919fd117d6..06b48c86907c5 100644
--- a/nixos/modules/services/mail/stalwart-mail.nix
+++ b/nixos/modules/services/mail/stalwart-mail.nix
@@ -7,11 +7,28 @@ let
   configFormat = pkgs.formats.toml { };
   configFile = configFormat.generate "stalwart-mail.toml" cfg.settings;
   dataDir = "/var/lib/stalwart-mail";
+  stalwartAtLeast = versionAtLeast cfg.package.version;
 
 in {
   options.services.stalwart-mail = {
     enable = mkEnableOption "the Stalwart all-in-one email server";
-    package = mkPackageOption pkgs "stalwart-mail" { };
+
+    package = mkOption {
+      type = types.package;
+      description = ''
+        Which package to use for the Stalwart mail server.
+
+        ::: {.note}
+        Upgrading from version 0.6.0 to version 0.7.0 or higher requires manual
+        intervention. See <https://github.com/stalwartlabs/mail-server/blob/main/UPGRADING.md>
+        for upgrade instructions.
+        :::
+      '';
+      default = pkgs.stalwart-mail_0_6;
+      defaultText = lib.literalExpression "pkgs.stalwart-mail_0_6";
+      example = lib.literalExpression "pkgs.stalwart-mail";
+      relatedPackages = [ "stalwart-mail_0_6" "stalwart-mail" ];
+    };
 
     settings = mkOption {
       inherit (configFormat) type;
@@ -26,6 +43,18 @@ in {
   };
 
   config = mkIf cfg.enable {
+
+    warnings = lib.optionals (!stalwartAtLeast "0.7.0") [
+      ''
+        Versions of stalwart-mail < 0.7.0 will get deprecated in NixOS 24.11.
+        Please set services.stalwart-mail.package to pkgs.stalwart-mail to
+        upgrade to the latest version.
+        Please note that upgrading to version >= 0.7 requires manual
+        intervention, see <https://github.com/stalwartlabs/mail-server/blob/main/UPGRADING.md>
+        for upgrade instructions.
+      ''
+    ];
+
     # Default config: all local
     services.stalwart-mail.settings = {
       global.tracing.method = mkDefault "stdout";
@@ -38,9 +67,12 @@ in {
       store.blob.path = mkDefault "${dataDir}/data/blobs";
       storage.data = mkDefault "db";
       storage.fts = mkDefault "db";
+      storage.lookup = mkDefault "db";
       storage.blob = mkDefault "blob";
       resolver.type = mkDefault "system";
-      resolver.public-suffix = mkDefault ["https://publicsuffix.org/list/public_suffix_list.dat"];
+      resolver.public-suffix = lib.mkDefault [
+        "file://${pkgs.publicsuffix-list}/share/publicsuffix/public_suffix_list.dat"
+      ];
     };
 
     systemd.services.stalwart-mail = {
diff --git a/nixos/modules/services/misc/bcg.nix b/nixos/modules/services/misc/bcg.nix
index 626a67f66d08b..63c441833d958 100644
--- a/nixos/modules/services/misc/bcg.nix
+++ b/nixos/modules/services/misc/bcg.nix
@@ -149,20 +149,20 @@ in
     systemd.services.bcg = let
       envConfig = cfg.environmentFiles != [];
       finalConfig = if envConfig
-                    then "$RUNTIME_DIRECTORY/bcg.config.yaml"
+                    then "\${RUNTIME_DIRECTORY}/bcg.config.yaml"
                     else configFile;
     in {
       description = "BigClown Gateway";
       wantedBy = [ "multi-user.target" ];
       wants = [ "network-online.target" ] ++ lib.optional config.services.mosquitto.enable "mosquitto.service";
       after = [ "network-online.target" ];
-      preStart = ''
+      preStart = mkIf envConfig ''
         umask 077
         ${pkgs.envsubst}/bin/envsubst -i "${configFile}" -o "${finalConfig}"
         '';
       serviceConfig = {
         EnvironmentFile = cfg.environmentFiles;
-        ExecStart="${cfg.package}/bin/bcg -c ${finalConfig} -v ${cfg.verbose}";
+        ExecStart = "${cfg.package}/bin/bcg -c ${finalConfig} -v ${cfg.verbose}";
         RuntimeDirectory = "bcg";
       };
     };
diff --git a/nixos/modules/services/misc/devpi-server.nix b/nixos/modules/services/misc/devpi-server.nix
new file mode 100644
index 0000000000000..0234db4bc2c5b
--- /dev/null
+++ b/nixos/modules/services/misc/devpi-server.nix
@@ -0,0 +1,128 @@
+{
+  pkgs,
+  lib,
+  config,
+  ...
+}:
+with lib;
+let
+  cfg = config.services.devpi-server;
+
+  secretsFileName = "devpi-secret-file";
+
+  stateDirName = "devpi";
+
+  runtimeDir = "/run/${stateDirName}";
+  serverDir = "/var/lib/${stateDirName}";
+in
+{
+  options.services.devpi-server = {
+    enable = mkEnableOption "Devpi Server";
+
+    package = mkPackageOption pkgs "devpi-server" { };
+
+    primaryUrl = mkOption {
+      type = types.str;
+      description = "Url for the primary node. Required option for replica nodes.";
+    };
+
+    replica = mkOption {
+      type = types.bool;
+      default = false;
+      description = ''
+        Run node as a replica.
+        Requires the secretFile option and the primaryUrl to be enabled.
+      '';
+    };
+
+    secretFile = mkOption {
+      type = types.nullOr types.path;
+      default = null;
+      description = ''
+        Path to a shared secret file used for synchronization,
+        Required for all nodes in a replica/primary setup.
+      '';
+    };
+
+    host = mkOption {
+      type = types.str;
+      default = "localhost";
+      description = ''
+        domain/ip address to listen on
+      '';
+    };
+
+    port = mkOption {
+      type = types.port;
+      default = 3141;
+      description = "The port on which Devpi Server will listen.";
+    };
+
+    openFirewall = mkEnableOption "opening the default ports in the firewall for Devpi Server";
+  };
+
+  config = mkIf cfg.enable {
+
+    systemd.services.devpi-server = {
+      enable = true;
+      description = "devpi PyPI-compatible server";
+      documentation = [ "https://devpi.net/docs/devpi/devpi/stable/+d/index.html" ];
+      wants = [ "network-online.target" ];
+      wantedBy = [ "multi-user.target" ];
+      after = [ "network-online.target" ];
+      # Since at least devpi-server 6.10.0, devpi requires the secrets file to
+      # have 0600 permissions.
+      preStart =
+        ''
+          cp ${cfg.secretFile} ${runtimeDir}/${secretsFileName}
+          chmod 0600 ${runtimeDir}/*${secretsFileName}
+
+          if [ -f ${serverDir}/.nodeinfo ]; then
+            # already initialized the package index, exit gracefully
+            exit 0
+          fi
+          ${cfg.package}/bin/devpi-init --serverdir ${serverDir} ''
+        + strings.optionalString cfg.replica "--role=replica --master-url=${cfg.primaryUrl}";
+
+      serviceConfig = {
+        Restart = "always";
+        ExecStart =
+          let
+            args =
+              [
+                "--request-timeout=5"
+                "--serverdir=${serverDir}"
+                "--host=${cfg.host}"
+                "--port=${builtins.toString cfg.port}"
+              ]
+              ++ lib.optionals (! isNull cfg.secretFile) [
+                "--secretfile=${runtimeDir}/${secretsFileName}"
+              ]
+              ++ (
+                if cfg.replica then
+                  [
+                    "--role=replica"
+                    "--master-url=${cfg.primaryUrl}"
+                  ]
+                else
+                  [ "--role=master" ]
+              );
+          in
+          "${cfg.package}/bin/devpi-server ${concatStringsSep " " args}";
+        DynamicUser = true;
+        StateDirectory = stateDirName;
+        RuntimeDirectory = stateDirName;
+        PrivateDevices = true;
+        PrivateTmp = true;
+        ProtectHome = true;
+        ProtectSystem = "strict";
+      };
+    };
+
+    networking.firewall = mkIf cfg.openFirewall {
+      allowedTCPPorts = [ cfg.port ];
+    };
+
+    meta.maintainers = [ cafkafk ];
+  };
+}
diff --git a/nixos/modules/services/misc/llama-cpp.nix b/nixos/modules/services/misc/llama-cpp.nix
index c73cff027e224..2fa1a7b28e3b1 100644
--- a/nixos/modules/services/misc/llama-cpp.nix
+++ b/nixos/modules/services/misc/llama-cpp.nix
@@ -92,7 +92,6 @@ in {
         SystemCallFilter = [
           "@system-service"
           "~@privileged"
-          "~@resources"
         ];
         SystemCallErrorNumber = "EPERM";
         ProtectProc = "invisible";
diff --git a/nixos/modules/services/misc/plex.nix b/nixos/modules/services/misc/plex.nix
index fcd8ebbac6edd..212abda5d1e0b 100644
--- a/nixos/modules/services/misc/plex.nix
+++ b/nixos/modules/services/misc/plex.nix
@@ -93,6 +93,17 @@ in
         '';
       };
 
+      accelerationDevices = mkOption {
+        type = types.listOf types.str;
+        default = ["*"];
+        example = [ "/dev/dri/renderD128" ];
+        description = ''
+          A list of device paths to hardware acceleration devices that Plex should
+          have access to. This is useful when transcoding media files.
+          The special value `"*"` will allow all devices.
+        '';
+      };
+
       package = mkPackageOption pkgs "plex" {
         extraDescription = ''
           Plex subscribers may wish to use their own package here,
@@ -133,6 +144,24 @@ in
         KillSignal = "SIGQUIT";
         PIDFile = "${cfg.dataDir}/Plex Media Server/plexmediaserver.pid";
         Restart = "on-failure";
+
+        # Hardening
+        NoNewPrivileges = true;
+        PrivateTmp = true;
+        PrivateDevices = cfg.accelerationDevices == [];
+        DeviceAllow = mkIf (cfg.accelerationDevices != [] && !lib.elem "*" cfg.accelerationDevices) cfg.accelerationDevices;
+        ProtectSystem = true;
+        ProtectHome = true;
+        ProtectControlGroups = true;
+        ProtectKernelModules = true;
+        ProtectKernelTunables = true;
+        RestrictAddressFamilies = ["AF_UNIX" "AF_INET" "AF_INET6" "AF_NETLINK"];
+        # This could be made to work if the namespaces needed were known
+        # RestrictNamespaces = true;
+        RestrictRealtime = true;
+        RestrictSUIDSGID = true;
+        MemoryDenyWriteExecute = true;
+        LockPersonality = true;
       };
 
       environment = {
diff --git a/nixos/modules/services/misc/portunus.nix b/nixos/modules/services/misc/portunus.nix
index bdb35da788e3a..335806b261a23 100644
--- a/nixos/modules/services/misc/portunus.nix
+++ b/nixos/modules/services/misc/portunus.nix
@@ -98,6 +98,10 @@ in
 
           The OIDC secret must be set as the `DEX_CLIENT_''${id}` environment variable
           in the [](#opt-services.dex.environmentFile) setting.
+
+          ::: {.note}
+          Make sure the id only contains characters that are allowed in an environment variable name, e.g. no -.
+          :::
         '';
       };
 
diff --git a/nixos/modules/services/misc/private-gpt.nix b/nixos/modules/services/misc/private-gpt.nix
new file mode 100644
index 0000000000000..9a3e5317cdb14
--- /dev/null
+++ b/nixos/modules/services/misc/private-gpt.nix
@@ -0,0 +1,121 @@
+{ config
+, lib
+, pkgs
+, ...
+}:
+let
+  inherit (lib) types;
+
+  format = pkgs.formats.yaml { };
+  cfg = config.services.private-gpt;
+in
+{
+  options = {
+    services.private-gpt = {
+      enable = lib.mkEnableOption "private-gpt for local large language models";
+      package = lib.mkPackageOption pkgs "private-gpt" { };
+
+      stateDir = lib.mkOption {
+        type = types.path;
+        default = "/var/lib/private-gpt";
+        description = "State directory of private-gpt.";
+      };
+
+      settings = lib.mkOption {
+        type = format.type;
+        default = {
+          llm = {
+            mode = "ollama";
+            tokenizer = "";
+          };
+          embedding = {
+            mode = "ollama";
+          };
+          ollama = {
+            llm_model = "llama3";
+            embedding_model = "nomic-embed-text";
+            api_base = "http://localhost:11434";
+            embedding_api_base = "http://localhost:11434";
+            keep_alive = "5m";
+            tfs_z = 1;
+            top_k = 40;
+            top_p = 0.9;
+            repeat_last_n = 64;
+            repeat_penalty = 1.2;
+            request_timeout = 120;
+          };
+          vectorstore = {
+            database = "qdrant";
+          };
+          qdrant = {
+            path = "/var/lib/private-gpt/vectorstore/qdrant";
+          };
+          data = {
+            local_data_folder = "/var/lib/private-gpt";
+          };
+          openai = { };
+          azopenai = { };
+        };
+        description = ''
+          settings-local.yaml for private-gpt
+        '';
+      };
+    };
+  };
+
+  config = lib.mkIf cfg.enable {
+    systemd.services.private-gpt = {
+      description = "Interact with your documents using the power of GPT, 100% privately, no data leaks";
+      wantedBy = [ "multi-user.target" ];
+      after = [ "network.target" ];
+
+      preStart =
+        let
+          config = format.generate "settings-local.yaml" (cfg.settings // { server.env_name = "local"; });
+        in
+        ''
+          mkdir -p ${cfg.stateDir}/{settings,huggingface,matplotlib,tiktoken_cache}
+          cp ${cfg.package.cl100k_base.tiktoken} ${cfg.stateDir}/tiktoken_cache/9b5ad71b2ce5302211f9c61530b329a4922fc6a4
+          cp ${pkgs.python3Packages.private-gpt}/${pkgs.python3.sitePackages}/private_gpt/settings.yaml ${cfg.stateDir}/settings/settings.yaml
+          cp "${config}" "${cfg.stateDir}/settings/settings-local.yaml"
+          chmod 600 "${cfg.stateDir}/settings/settings-local.yaml"
+        '';
+
+      environment = {
+        PGPT_PROFILES = "local";
+        PGPT_SETTINGS_FOLDER = "${cfg.stateDir}/settings";
+        HF_HOME = "${cfg.stateDir}/huggingface";
+        TRANSFORMERS_OFFLINE = "1";
+        HF_DATASETS_OFFLINE = "1";
+        MPLCONFIGDIR = "${cfg.stateDir}/matplotlib";
+      };
+
+      serviceConfig = {
+        ExecStart = lib.getExe cfg.package;
+        WorkingDirectory = cfg.stateDir;
+        StateDirectory = "private-gpt";
+        RuntimeDirectory = "private-gpt";
+        RuntimeDirectoryMode = "0755";
+        PrivateTmp = true;
+        DynamicUser = true;
+        DevicePolicy = "closed";
+        LockPersonality = true;
+        MemoryDenyWriteExecute = true;
+        PrivateUsers = true;
+        ProtectHome = true;
+        ProtectHostname = true;
+        ProtectKernelLogs = true;
+        ProtectKernelModules = true;
+        ProtectKernelTunables = true;
+        ProtectControlGroups = true;
+        ProcSubset = "pid";
+        RestrictNamespaces = true;
+        RestrictRealtime = true;
+        SystemCallArchitectures = "native";
+        UMask = "0077";
+      };
+    };
+  };
+
+  meta.maintainers = with lib.maintainers; [ drupol ];
+}
diff --git a/nixos/modules/services/misc/snapper.nix b/nixos/modules/services/misc/snapper.nix
index 3a3ed1b5c0f56..a42fca5b60289 100644
--- a/nixos/modules/services/misc/snapper.nix
+++ b/nixos/modules/services/misc/snapper.nix
@@ -103,6 +103,18 @@ in
       '';
     };
 
+    persistentTimer = mkOption {
+      default = false;
+      type = types.bool;
+      example = true;
+      description = ''
+        Set the `Persistent` option for the
+        {manpage}`systemd.timer(5)`
+        which triggers the snapshot immediately if the last trigger
+        was missed (e.g. if the system was powered down).
+      '';
+    };
+
     cleanupInterval = mkOption {
       type = types.str;
       default = "1d";
@@ -198,7 +210,14 @@ in
       inherit documentation;
       requires = [ "local-fs.target" ];
       serviceConfig.ExecStart = "${pkgs.snapper}/lib/snapper/systemd-helper --timeline";
-      startAt = cfg.snapshotInterval;
+    };
+
+    systemd.timers.snapper-timeline = {
+      wantedBy = [ "timers.target" ];
+      timerConfig = {
+        Persistent = cfg.persistentTimer;
+        OnCalendar = cfg.snapshotInterval;
+      };
     };
 
     systemd.services.snapper-cleanup = {
diff --git a/nixos/modules/services/misc/tzupdate.nix b/nixos/modules/services/misc/tzupdate.nix
index eac1e1112a5ab..be63bb179e423 100644
--- a/nixos/modules/services/misc/tzupdate.nix
+++ b/nixos/modules/services/misc/tzupdate.nix
@@ -41,5 +41,5 @@ in {
     };
   };
 
-  meta.maintainers = [ maintainers.michaelpj ];
+  meta.maintainers = [ ];
 }
diff --git a/nixos/modules/services/monitoring/arbtt.nix b/nixos/modules/services/monitoring/arbtt.nix
index 6dad6bdec3284..cf9a236c079c0 100644
--- a/nixos/modules/services/monitoring/arbtt.nix
+++ b/nixos/modules/services/monitoring/arbtt.nix
@@ -45,5 +45,5 @@ in {
     };
   };
 
-  meta.maintainers = [ maintainers.michaelpj ];
+  meta.maintainers = [ ];
 }
diff --git a/nixos/modules/services/monitoring/loki.nix b/nixos/modules/services/monitoring/loki.nix
index ba63f95e7f1a8..de4f1bc7aa23e 100644
--- a/nixos/modules/services/monitoring/loki.nix
+++ b/nixos/modules/services/monitoring/loki.nix
@@ -97,8 +97,20 @@ in {
 
       serviceConfig = let
         conf = if cfg.configFile == null
-               then prettyJSON cfg.configuration
+               then
+                 # Config validation may fail when using extraFlags = [ "-config.expand-env=true" ].
+                 # To work around this, we simply skip it when extraFlags is not empty.
+                 if cfg.extraFlags == []
+                 then validateConfig (prettyJSON cfg.configuration)
+                 else prettyJSON cfg.configuration
                else cfg.configFile;
+        validateConfig = file:
+        pkgs.runCommand "validate-loki-conf" {
+          nativeBuildInputs = [ cfg.package ];
+        } ''
+            loki -verify-config -config.file "${file}"
+            ln -s "${file}" "$out"
+          '';
       in
       {
         ExecStart = "${cfg.package}/bin/loki --config.file=${conf} ${escapeShellArgs cfg.extraFlags}";
diff --git a/nixos/modules/services/networking/hostapd.nix b/nixos/modules/services/networking/hostapd.nix
index 1bef5a1f0a9e8..b678656f2e046 100644
--- a/nixos/modules/services/networking/hostapd.nix
+++ b/nixos/modules/services/networking/hostapd.nix
@@ -687,7 +687,7 @@ in {
                   authentication = {
                     mode = mkOption {
                       default = "wpa3-sae";
-                      type = types.enum ["none" "wpa2-sha256" "wpa3-sae-transition" "wpa3-sae"];
+                      type = types.enum ["none" "wpa2-sha1" "wpa2-sha256" "wpa3-sae-transition" "wpa3-sae"];
                       description = ''
                         Selects the authentication mode for this AP.
 
@@ -695,7 +695,9 @@ in {
                           and create an open AP. Use {option}`settings` together with this option if you
                           want to configure the authentication manually. Any password options will still be
                           effective, if set.
-                        - {var}`"wpa2-sha256"`: WPA2-Personal using SHA256 (IEEE 802.11i/RSN). Passwords are set
+                        - {var}`"wpa2-sha1"`: Not recommended. WPA2-Personal using HMAC-SHA1. Passwords are set
+                          using {option}`wpaPassword` or preferably by {option}`wpaPasswordFile` or {option}`wpaPskFile`.
+                        - {var}`"wpa2-sha256"`: WPA2-Personal using HMAC-SHA256 (IEEE 802.11i/RSN). Passwords are set
                           using {option}`wpaPassword` or preferably by {option}`wpaPasswordFile` or {option}`wpaPskFile`.
                         - {var}`"wpa3-sae-transition"`: Use WPA3-Personal (SAE) if possible, otherwise fallback
                           to WPA2-SHA256. Only use if necessary and switch to the newer WPA3-SAE when possible.
@@ -812,7 +814,7 @@ in {
                         Warning: These entries will get put into a world-readable file in
                         the Nix store! Using {option}`saePasswordFile` instead is recommended.
 
-                        Not used when {option}`mode` is {var}`"wpa2-sha256"`.
+                        Not used when {option}`mode` is {var}`"wpa2-sha1"` or {var}`"wpa2-sha256"`.
                       '';
                       type = types.listOf (types.submodule {
                         options = {
@@ -884,7 +886,7 @@ in {
                         parameters doesn't matter:
                         `<password>[|mac=<peer mac>][|vlanid=<VLAN ID>][|pk=<m:ECPrivateKey-base64>][|id=<identifier>]`
 
-                        Not used when {option}`mode` is {var}`"wpa2-sha256"`.
+                        Not used when {option}`mode` is {var}`"wpa2-sha1"` or {var}`"wpa2-sha256"`.
                       '';
                     };
 
@@ -959,6 +961,9 @@ in {
                   } // optionalAttrs (bssCfg.authentication.mode == "wpa3-sae-transition") {
                     wpa = 2;
                     wpa_key_mgmt = "WPA-PSK-SHA256 SAE";
+                  } // optionalAttrs (bssCfg.authentication.mode == "wpa2-sha1") {
+                    wpa = 2;
+                    wpa_key_mgmt = "WPA-PSK";
                   } // optionalAttrs (bssCfg.authentication.mode == "wpa2-sha256") {
                     wpa = 2;
                     wpa_key_mgmt = "WPA-PSK-SHA256";
@@ -1186,8 +1191,8 @@ in {
                   message = ''hostapd radio ${radio} bss ${bss}: uses WPA3-SAE in transition mode requires defining both a wpa password option and a sae password option'';
                 }
                 {
-                  assertion = auth.mode == "wpa2-sha256" -> countWpaPasswordDefinitions == 1;
-                  message = ''hostapd radio ${radio} bss ${bss}: uses WPA2-SHA256 which requires defining a wpa password option'';
+                  assertion = (auth.mode == "wpa2-sha1" || auth.mode == "wpa2-sha256") -> countWpaPasswordDefinitions == 1;
+                  message = ''hostapd radio ${radio} bss ${bss}: uses WPA2-PSK which requires defining a wpa password option'';
                 }
               ])
               radioCfg.networks))
diff --git a/nixos/modules/services/networking/kea.nix b/nixos/modules/services/networking/kea.nix
index 66173c145d16a..11add600b66fb 100644
--- a/nixos/modules/services/networking/kea.nix
+++ b/nixos/modules/services/networking/kea.nix
@@ -278,6 +278,9 @@ in
         "https://kea.readthedocs.io/en/kea-${package.version}/arm/agent.html"
       ];
 
+      wants = [
+        "network-online.target"
+      ];
       after = [
         "network-online.target"
         "time-sync.target"
diff --git a/nixos/modules/services/networking/oink.nix b/nixos/modules/services/networking/oink.nix
new file mode 100644
index 0000000000000..cd0fdf172331d
--- /dev/null
+++ b/nixos/modules/services/networking/oink.nix
@@ -0,0 +1,84 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.services.oink;
+  makeOinkConfig = attrs: (pkgs.formats.json { }).generate
+    "oink.json" (mapAttrs' (k: v: nameValuePair (toLower k) v) attrs);
+  oinkConfig = makeOinkConfig {
+    global = cfg.settings;
+    domains = cfg.domains;
+  };
+in
+{
+  options.services.oink = {
+    enable = mkEnableOption "Oink, a dynamic DNS client for Porkbun";
+    package = mkPackageOption pkgs "oink" { };
+    settings = {
+      apiKey = mkOption {
+        type = types.str;
+        description = "API key to use when modifying DNS records.";
+      };
+      secretApiKey = mkOption {
+        type = types.str;
+        description = "Secret API key to use when modifying DNS records.";
+      };
+      interval = mkOption {
+        # https://github.com/rlado/oink/blob/v1.1.1/src/main.go#L364
+        type = types.ints.between 60 172800; # 48 hours
+        default = 900;
+        description = "Seconds to wait before sending another request.";
+      };
+      ttl = mkOption {
+        type = types.ints.between 600 172800;
+        default = 600;
+        description = ''
+          The TTL ("Time to Live") value to set for your DNS records.
+
+          The TTL controls how long in seconds your records will be cached
+          for. A smaller value will allow the record to update quicker.
+        '';
+      };
+    };
+    domains = mkOption {
+      type = with types; listOf (attrsOf anything);
+      default = [];
+      example = [
+        {
+          domain = "nixos.org";
+          subdomain = "";
+          ttl = 1200;
+        }
+        {
+          domain = "nixos.org";
+          subdomain = "hydra";
+        }
+      ];
+      description = ''
+        List of attribute sets containing configuration for each domain.
+
+        Each attribute set must have two attributes, one named *domain*
+        and another named *subdomain*. The domain attribute must specify
+        the root domain that you want to configure, and the subdomain
+        attribute must specify its subdomain if any. If you want to
+        configure the root domain rather than a subdomain, leave the
+        subdomain attribute as an empty string.
+
+        Additionally, you can use attributes from *services.oink.settings*
+        to override settings per-domain.
+
+        Every domain listed here *must* have API access enabled in
+        Porkbun's control panel.
+      '';
+    };
+  };
+
+  config = mkIf cfg.enable {
+    systemd.services.oink = {
+      description = "Dynamic DNS client for Porkbun";
+      wantedBy = [ "multi-user.target" ];
+      script = "${cfg.package}/bin/oink -c ${oinkConfig}";
+    };
+  };
+}
diff --git a/nixos/modules/services/networking/pixiecore.nix b/nixos/modules/services/networking/pixiecore.nix
index cfdb8014136ed..111cb7e355040 100644
--- a/nixos/modules/services/networking/pixiecore.nix
+++ b/nixos/modules/services/networking/pixiecore.nix
@@ -82,8 +82,8 @@ in
 
       apiServer = mkOption {
         type = types.str;
-        example = "localhost:8080";
-        description = "host:port to connect to the API. Ignored unless mode is set to 'api'";
+        example = "http://localhost:8080";
+        description = "URI to connect to the API. Ignored unless mode is set to 'api'";
       };
 
       extraArguments = mkOption {
diff --git a/nixos/modules/services/networking/radvd.nix b/nixos/modules/services/networking/radvd.nix
index 4e3e501d2f593..0143324a78155 100644
--- a/nixos/modules/services/networking/radvd.nix
+++ b/nixos/modules/services/networking/radvd.nix
@@ -33,6 +33,17 @@ in
 
     package = mkPackageOption pkgs "radvd" { };
 
+    debugLevel = mkOption {
+      type = types.int;
+      default = 0;
+      example = 5;
+      description = ''
+          The debugging level is an integer in the range from 1 to 5,
+          from quiet to very verbose. A debugging level of 0 completely
+          turns off debugging.
+        '';
+    };
+
     config = mkOption {
       type = types.lines;
       example =
@@ -67,7 +78,7 @@ in
         wantedBy = [ "multi-user.target" ];
         after = [ "network.target" ];
         serviceConfig =
-          { ExecStart = "@${cfg.package}/bin/radvd radvd -n -u radvd -C ${confFile}";
+          { ExecStart = "@${cfg.package}/bin/radvd radvd -n -u radvd -d ${toString cfg.debugLevel} -C ${confFile}";
             Restart = "always";
           };
       };
diff --git a/nixos/modules/services/networking/rosenpass.nix b/nixos/modules/services/networking/rosenpass.nix
index 373a6c7690799..66b6f960a81ab 100644
--- a/nixos/modules/services/networking/rosenpass.nix
+++ b/nixos/modules/services/networking/rosenpass.nix
@@ -225,8 +225,10 @@ in
         # See <https://www.freedesktop.org/software/systemd/man/systemd.unit.html#Specifiers>
         environment.CONFIG = "%t/${serviceConfig.RuntimeDirectory}/config.toml";
 
-        preStart = "${getExe pkgs.envsubst} -i ${config} -o \"$CONFIG\"";
-        script = "rosenpass exchange-config \"$CONFIG\"";
+        script = ''
+          ${getExe pkgs.envsubst} -i ${config} -o "$CONFIG"
+          rosenpass exchange-config "$CONFIG"
+        '';
       };
   };
 }
diff --git a/nixos/modules/services/networking/smokeping.nix b/nixos/modules/services/networking/smokeping.nix
index 38d6e4452c97b..3fb3eac45cc82 100644
--- a/nixos/modules/services/networking/smokeping.nix
+++ b/nixos/modules/services/networking/smokeping.nix
@@ -47,6 +47,13 @@ let
 in
 
 {
+  imports = [
+    (mkRemovedOptionModule [ "services" "smokeping" "port" ] ''
+      The smokeping web service is now served by nginx.
+      In order to change the port, you need to change the nginx configuration under `services.nginx.virtualHosts.smokeping.listen.*.port`.
+    '')
+  ];
+
   options = {
     services.smokeping = {
       enable = mkEnableOption "smokeping service";
@@ -71,8 +78,8 @@ in
       };
       cgiUrl = mkOption {
         type = types.str;
-        default = "http://${cfg.hostName}:${toString cfg.port}/smokeping.cgi";
-        defaultText = literalExpression ''"http://''${hostName}:''${toString port}/smokeping.cgi"'';
+        default = "http://${cfg.hostName}/smokeping.cgi";
+        defaultText = literalExpression ''"http://''${hostName}/smokeping.cgi"'';
         example = "https://somewhere.example.com/smokeping.cgi";
         description = "URL to the smokeping cgi.";
       };
@@ -177,11 +184,6 @@ in
           which makes it bind to all interfaces.
         '';
       };
-      port = mkOption {
-        type = types.port;
-        default = 8081;
-        description = "TCP port to use for the web server.";
-      };
       presentationConfig = mkOption {
         type = types.lines;
         default = ''
@@ -312,17 +314,8 @@ in
       description = "smokeping daemon user";
       home = smokepingHome;
       createHome = true;
-      # When `cfg.webService` is enabled, `thttpd` makes SmokePing available
-      # under `${cfg.host}:${cfg.port}/smokeping.fcgi` as per the `ln -s` below.
-      # We also want that going to `${cfg.host}:${cfg.port}` without `smokeping.fcgi`
-      # makes it easy for the user to find SmokePing.
-      # However `thttpd` does not seem to support easy redirections from `/` to `smokeping.fcgi`
-      # and only allows directory listings or `/` -> `index.html` resolution if the directory
-      # has `chmod 755` (see https://acme.com/software/thttpd/thttpd_man.html#PERMISSIONS,
-      # " directories should be 755 if you want to allow indexing").
-      # Otherwise it shows `403 Forbidden` on `/`.
-      # Thus, we need to make `smokepingHome` (which is given to `thttpd -d` below) `755`.
-      homeMode = "755";
+      # When `cfg.webService` is enabled, `nginx` requires read permissions on the home directory.
+      homeMode = "711";
     };
     users.groups.${cfg.user} = { };
     systemd.services.smokeping = {
@@ -342,21 +335,25 @@ in
         ${cfg.package}/bin/smokeping --static --config=${configPath}
       '';
     };
-    systemd.services.thttpd = mkIf cfg.webService {
-      requiredBy = [ "multi-user.target" ];
-      requires = [ "smokeping.service" ];
-      path = with pkgs; [ bash rrdtool smokeping thttpd ];
-      serviceConfig = {
-        Restart = "always";
-        ExecStart = lib.concatStringsSep " " (lib.concatLists [
-          [ "${pkgs.thttpd}/bin/thttpd" ]
-          [ "-u ${cfg.user}" ]
-          [ ''-c "**.fcgi"'' ]
-          [ "-d ${smokepingHome}" ]
-          (lib.optional (cfg.host != null) "-h ${cfg.host}")
-          [ "-p ${builtins.toString cfg.port}" ]
-          [ "-D -nos" ]
-        ]);
+
+    # use nginx to serve the smokeping web service
+    services.fcgiwrap.enable = mkIf cfg.webService true;
+    services.nginx = mkIf cfg.webService {
+      enable = true;
+      virtualHosts."smokeping" = {
+        serverName = mkDefault cfg.host;
+        locations."/" = {
+          root = smokepingHome;
+          index = "smokeping.fcgi";
+        };
+        locations."/smokeping.fcgi" = {
+          extraConfig = ''
+            include ${config.services.nginx.package}/conf/fastcgi_params;
+            fastcgi_pass unix:${config.services.fcgiwrap.socketAddress};
+            fastcgi_param SCRIPT_FILENAME ${smokepingHome}/smokeping.fcgi;
+            fastcgi_param DOCUMENT_ROOT ${smokepingHome};
+          '';
+        };
       };
     };
   };
diff --git a/nixos/modules/services/networking/tayga.nix b/nixos/modules/services/networking/tayga.nix
index 1a0df33fe883d..9f118b243e90c 100644
--- a/nixos/modules/services/networking/tayga.nix
+++ b/nixos/modules/services/networking/tayga.nix
@@ -16,6 +16,8 @@ let
     prefix ${strAddr cfg.ipv6.pool}
     dynamic-pool ${strAddr cfg.ipv4.pool}
     data-dir ${cfg.dataDir}
+
+    ${concatStringsSep "\n" (mapAttrsToList (ipv4: ipv6: "map " + ipv4 + " " + ipv6) cfg.mappings)}
   '';
 
   addrOpts = v:
@@ -103,18 +105,38 @@ in
       dataDir = mkOption {
         type = types.path;
         default = "/var/lib/tayga";
-        description = "Directory for persistent data";
+        description = "Directory for persistent data.";
       };
 
       tunDevice = mkOption {
         type = types.str;
         default = "nat64";
-        description = "Name of the nat64 tun device";
+        description = "Name of the nat64 tun device.";
+      };
+
+      mappings = mkOption {
+        type = types.attrsOf types.str;
+        default = {};
+        description = "Static IPv4 -> IPv6 host mappings.";
+        example = literalExpression ''
+          {
+            "192.168.5.42" = "2001:db8:1:4444::1";
+            "192.168.5.43" = "2001:db8:1:4444::2";
+            "192.168.255.2" = "2001:db8:1:569::143";
+          }
+        '';
       };
     };
   };
 
   config = mkIf cfg.enable {
+    assertions = [
+      {
+        assertion = allUnique (attrValues cfg.mappings);
+        message = "Neither the IPv4 nor the IPv6 addresses must be entered twice in the mappings.";
+      }
+    ];
+
     networking.interfaces."${cfg.tunDevice}" = {
       virtual = true;
       virtualType = "tun";
diff --git a/nixos/modules/services/networking/vsftpd.nix b/nixos/modules/services/networking/vsftpd.nix
index 25f950600b91c..07b93e92a7509 100644
--- a/nixos/modules/services/networking/vsftpd.nix
+++ b/nixos/modules/services/networking/vsftpd.nix
@@ -278,7 +278,7 @@ in
       }
       {
         assertion = (cfg.enableVirtualUsers -> cfg.userDbPath != null)
-                 && (cfg.enableVirtualUsers -> cfg.localUsers != null);
+                 && (cfg.enableVirtualUsers -> cfg.localUsers);
         message = "vsftpd: If enableVirtualUsers is true, you need to setup both the userDbPath and localUsers options.";
       }];
 
diff --git a/nixos/modules/services/networking/wireguard.nix b/nixos/modules/services/networking/wireguard.nix
index 3f68af3a86c96..81abae2c9303d 100644
--- a/nixos/modules/services/networking/wireguard.nix
+++ b/nixos/modules/services/networking/wireguard.nix
@@ -80,6 +80,15 @@ let
         description = "Commands called at the end of the interface setup.";
       };
 
+      preShutdown = mkOption {
+        example = literalExpression ''"''${pkgs.iproute2}/bin/ip netns del foo"'';
+        default = "";
+        type = with types; coercedTo (listOf str) (concatStringsSep "\n") lines;
+        description = ''
+          Commands called before shutting down the interface.
+        '';
+      };
+
       postShutdown = mkOption {
         example = literalExpression ''"''${pkgs.openresolv}/bin/resolvconf -d wg0"'';
         default = "";
@@ -497,6 +506,7 @@ let
         '';
 
         postStop = ''
+          ${values.preShutdown}
           ${ipPostMove} link del dev "${name}"
           ${values.postShutdown}
         '';
diff --git a/nixos/modules/services/security/bitwarden-directory-connector-cli.nix b/nixos/modules/services/security/bitwarden-directory-connector-cli.nix
index d21322caf4c33..fef4a88648979 100644
--- a/nixos/modules/services/security/bitwarden-directory-connector-cli.nix
+++ b/nixos/modules/services/security/bitwarden-directory-connector-cli.nix
@@ -260,6 +260,7 @@ in {
         description = "Sync timer for Bitwarden Directory Connector";
         wantedBy = ["timers.target"];
         after = ["network-online.target"];
+        wants = ["network-online.target"];
         timerConfig = {
           OnCalendar = cfg.interval;
           Unit = "bitwarden-directory-connector-cli.service";
diff --git a/nixos/modules/services/security/oauth2-proxy-nginx.nix b/nixos/modules/services/security/oauth2-proxy-nginx.nix
index c05bd304752d1..44bf56233e95e 100644
--- a/nixos/modules/services/security/oauth2-proxy-nginx.nix
+++ b/nixos/modules/services/security/oauth2-proxy-nginx.nix
@@ -64,11 +64,11 @@ in
     };
   };
 
-  config.services.oauth2-proxy = lib.mkIf (cfg.virtualHosts != [] && (lib.hasPrefix "127.0.0.1:" cfg.proxy)) {
+  config.services.oauth2-proxy = lib.mkIf (cfg.virtualHosts != {} && (lib.hasPrefix "127.0.0.1:" cfg.proxy)) {
     enable = true;
   };
 
-  config.services.nginx = lib.mkIf (cfg.virtualHosts != [] && config.services.oauth2-proxy.enable) (lib.mkMerge ([
+  config.services.nginx = lib.mkIf (cfg.virtualHosts != {} && config.services.oauth2-proxy.enable) (lib.mkMerge ([
     {
       virtualHosts.${cfg.domain}.locations."/oauth2/" = {
         proxyPass = cfg.proxy;
@@ -78,11 +78,20 @@ in
         '';
       };
     }
-  ] ++ lib.optional (cfg.virtualHosts != []) {
+  ] ++ lib.optional (cfg.virtualHosts != {}) {
     recommendedProxySettings = true; # needed because duplicate headers
   } ++ (lib.mapAttrsToList (vhost: conf: {
     virtualHosts.${vhost} = {
       locations = {
+        "/".extraConfig = ''
+          # pass information via X-User and X-Email headers to backend, requires running with --set-xauthrequest flag
+          proxy_set_header X-User  $user;
+          proxy_set_header X-Email $email;
+
+          # if you enabled --cookie-refresh, this is needed for it to work with auth_request
+          add_header Set-Cookie $auth_cookie;
+        '';
+
         "/oauth2/auth" = let
           maybeQueryArg = name: value:
             if value == null then null
@@ -102,6 +111,7 @@ in
             proxy_pass_request_body           off;
           '';
         };
+
         "@redirectToAuth2ProxyLogin" = {
           return = "307 https://${cfg.domain}/oauth2/start?rd=$scheme://$host$request_uri";
           extraConfig = ''
@@ -114,16 +124,10 @@ in
         auth_request /oauth2/auth;
         error_page 401 = @redirectToAuth2ProxyLogin;
 
-        # pass information via X-User and X-Email headers to backend,
-        # requires running with --set-xauthrequest flag
+        # set variables being used in locations."/".extraConfig
         auth_request_set $user   $upstream_http_x_auth_request_user;
         auth_request_set $email  $upstream_http_x_auth_request_email;
-        proxy_set_header X-User  $user;
-        proxy_set_header X-Email $email;
-
-        # if you enabled --cookie-refresh, this is needed for it to work with auth_request
         auth_request_set $auth_cookie $upstream_http_set_cookie;
-        add_header Set-Cookie $auth_cookie;
       '';
     };
   }) cfg.virtualHosts)));
diff --git a/nixos/modules/services/security/oauth2-proxy.nix b/nixos/modules/services/security/oauth2-proxy.nix
index 78a772845a352..3079a1d030c52 100644
--- a/nixos/modules/services/security/oauth2-proxy.nix
+++ b/nixos/modules/services/security/oauth2-proxy.nix
@@ -577,20 +577,22 @@ in
 
     users.groups.oauth2-proxy = {};
 
-    systemd.services.oauth2-proxy = {
-      description = "OAuth2 Proxy";
-      path = [ cfg.package ];
-      wantedBy = [ "multi-user.target" ];
-      wants = [ "network-online.target" ];
-      after = [ "network-online.target" ];
-
-      serviceConfig = {
-        User = "oauth2-proxy";
-        Restart = "always";
-        ExecStart = "${cfg.package}/bin/oauth2-proxy ${configString}";
-        EnvironmentFile = lib.mkIf (cfg.keyFile != null) cfg.keyFile;
+    systemd.services.oauth2-proxy =
+      let needsKeycloak = lib.elem cfg.provider ["keycloak" "keycloak-oidc"]
+                          && config.services.keycloak.enable;
+      in {
+        description = "OAuth2 Proxy";
+        path = [ cfg.package ];
+        wantedBy = [ "multi-user.target" ];
+        wants = [ "network-online.target" ] ++ lib.optionals needsKeycloak [ "keycloak.service" ];
+        after = [ "network-online.target" ] ++ lib.optionals needsKeycloak [ "keycloak.service" ];
+
+        serviceConfig = {
+          User = "oauth2-proxy";
+          Restart = "always";
+          ExecStart = "${cfg.package}/bin/oauth2-proxy ${configString}";
+          EnvironmentFile = lib.mkIf (cfg.keyFile != null) cfg.keyFile;
+        };
       };
-    };
-
   };
 }
diff --git a/nixos/modules/services/system/dbus.nix b/nixos/modules/services/system/dbus.nix
index 26f4eba707f92..d84136125f934 100644
--- a/nixos/modules/services/system/dbus.nix
+++ b/nixos/modules/services/system/dbus.nix
@@ -128,10 +128,14 @@ in
         contents."/etc/dbus-1".source = pkgs.makeDBusConf {
           inherit (cfg) apparmor;
           suidHelper = "/bin/false";
-          serviceDirectories = [ pkgs.dbus ];
+          serviceDirectories = [ pkgs.dbus config.boot.initrd.systemd.package ];
         };
         packages = [ pkgs.dbus ];
-        storePaths = [ "${pkgs.dbus}/bin/dbus-daemon" ];
+        storePaths = [
+          "${pkgs.dbus}/bin/dbus-daemon"
+          "${config.boot.initrd.systemd.package}/share/dbus-1/system-services"
+          "${config.boot.initrd.systemd.package}/share/dbus-1/system.d"
+        ];
         targets.sockets.wants = [ "dbus.socket" ];
       };
     })
diff --git a/nixos/modules/services/video/frigate.nix b/nixos/modules/services/video/frigate.nix
index 0e6bde447c033..c3ec4a3c76c34 100644
--- a/nixos/modules/services/video/frigate.nix
+++ b/nixos/modules/services/video/frigate.nix
@@ -427,10 +427,6 @@ in
         PrivateTmp = true;
         CacheDirectory = "frigate";
         CacheDirectoryMode = "0750";
-
-        BindPaths = [
-          "/migrations:${cfg.package}/share/frigate/migrations:ro"
-        ];
       };
     };
   };
diff --git a/nixos/modules/services/web-apps/artalk.nix b/nixos/modules/services/web-apps/artalk.nix
new file mode 100644
index 0000000000000..d3d06f1521b6a
--- /dev/null
+++ b/nixos/modules/services/web-apps/artalk.nix
@@ -0,0 +1,131 @@
+{
+  config,
+  lib,
+  pkgs,
+  utils,
+  ...
+}:
+let
+  cfg = config.services.artalk;
+  settingsFormat = pkgs.formats.json { };
+in
+{
+
+  meta = {
+    maintainers = with lib.maintainers; [ moraxyc ];
+  };
+
+  options = {
+    services.artalk = {
+      enable = lib.mkEnableOption "artalk, a comment system";
+      configFile = lib.mkOption {
+        type = lib.types.str;
+        default = "/etc/artalk/config.yml";
+        description = "Artalk config file path. If it is not exist, Artalk will generate one.";
+      };
+      allowModify = lib.mkOption {
+        type = lib.types.bool;
+        default = true;
+        description = "allow Artalk store the settings to config file persistently";
+      };
+      workdir = lib.mkOption {
+        type = lib.types.str;
+        default = "/var/lib/artalk";
+        description = "Artalk working directory";
+      };
+      user = lib.mkOption {
+        type = lib.types.str;
+        default = "artalk";
+        description = "Artalk user name.";
+      };
+
+      group = lib.mkOption {
+        type = lib.types.str;
+        default = "artalk";
+        description = "Artalk group name.";
+      };
+
+      package = lib.mkPackageOption pkgs "artalk" { };
+      settings = lib.mkOption {
+        type = lib.types.submodule {
+          freeformType = settingsFormat.type;
+          options = {
+            host = lib.mkOption {
+              type = lib.types.str;
+              default = "0.0.0.0";
+              description = ''
+                Artalk server listen host
+              '';
+            };
+            port = lib.mkOption {
+              type = lib.types.port;
+              default = 23366;
+              description = ''
+                Artalk server listen port
+              '';
+            };
+          };
+        };
+        default = { };
+        description = ''
+          The artalk configuration.
+
+          If you set allowModify to true, Artalk will be able to store the settings in the config file persistently. This section's content will update in the config file after the service restarts.
+
+          Options containing secret data should be set to an attribute set
+          containing the attribute `_secret` - a string pointing to a file
+          containing the value the option should be set to.
+        '';
+      };
+    };
+  };
+
+  config = lib.mkIf cfg.enable {
+    users.users.artalk = lib.optionalAttrs (cfg.user == "artalk") {
+      description = "artalk user";
+      isSystemUser = true;
+      group = cfg.group;
+    };
+    users.groups.artalk = lib.optionalAttrs (cfg.group == "artalk") { };
+
+    environment.systemPackages = [ cfg.package ];
+
+    systemd.services.artalk = {
+      after = [ "network.target" ];
+      wantedBy = [ "multi-user.target" ];
+      preStart =
+        ''
+          umask 0077
+          ${utils.genJqSecretsReplacementSnippet cfg.settings "/run/artalk/new"}
+        ''
+        + (
+          if cfg.allowModify then
+            ''
+              [ -e "${cfg.configFile}" ] || ${lib.getExe cfg.package} gen config "${cfg.configFile}"
+              cat "${cfg.configFile}" | ${lib.getExe pkgs.yj} > "/run/artalk/old"
+              ${lib.getExe pkgs.jq} -s '.[0] * .[1]' "/run/artalk/old" "/run/artalk/new" > "/run/artalk/result"
+              cat "/run/artalk/result" | ${lib.getExe pkgs.yj} -r > "${cfg.configFile}"
+              rm /run/artalk/{old,new,result}
+            ''
+          else
+            ''
+              cat /run/artalk/new | ${lib.getExe pkgs.yj} -r > "${cfg.configFile}"
+              rm /run/artalk/new
+            ''
+        );
+      serviceConfig = {
+        User = cfg.user;
+        Group = cfg.group;
+        Type = "simple";
+        ExecStart = "${lib.getExe cfg.package} server --config ${cfg.configFile} --workdir ${cfg.workdir} --host ${cfg.settings.host} --port ${builtins.toString cfg.settings.port}";
+        Restart = "on-failure";
+        RestartSec = "5s";
+        ConfigurationDirectory = [ "artalk" ];
+        StateDirectory = [ "artalk" ];
+        RuntimeDirectory = [ "artalk" ];
+        AmbientCapabilities = [ "CAP_NET_BIND_SERVICE" ];
+        ProtectHome = "yes";
+      };
+    };
+  };
+}
diff --git a/nixos/modules/services/web-apps/commafeed.nix b/nixos/modules/services/web-apps/commafeed.nix
new file mode 100644
index 0000000000000..354e3625bb999
--- /dev/null
+++ b/nixos/modules/services/web-apps/commafeed.nix
@@ -0,0 +1,114 @@
+{
+  config,
+  lib,
+  pkgs,
+  ...
+}:
+let
+  cfg = config.services.commafeed;
+in
+{
+  options.services.commafeed = {
+    enable = lib.mkEnableOption "CommaFeed";
+
+    package = lib.mkPackageOption pkgs "commafeed" { };
+
+    user = lib.mkOption {
+      type = lib.types.str;
+      description = "User under which CommaFeed runs.";
+      default = "commafeed";
+    };
+
+    group = lib.mkOption {
+      type = lib.types.str;
+      description = "Group under which CommaFeed runs.";
+      default = "commafeed";
+    };
+
+    stateDir = lib.mkOption {
+      type = lib.types.path;
+      description = "Directory holding all state for CommaFeed to run.";
+      default = "/var/lib/commafeed";
+    };
+
+    environment = lib.mkOption {
+      type = lib.types.attrsOf (
+        lib.types.oneOf [
+          lib.types.bool
+          lib.types.int
+          lib.types.str
+        ]
+      );
+      description = ''
+        Extra environment variables passed to CommaFeed, refer to
+        <https://github.com/Athou/commafeed/blob/master/commafeed-server/config.yml.example>
+        for supported values. The default user is `admin` and the default password is `admin`.
+        Correct configuration for H2 database is already provided.
+      '';
+      default = { };
+      example = {
+        CF_SERVER_APPLICATIONCONNECTORS_0_TYPE = "http";
+        CF_SERVER_APPLICATIONCONNECTORS_0_PORT = 9090;
+      };
+    };
+
+    environmentFile = lib.mkOption {
+      type = lib.types.nullOr lib.types.path;
+      description = ''
+        Environment file as defined in {manpage}`systemd.exec(5)`.
+      '';
+      default = null;
+      example = "/var/lib/commafeed/commafeed.env";
+    };
+  };
+
+  config = lib.mkIf cfg.enable {
+    systemd.services.commafeed = {
+      after = [ "network.target" ];
+      wantedBy = [ "multi-user.target" ];
+      environment = lib.mapAttrs (
+        _: v: if lib.isBool v then lib.boolToString v else toString v
+      ) cfg.environment;
+      serviceConfig = {
+        ExecStart = "${lib.getExe cfg.package} server ${cfg.package}/share/config.yml";
+        User = cfg.user;
+        Group = cfg.group;
+        StateDirectory = baseNameOf cfg.stateDir;
+        WorkingDirectory = cfg.stateDir;
+        # Hardening
+        CapabilityBoundingSet = [ "" ];
+        DevicePolicy = "closed";
+        DynamicUser = true;
+        LockPersonality = true;
+        NoNewPrivileges = true;
+        PrivateDevices = true;
+        PrivateUsers = true;
+        ProcSubset = "pid";
+        ProtectClock = true;
+        ProtectControlGroups = true;
+        ProtectHome = true;
+        ProtectHostname = true;
+        ProtectKernelLogs = true;
+        ProtectKernelModules = true;
+        ProtectKernelTunables = true;
+        ProtectProc = "invisible";
+        ProtectSystem = true;
+        RestrictAddressFamilies = [
+          "AF_INET"
+          "AF_INET6"
+        ];
+        RestrictNamespaces = true;
+        RestrictRealtime = true;
+        RestrictSUIDSGID = true;
+        SystemCallArchitectures = "native";
+        SystemCallFilter = [
+          "@system-service"
+          "~@privileged"
+        ];
+        UMask = "0077";
+      } // lib.optionalAttrs (cfg.environmentFile != null) { EnvironmentFile = cfg.environmentFile; };
+    };
+  };
+
+  meta.maintainers = [ lib.maintainers.raroh73 ];
+}
diff --git a/nixos/modules/services/web-apps/filesender.md b/nixos/modules/services/web-apps/filesender.md
new file mode 100644
index 0000000000000..44d066761b9a4
--- /dev/null
+++ b/nixos/modules/services/web-apps/filesender.md
@@ -0,0 +1,49 @@
+# FileSender {#module-services-filesender}
+
+[FileSender](https://filesender.org/software/) is a software that makes it easy to send and receive big files.
+
+## Quickstart {#module-services-filesender-quickstart}
+
+FileSender uses [SimpleSAMLphp](https://simplesamlphp.org/) for authentication, which needs to be configured separately.
+
+Minimal working instance of FileSender that uses password-authentication would look like this:
+
+```nix
+{
+  networking.firewall.allowedTCPPorts = [ 80 443 ];
+  services.filesender = {
+    enable = true;
+    localDomain = "filesender.example.com";
+    configureNginx = true;
+    database.createLocally = true;
+
+    settings = {
+      auth_sp_saml_authentication_source = "default";
+      auth_sp_saml_uid_attribute = "uid";
+      storage_filesystem_path = "<STORAGE PATH FOR UPLOADED FILES>";
+      admin = "admin";
+      admin_email = "admin@example.com";
+      email_reply_to = "noreply@example.com";
+    };
+  };
+  services.simplesamlphp.filesender = {
+    settings = {
+      "module.enable".exampleauth = true;
+    };
+    authSources = {
+      admin = [ "core:AdminPassword" ];
+      default = format.lib.mkMixedArray [ "exampleauth:UserPass" ] {
+        "admin:admin123" = {
+          uid = [ "admin" ];
+          cn = [ "admin" ];
+          mail = [ "admin@example.com" ];
+        };
+      };
+    };
+  };
+}
+```
+
+::: {.warning}
+Example above uses hardcoded clear-text password, in production you should use other authentication method like LDAP. You can check supported authentication methods [in SimpleSAMLphp documentation](https://simplesamlphp.org/docs/stable/simplesamlphp-idp.html).
+:::
diff --git a/nixos/modules/services/web-apps/filesender.nix b/nixos/modules/services/web-apps/filesender.nix
new file mode 100644
index 0000000000000..bc8d465643f2f
--- /dev/null
+++ b/nixos/modules/services/web-apps/filesender.nix
@@ -0,0 +1,253 @@
+{
+  config,
+  lib,
+  pkgs,
+  ...
+}:
+let
+  format = pkgs.formats.php { finalVariable = "config"; };
+
+  cfg = config.services.filesender;
+  simpleSamlCfg = config.services.simplesamlphp.filesender;
+  fpm = config.services.phpfpm.pools.filesender;
+
+  filesenderConfigDirectory = pkgs.runCommand "filesender-config" { } ''
+    mkdir $out
+    cp ${format.generate "config.php" cfg.settings} $out/config.php
+  '';
+in
+{
+  meta = {
+    maintainers = with lib.maintainers; [ nhnn ];
+    doc = ./filesender.md;
+  };
+
+  options.services.filesender = with lib; {
+    enable = mkEnableOption "FileSender";
+    package = mkPackageOption pkgs "filesender" { };
+    user = mkOption {
+      description = "User under which filesender runs.";
+      type = types.str;
+      default = "filesender";
+    };
+    database = {
+      createLocally = mkOption {
+        type = types.bool;
+        default = true;
+        description = ''
+          Create the PostgreSQL database and database user locally.
+        '';
+      };
+      hostname = mkOption {
+        type = types.str;
+        default = "/run/postgresql";
+        description = "Database hostname.";
+      };
+      port = mkOption {
+        type = types.port;
+        default = 5432;
+        description = "Database port.";
+      };
+      name = mkOption {
+        type = types.str;
+        default = "filesender";
+        description = "Database name.";
+      };
+      user = mkOption {
+        type = types.str;
+        default = "filesender";
+        description = "Database user.";
+      };
+      passwordFile = mkOption {
+        type = types.nullOr types.path;
+        default = null;
+        example = "/run/keys/filesender-dbpassword";
+        description = ''
+          A file containing the password corresponding to
+          [](#opt-services.filesender.database.user).
+        '';
+      };
+    };
+    settings = mkOption {
+      type = types.submodule {
+        freeformType = format.type;
+        options = {
+          site_url = mkOption {
+            type = types.str;
+            description = "Site URL. Used in emails, to build URLs for logging in, logging out, build URL for upload endpoint for web workers, to include scripts etc.";
+          };
+          admin = mkOption {
+            type = types.commas;
+            description = ''
+              UIDs (as per the configured saml_uid_attribute) of FileSender administrators.
+              Accounts with these UIDs can access the Admin page through the web UI.
+            '';
+          };
+          admin_email = mkOption {
+            type = types.commas;
+            description = ''
+              Email address of FileSender administrator(s).
+              Emails regarding disk full etc. are sent here.
+              You should use a role-address here.
+            '';
+          };
+          storage_filesystem_path = mkOption {
+            type = types.nullOr types.str;
+            description = "When using storage type filesystem this is the absolute path to the file system where uploaded files are stored until they expire. Your FileSender storage root.";
+          };
+          log_facilities = mkOption {
+            type = format.type;
+            default = [ { type = "error_log"; } ];
+            description = "Defines where FileSender logging is sent. You can sent logging to a file, to syslog or to the default PHP log facility (as configured through your webserver's PHP module). The directive takes an array of one or more logging targets. Logging can be sent to multiple targets simultaneously. Each logging target is a list containing the name of the logging target and a number of attributes which vary per log target. See below for the exact definiation of each log target.";
+          };
+        };
+      };
+      default = { };
+      description = ''
+        Configuration options used by FileSender.
+        See [](https://docs.filesender.org/filesender/v2.0/admin/configuration/)
+        for available options.
+      '';
+    };
+    configureNginx = mkOption {
+      type = types.bool;
+      default = true;
+      description = "Configure nginx as a reverse proxy for FileSender.";
+    };
+    localDomain = mkOption {
+      type = types.str;
+      example = "filesender.example.org";
+      description = "The domain serving your FileSender instance.";
+    };
+    poolSettings = mkOption {
+      type =
+        with types;
+        attrsOf (oneOf [
+          str
+          int
+          bool
+        ]);
+      default = {
+        "pm" = "dynamic";
+        "pm.max_children" = "32";
+        "pm.start_servers" = "2";
+        "pm.min_spare_servers" = "2";
+        "pm.max_spare_servers" = "4";
+        "pm.max_requests" = "500";
+      };
+      description = ''
+        Options for FileSender's PHP pool. See the documentation on `php-fpm.conf` for details on configuration directives.
+      '';
+    };
+  };
+  config = lib.mkIf cfg.enable {
+    services.simplesamlphp.filesender = {
+      phpfpmPool = "filesender";
+      localDomain = cfg.localDomain;
+      settings.baseurlpath = lib.mkDefault "https://${cfg.localDomain}/saml";
+    };
+
+    services.phpfpm = {
+      pools.filesender = {
+        user = cfg.user;
+        group = config.services.nginx.group;
+        phpEnv = {
+          FILESENDER_CONFIG_DIR = toString filesenderConfigDirectory;
+          SIMPLESAMLPHP_CONFIG_DIR = toString simpleSamlCfg.configDir;
+        };
+        settings = {
+          "listen.owner" = config.services.nginx.user;
+          "listen.group" = config.services.nginx.group;
+        } // cfg.poolSettings;
+      };
+    };
+
+    services.nginx = lib.mkIf cfg.configureNginx {
+      enable = true;
+      virtualHosts.${cfg.localDomain} = {
+        root = "${cfg.package}/www";
+        extraConfig = ''
+          index index.php;
+        '';
+        locations = {
+          "/".extraConfig = ''
+            try_files $uri $uri/ /index.php?args;
+          '';
+          "~ [^/]\\.php(/|$)" = {
+            extraConfig = ''
+              fastcgi_split_path_info  ^(.+\.php)(/.+)$;
+              fastcgi_pass  unix:${fpm.socket};
+              include ${pkgs.nginx}/conf/fastcgi.conf;
+              fastcgi_intercept_errors on;
+              fastcgi_param PATH_INFO       $fastcgi_path_info;
+              fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
+            '';
+          };
+          "~ /\\.".extraConfig = "deny all;";
+        };
+      };
+    };
+
+    services.postgresql = lib.mkIf cfg.database.createLocally {
+      enable = true;
+      ensureDatabases = [ cfg.database.name ];
+      ensureUsers = [
+        {
+          name = cfg.database.user;
+          ensureDBOwnership = true;
+        }
+      ];
+    };
+
+    services.filesender.settings = lib.mkMerge [
+      (lib.mkIf cfg.database.createLocally {
+        db_host = "/run/postgresql";
+        db_port = "5432";
+        db_password = "."; # FileSender requires it even when on UNIX socket auth.
+      })
+      (lib.mkIf (!cfg.database.createLocally) {
+        db_host = cfg.database.hostname;
+        db_port = toString cfg.database.port;
+        db_password = format.lib.mkRaw "file_get_contents('${cfg.database.passwordFile}')";
+      })
+      {
+        site_url = lib.mkDefault "https://${cfg.localDomain}";
+        db_type = "pgsql";
+        db_username = cfg.database.user;
+        db_database = cfg.database.name;
+        "auth_sp_saml_simplesamlphp_url" = "/saml";
+        "auth_sp_saml_simplesamlphp_location" = "${simpleSamlCfg.libDir}";
+      }
+    ];
+
+    systemd.services.filesender-initdb = {
+      description = "Init filesender DB";
+
+      wantedBy = [
+        "multi-user.target"
+        "phpfpm-filesender.service"
+      ];
+      after = [ "postgresql.service" ];
+
+      restartIfChanged = true;
+
+      serviceConfig = {
+        Environment = [
+          "FILESENDER_CONFIG_DIR=${toString filesenderConfigDirectory}"
+          "SIMPLESAMLPHP_CONFIG_DIR=${toString simpleSamlCfg.configDir}"
+        ];
+        Type = "oneshot";
+        Group = config.services.nginx.group;
+        User = "filesender";
+        ExecStart = "${fpm.phpPackage}/bin/php ${cfg.package}/scripts/upgrade/database.php";
+      };
+    };
+
+    users.extraUsers.filesender = lib.mkIf (cfg.user == "filesender") {
+      home = "/var/lib/filesender";
+      group = config.services.nginx.group;
+      createHome = true;
+      isSystemUser = true;
+    };
+  };
+}
diff --git a/nixos/modules/services/web-apps/flarum.nix b/nixos/modules/services/web-apps/flarum.nix
new file mode 100644
index 0000000000000..a967c3b121bd6
--- /dev/null
+++ b/nixos/modules/services/web-apps/flarum.nix
@@ -0,0 +1,210 @@
+{ pkgs, lib, config, ... }:
+
+with lib;
+
+let
+  cfg = config.services.flarum;
+
+  flarumInstallConfig = pkgs.writeText "config.json" (builtins.toJSON {
+    debug = false;
+    offline = false;
+
+    baseUrl = cfg.baseUrl;
+    databaseConfiguration = cfg.database;
+    adminUser = {
+      username = cfg.adminUser;
+      password = cfg.initialAdminPassword;
+      email = cfg.adminEmail;
+    };
+    settings = {
+      forum_title = cfg.forumTitle;
+    };
+  });
+in {
+  options.services.flarum = {
+    enable = mkEnableOption "Flarum discussion platform";
+
+    package = mkPackageOption pkgs "flarum" { };
+
+    forumTitle = mkOption {
+      type = types.str;
+      default = "A Flarum Forum on NixOS";
+      description = "Title of the forum.";
+    };
+
+    domain = mkOption {
+      type = types.str;
+      default = "localhost";
+      example = "forum.example.com";
+      description = "Domain to serve on.";
+    };
+
+    baseUrl = mkOption {
+      type = types.str;
+      default = "http://localhost";
+      example = "https://forum.example.com";
+      description = "Change `domain` instead.";
+    };
+
+    adminUser = mkOption {
+      type = types.str;
+      default = "flarum";
+      description = "Username for first web application administrator";
+    };
+
+    adminEmail = mkOption {
+      type = types.str;
+      default = "admin@example.com";
+      description = "Email for first web application administrator";
+    };
+
+    initialAdminPassword = mkOption {
+      type = types.str;
+      default = "flarum";
+      description = "Initial password for the adminUser";
+    };
+
+    user = mkOption {
+      type = types.str;
+      default = "flarum";
+      description = "System user to run Flarum";
+    };
+
+    group = mkOption {
+      type = types.str;
+      default = "flarum";
+      description = "System group to run Flarum";
+    };
+
+    stateDir = mkOption {
+      type = types.path;
+      default = "/var/lib/flarum";
+      description = "Home directory for writable storage";
+    };
+
+    database = mkOption rec {
+      type = with types; attrsOf (oneOf [str bool int]);
+      description = "MySQL database parameters";
+      default = {
+        # the database driver; i.e. MySQL; MariaDB...
+        driver = "mysql";
+        # the host of the connection; localhost in most cases unless using an external service
+        host = "localhost";
+        # the name of the database in the instance
+        database = "flarum";
+        # database username
+        username = "flarum";
+        # database password
+        password = "";
+        # the prefix for the tables; useful if you are sharing the same database with another service
+        prefix = "";
+        # the port of the connection; defaults to 3306 with MySQL
+        port = 3306;
+        strict = false;
+      };
+    };
+
+    createDatabaseLocally = mkOption {
+      type = types.bool;
+      default = true;
+      description = "Create the database and database user locally, and run installation.";
+    };
+  };
+
+  config = mkIf cfg.enable {
+    users.users.${cfg.user} = {
+      isSystemUser = true;
+      home = cfg.stateDir;
+      createHome = true;
+      group = cfg.group;
+    };
+    users.groups.${cfg.group} = {};
+
+    services.phpfpm.pools.flarum = {
+      user = cfg.user;
+      settings = {
+        "listen.owner" = config.services.nginx.user;
+        "listen.group" = config.services.nginx.group;
+        "listen.mode" = "0600";
+        "pm" = mkDefault "dynamic";
+        "pm.max_children" = mkDefault 10;
+        "pm.max_requests" = mkDefault 500;
+        "pm.start_servers" = mkDefault 2;
+        "pm.min_spare_servers" = mkDefault 1;
+        "pm.max_spare_servers" = mkDefault 3;
+      };
+      phpOptions = ''
+        error_log = syslog
+        log_errors = on
+      '';
+    };
+
+    services.nginx = {
+      enable = true;
+      virtualHosts."${cfg.domain}" = {
+        root = "${cfg.stateDir}/public";
+        locations."~ \.php$".extraConfig = ''
+          fastcgi_pass unix:${config.services.phpfpm.pools.flarum.socket};
+          fastcgi_index site.php;
+        '';
+        extraConfig = ''
+          index index.php;
+          include ${cfg.package}/share/php/flarum/.nginx.conf;
+        '';
+      };
+    };
+
+    services.mysql = mkIf cfg.enable {
+      enable = true;
+      package = pkgs.mysql;
+      ensureDatabases = [cfg.database.database];
+      ensureUsers = [
+        {
+          name = cfg.database.username;
+          ensurePermissions = {
+            "${cfg.database.database}.*" = "ALL PRIVILEGES";
+          };
+        }
+      ];
+    };
+
+    assertions = [
+      {
+        assertion = !cfg.createDatabaseLocally || cfg.database.driver == "mysql";
+        message = "Flarum can only be automatically installed in MySQL/MariaDB.";
+      }
+    ];
+
+    systemd.services.flarum-install = {
+      description = "Flarum installation";
+      requiredBy = ["phpfpm-flarum.service"];
+      before = ["phpfpm-flarum.service"];
+      requires = ["mysql.service"];
+      after = ["mysql.service"];
+      serviceConfig = {
+        Type = "oneshot";
+        User = cfg.user;
+        Group = cfg.group;
+      };
+      path = [config.services.phpfpm.phpPackage];
+      script = ''
+        mkdir -p ${cfg.stateDir}/{extensions,public/assets/avatars}
+        mkdir -p ${cfg.stateDir}/storage/{cache,formatter,sessions,views}
+        cd ${cfg.stateDir}
+        cp -f ${cfg.package}/share/php/flarum/{extend.php,site.php,flarum} .
+        ln -sf ${cfg.package}/share/php/flarum/vendor .
+        ln -sf ${cfg.package}/share/php/flarum/public/index.php public/
+        chmod a+x . public
+        chmod +x site.php extend.php flarum
+      '' + optionalString (cfg.createDatabaseLocally && cfg.database.driver == "mysql") ''
+        if [ ! -f config.php ]; then
+            php flarum install --file=${flarumInstallConfig}
+        fi
+        php flarum migrate
+        php flarum cache:clear
+      '';
+    };
+  };
+
+  meta.maintainers = with lib.maintainers; [ fsagbuya jasonodoom ];
+}
diff --git a/nixos/modules/services/web-apps/keycloak.nix b/nixos/modules/services/web-apps/keycloak.nix
index 201085daa74a8..6d472cf48cd01 100644
--- a/nixos/modules/services/web-apps/keycloak.nix
+++ b/nixos/modules/services/web-apps/keycloak.nix
@@ -466,7 +466,8 @@ in
       confFile = pkgs.writeText "keycloak.conf" (keycloakConfig filteredConfig);
       keycloakBuild = cfg.package.override {
         inherit confFile;
-        plugins = cfg.package.enabledPlugins ++ cfg.plugins;
+        plugins = cfg.package.enabledPlugins ++ cfg.plugins ++
+                  (with cfg.package.plugins; [quarkus-systemd-notify quarkus-systemd-notify-deployment]);
       };
     in
     mkIf cfg.enable
@@ -638,6 +639,8 @@ in
               RuntimeDirectory = "keycloak";
               RuntimeDirectoryMode = "0700";
               AmbientCapabilities = "CAP_NET_BIND_SERVICE";
+              Type = "notify";  # Requires quarkus-systemd-notify plugin
+              NotifyAccess = "all";
             };
             script = ''
               set -o errexit -o pipefail -o nounset -o errtrace
diff --git a/nixos/modules/services/web-apps/miniflux.nix b/nixos/modules/services/web-apps/miniflux.nix
index d65d6db3cdaaa..61243a63c582e 100644
--- a/nixos/modules/services/web-apps/miniflux.nix
+++ b/nixos/modules/services/web-apps/miniflux.nix
@@ -1,7 +1,7 @@
 { config, lib, pkgs, ... }:
 
-with lib;
 let
+  inherit (lib) mkEnableOption mkPackageOption mkOption types literalExpression mkIf mkDefault;
   cfg = config.services.miniflux;
 
   defaultAddress = "localhost:8080";
@@ -20,8 +20,8 @@ in
 
       package = mkPackageOption pkgs "miniflux" { };
 
-      createDatabaseLocally = lib.mkOption {
-        type = lib.types.bool;
+      createDatabaseLocally = mkOption {
+        type = types.bool;
         default = true;
         description = ''
           Whether a PostgreSQL database should be automatically created and
@@ -66,6 +66,7 @@ in
       DATABASE_URL = lib.mkIf cfg.createDatabaseLocally "user=miniflux host=/run/postgresql dbname=miniflux";
       RUN_MIGRATIONS = 1;
       CREATE_ADMIN = 1;
+      WATCHDOG = 1;
     };
 
     services.postgresql = lib.mkIf cfg.createDatabaseLocally {
@@ -96,12 +97,18 @@ in
         ++ lib.optionals cfg.createDatabaseLocally [ "postgresql.service" "miniflux-dbsetup.service" ];
 
       serviceConfig = {
-        ExecStart = "${cfg.package}/bin/miniflux";
+        Type = "notify";
+        ExecStart = lib.getExe cfg.package;
         User = "miniflux";
         DynamicUser = true;
         RuntimeDirectory = "miniflux";
         RuntimeDirectoryMode = "0750";
         EnvironmentFile = cfg.adminCredentialsFile;
+        WatchdogSec = 60;
+        WatchdogSignal = "SIGKILL";
+        Restart = "always";
+        RestartSec = 5;
+
         # Hardening
         CapabilityBoundingSet = [ "" ];
         DeviceAllow = [ "" ];
diff --git a/nixos/modules/services/web-apps/nextcloud.nix b/nixos/modules/services/web-apps/nextcloud.nix
index 36c8d2ed6dbd4..91d03dc160779 100644
--- a/nixos/modules/services/web-apps/nextcloud.nix
+++ b/nixos/modules/services/web-apps/nextcloud.nix
@@ -797,7 +797,7 @@ in {
 
   config = mkIf cfg.enable (mkMerge [
     { warnings = let
-        latest = 28;
+        latest = 29;
         upgradeWarning = major: nixos:
           ''
             A legacy Nextcloud install (from before NixOS ${nixos}) may be installed.
diff --git a/nixos/modules/services/web-apps/nextjs-ollama-llm-ui.nix b/nixos/modules/services/web-apps/nextjs-ollama-llm-ui.nix
new file mode 100644
index 0000000000000..d58210c8d9610
--- /dev/null
+++ b/nixos/modules/services/web-apps/nextjs-ollama-llm-ui.nix
@@ -0,0 +1,87 @@
+{
+  config,
+  pkgs,
+  lib,
+  ...
+}:
+let
+  cfg = config.services.nextjs-ollama-llm-ui;
+  # we have to override the URL to a Ollama service here, because it gets baked into the web app.
+  nextjs-ollama-llm-ui = cfg.package.override { ollamaUrl = "https://ollama.lambdablob.com"; };
+in
+{
+  options = {
+    services.nextjs-ollama-llm-ui = {
+      enable = lib.mkEnableOption ''
+        Simple Ollama web UI service; an easy to use web frontend for a Ollama backend service.
+        Run state-of-the-art AI large language models (LLM) similar to ChatGPT locally with privacy
+        on your personal computer.
+        This service is stateless and doesn't store any data on the server; all data is kept
+        locally in your web browser.
+        See https://github.com/jakobhoeg/nextjs-ollama-llm-ui.
+
+        Required: You need the Ollama backend service running by having
+        "services.nextjs-ollama-llm-ui.ollamaUrl" point to the correct url.
+        You can host such a backend service with NixOS through "services.ollama".
+      '';
+      package = lib.mkPackageOption pkgs "nextjs-ollama-llm-ui" { };
+
+      hostname = lib.mkOption {
+        type = lib.types.str;
+        default = "127.0.0.1";
+        example = "ui.example.org";
+        description = ''
+          The hostname under which the Ollama UI interface should be accessible.
+          By default it uses localhost/127.0.0.1 to be accessible only from the local machine.
+          Change to "0.0.0.0" to make it directly accessible from the local network.
+
+          Note: You should keep it at 127.0.0.1 and only serve to the local
+          network or internet from a (home) server behind a reverse-proxy and secured encryption.
+          See https://wiki.nixos.org/wiki/Nginx for instructions on how to set up a reverse-proxy.
+        '';
+      };
+
+      port = lib.mkOption {
+        type = lib.types.port;
+        default = 3000;
+        example = 3000;
+        description = ''
+          The port under which the Ollama UI interface should be accessible.
+        '';
+      };
+
+      ollamaUrl = lib.mkOption {
+        type = lib.types.str;
+        default = "127.0.0.1:11434";
+        example = "https://ollama.example.org";
+        description = ''
+          The address (including host and port) under which we can access the Ollama backend server.
+          !Note that if the the UI service is running under a domain "https://ui.example.org",
+          the Ollama backend service must allow "CORS" requests from this domain, e.g. by adding
+          "services.ollama.environment.OLLAMA_ORIGINS = [ ... "https://ui.example.org" ];"!
+        '';
+      };
+    };
+  };
+
+  config = lib.mkIf cfg.enable {
+    systemd.services = {
+
+      nextjs-ollama-llm-ui = {
+        wantedBy = [ "multi-user.target" ];
+        description = "Nextjs Ollama LLM Ui.";
+        after = [ "network.target" ];
+        environment = {
+          HOSTNAME = cfg.hostname;
+          PORT = toString cfg.port;
+          NEXT_PUBLIC_OLLAMA_URL = cfg.ollamaUrl;
+        };
+        serviceConfig = {
+          ExecStart = "${lib.getExe nextjs-ollama-llm-ui}";
+          DynamicUser = true;
+        };
+      };
+    };
+  };
+  meta.maintainers = with lib.maintainers; [ malteneuss ];
+}
diff --git a/nixos/modules/services/web-apps/pretalx.nix b/nixos/modules/services/web-apps/pretalx.nix
index b062a8b7eeeac..1411d11982c87 100644
--- a/nixos/modules/services/web-apps/pretalx.nix
+++ b/nixos/modules/services/web-apps/pretalx.nix
@@ -11,20 +11,25 @@ let
 
   configFile = format.generate "pretalx.cfg" cfg.settings;
 
-  extras = cfg.package.optional-dependencies.redis
-    ++ lib.optionals (cfg.settings.database.backend == "mysql") cfg.package.optional-dependencies.mysql
-    ++ lib.optionals (cfg.settings.database.backend == "postgresql") cfg.package.optional-dependencies.postgres;
-
-  pythonEnv = cfg.package.python.buildEnv.override {
-    extraLibs = [ (cfg.package.python.pkgs.toPythonModule cfg.package) ]
-      ++ (with cfg.package.python.pkgs; [ gunicorn ]
-      ++ lib.optional cfg.celery.enable celery) ++ extras;
+  finalPackage = cfg.package.override {
+    inherit (cfg) plugins;
+  };
+
+  pythonEnv = finalPackage.python.buildEnv.override {
+    extraLibs = with finalPackage.python.pkgs; [
+      (toPythonModule finalPackage)
+      gunicorn
+    ]
+    ++ finalPackage.optional-dependencies.redis
+    ++ lib.optionals cfg.celery.enable [ celery ]
+    ++ lib.optionals (cfg.settings.database.backend == "mysql") finalPackage.optional-dependencies.mysql
+    ++ lib.optionals (cfg.settings.database.backend == "postgresql") finalPackage.optional-dependencies.postgres;
   };
 in
 
 {
   meta = with lib; {
-    maintainers = teams.c3d2.members;
+    maintainers = with maintainers; [ hexa] ++ teams.c3d2.members;
   };
 
   options.services.pretalx = {
@@ -44,6 +49,20 @@ in
       description = "User under which pretalx should run.";
     };
 
+    plugins = lib.mkOption {
+      type = with lib.types; listOf package;
+      default = [];
+      example = lib.literalExpression ''
+        with config.services.pretalx.package.plugins; [
+          pages
+          youtube
+        ];
+      '';
+      description = ''
+        Pretalx plugins to install into the Python environment.
+      '';
+    };
+
     gunicorn.extraArgs = lib.mkOption {
       type = with lib.types; listOf str;
       default = [
@@ -329,10 +348,47 @@ in
         serviceConfig = {
           User = "pretalx";
           Group = "pretalx";
-          StateDirectory = [ "pretalx" "pretalx/media" ];
+          StateDirectory = [
+            "pretalx"
+            "pretalx/media"
+          ];
+          StateDirectoryMode = "0750";
           LogsDirectory = "pretalx";
           WorkingDirectory = cfg.settings.filesystem.data;
           SupplementaryGroups = [ "redis-pretalx" ];
+          AmbientCapabilities = "";
+          CapabilityBoundingSet = [ "" ];
+          DevicePolicy = "closed";
+          LockPersonality = true;
+          MemoryDenyWriteExecute = true;
+          NoNewPrivileges = true;
+          PrivateDevices = true;
+          PrivateTmp = true;
+          ProcSubset = "pid";
+          ProtectControlGroups = true;
+          ProtectHome = true;
+          ProtectHostname = true;
+          ProtectKernelLogs = true;
+          ProtectKernelModules = true;
+          ProtectKernelTunables = true;
+          ProtectProc = "invisible";
+          ProtectSystem = "strict";
+          RemoveIPC = true;
+          RestrictAddressFamilies = [
+            "AF_INET"
+            "AF_INET6"
+            "AF_UNIX"
+          ];
+          RestrictNamespaces = true;
+          RestrictRealtime = true;
+          RestrictSUIDSGID = true;
+          SystemCallArchitectures = "native";
+          SystemCallFilter = [
+            "@system-service"
+            "~@privileged"
+            "@chown"
+          ];
+          UMask = "0027";
         };
       };
     in {
@@ -395,6 +451,8 @@ in
         wantedBy = [ "multi-user.target" ];
         serviceConfig.ExecStart = "${lib.getExe' pythonEnv "celery"} -A pretalx.celery_app worker ${cfg.celery.extraArgs}";
       });
+
+      nginx.serviceConfig.SupplementaryGroups = lib.mkIf cfg.nginx.enable [ "pretalx" ];
     };
 
     systemd.sockets.pretalx-web.socketConfig = {
@@ -403,11 +461,9 @@ in
     };
 
     users = {
-      groups."${cfg.group}" = {};
-      users."${cfg.user}" = {
+      groups.${cfg.group} = {};
+      users.${cfg.user} = {
         isSystemUser = true;
-        createHome = true;
-        home = cfg.settings.filesystem.data;
         inherit (cfg) group;
       };
     };
diff --git a/nixos/modules/services/web-apps/pretix.nix b/nixos/modules/services/web-apps/pretix.nix
index 22ee9769aa923..498face7456db 100644
--- a/nixos/modules/services/web-apps/pretix.nix
+++ b/nixos/modules/services/web-apps/pretix.nix
@@ -468,7 +468,7 @@ in
           StateDirectory = [
             "pretix"
           ];
-          StateDirectoryMode = "0755";
+          StateDirectoryMode = "0750";
           CacheDirectory = "pretix";
           LogsDirectory = "pretix";
           WorkingDirectory = cfg.settings.pretix.datadir;
@@ -507,7 +507,7 @@ in
             "~@privileged"
             "@chown"
           ];
-          UMask = "0022";
+          UMask = "0027";
         };
       };
     in {
@@ -561,6 +561,8 @@ in
         wantedBy = [ "multi-user.target" ];
         serviceConfig.ExecStart = "${getExe' pythonEnv "celery"} -A pretix.celery_app worker ${cfg.celery.extraArgs}";
       };
+
+      nginx.serviceConfig.SupplementaryGroups = mkIf cfg.nginx.enable [ "pretix" ];
     };
 
     systemd.sockets.pretix-web.socketConfig = {
@@ -569,11 +571,9 @@ in
     };
 
     users = {
-      groups."${cfg.group}" = {};
-      users."${cfg.user}" = {
+      groups.${cfg.group} = {};
+      users.${cfg.user} = {
         isSystemUser = true;
-        createHome = true;
-        home = cfg.settings.pretix.datadir;
         inherit (cfg) group;
       };
     };
diff --git a/nixos/modules/services/web-apps/simplesamlphp.nix b/nixos/modules/services/web-apps/simplesamlphp.nix
new file mode 100644
index 0000000000000..e970266fc17dd
--- /dev/null
+++ b/nixos/modules/services/web-apps/simplesamlphp.nix
@@ -0,0 +1,128 @@
+{
+  config,
+  lib,
+  pkgs,
+  ...
+}:
+let
+  cfg = config.services.simplesamlphp;
+
+  format = pkgs.formats.php { finalVariable = "config"; };
+
+  generateConfig =
+    opts:
+    pkgs.runCommand "simplesamlphp-config" { } ''
+      mkdir $out
+      cp ${format.generate "config.php" opts.settings} $out/config.php
+      cp ${format.generate "authsources.php" opts.authSources} $out/authsources.php
+    '';
+in
+{
+  meta = {
+    maintainers = with lib.maintainers; [ nhnn ];
+  };
+
+  options.services.simplesamlphp =
+    with lib;
+    mkOption {
+      type = types.attrsOf (
+        types.submodule (
+          { config, ... }:
+          {
+            options = {
+              package = mkPackageOption pkgs "simplesamlphp" { };
+              configureNginx = mkOption {
+                type = types.bool;
+                default = true;
+                description = "Configure nginx as a reverse proxy for SimpleSAMLphp.";
+              };
+              phpfpmPool = mkOption {
+                type = types.str;
+                description = "The PHP-FPM pool that serves SimpleSAMLphp instance.";
+              };
+              localDomain = mkOption {
+                type = types.str;
+                description = "The domain serving your SimpleSAMLphp instance. This option modifies only /saml route.";
+              };
+              settings = mkOption {
+                type = types.submodule {
+                  freeformType = format.type;
+                  options = {
+                    baseurlpath = mkOption {
+                      type = types.str;
+                      example = "https://filesender.example.com/saml/";
+                      description = "URL where SimpleSAMLphp can be reached.";
+                    };
+                  };
+                };
+                default = { };
+                description = ''
+                  Configuration options used by SimpleSAMLphp.
+                  See [](https://simplesamlphp.org/docs/stable/simplesamlphp-install)
+                  for available options.
+                '';
+              };
+
+              authSources = mkOption {
+                type = format.type;
+                default = { };
+                description = ''
+                  Auth sources options used by SimpleSAMLphp.
+                '';
+              };
+
+              libDir = mkOption {
+                type = types.str;
+                readOnly = true;
+                description = ''
+                  Path to the SimpleSAMLphp library directory.
+                '';
+              };
+              configDir = mkOption {
+                type = types.str;
+                readOnly = true;
+                description = ''
+                  Path to the SimpleSAMLphp config directory.
+                '';
+              };
+            };
+            config = {
+              libDir = "${config.package}/share/php/simplesamlphp/";
+              configDir = "${generateConfig config}";
+            };
+          }
+        )
+      );
+      default = { };
+      description = "Instances of SimpleSAMLphp. This module is designed to work with already existing PHP-FPM pool and NGINX virtualHost.";
+    };
+
+  config = {
+    services.phpfpm.pools = lib.mapAttrs' (
+      phpfpmName: opts:
+      lib.nameValuePair opts.phpfpmPool { phpEnv.SIMPLESAMLPHP_CONFIG_DIR = "${generateConfig opts}"; }
+    ) cfg;
+
+    services.nginx.virtualHosts = lib.mapAttrs' (
+      phpfpmName: opts:
+      lib.nameValuePair opts.localDomain (
+        lib.mkIf opts.configureNginx {
+          locations."^~ /saml/" = {
+            alias = "${opts.package}/share/php/simplesamlphp/www/";
+            extraConfig = ''
+                location ~ ^(?<prefix>/saml)(?<phpfile>.+?\.php)(?<pathinfo>/.*)?$ {
+                  include ${pkgs.nginx}/conf/fastcgi.conf;
+                  fastcgi_split_path_info  ^(.+\.php)(/.+)$;
+                  fastcgi_pass  unix:${config.services.phpfpm.pools.${phpfpmName}.socket};
+                  fastcgi_intercept_errors on;
+                  fastcgi_param SCRIPT_FILENAME $document_root$phpfile;
+                  fastcgi_param SCRIPT_NAME /saml$phpfile;
+                  fastcgi_param PATH_INFO $pathinfo if_not_empty;
+              }
+            '';
+          };
+        }
+      )
+    ) cfg;
+  };
+}
diff --git a/nixos/modules/services/web-apps/your_spotify.nix b/nixos/modules/services/web-apps/your_spotify.nix
new file mode 100644
index 0000000000000..3eb2ffef4f933
--- /dev/null
+++ b/nixos/modules/services/web-apps/your_spotify.nix
@@ -0,0 +1,191 @@
+{
+  pkgs,
+  config,
+  lib,
+  ...
+}: let
+  inherit
+    (lib)
+    boolToString
+    concatMapAttrs
+    concatStrings
+    isBool
+    mapAttrsToList
+    mkEnableOption
+    mkIf
+    mkOption
+    mkPackageOption
+    optionalAttrs
+    types
+    mkDefault
+    ;
+  cfg = config.services.your_spotify;
+
+  configEnv = concatMapAttrs (name: value:
+    optionalAttrs (value != null) {
+      ${name} =
+        if isBool value
+        then boolToString value
+        else toString value;
+    })
+  cfg.settings;
+
+  configFile = pkgs.writeText "your_spotify.env" (concatStrings (mapAttrsToList (name: value: "${name}=${value}\n") configEnv));
+in {
+  options.services.your_spotify = let
+    inherit (types) nullOr port str path package;
+  in {
+    enable = mkEnableOption "your_spotify";
+
+    enableLocalDB = mkEnableOption "a local mongodb instance";
+    nginxVirtualHost = mkOption {
+      type = nullOr str;
+      default = null;
+      description = ''
+        If set creates an nginx virtual host for the client.
+        In most cases this should be the CLIENT_ENDPOINT without
+        protocol prefix.
+      '';
+    };
+
+    package = mkPackageOption pkgs "your_spotify" {};
+
+    clientPackage = mkOption {
+      type = package;
+      description = "Client package to use.";
+    };
+
+    spotifySecretFile = mkOption {
+      type = path;
+      description = ''
+        A file containing the secret key of your Spotify application.
+        Refer to: [Creating the Spotify Application](https://github.com/Yooooomi/your_spotify#creating-the-spotify-application).
+      '';
+    };
+
+    settings = mkOption {
+      description = ''
+        Your Spotify Configuration. Refer to [Your Spotify](https://github.com/Yooooomi/your_spotify) for definitions and values.
+      '';
+      example = lib.literalExpression ''
+        {
+          CLIENT_ENDPOINT = "https://example.com";
+          API_ENDPOINT = "https://api.example.com";
+          SPOTIFY_PUBLIC = "spotify_client_id";
+        }
+      '';
+      type = types.submodule {
+        freeformType = types.attrsOf types.str;
+        options = {
+          CLIENT_ENDPOINT = mkOption {
+            type = str;
+            description = ''
+              The endpoint of your web application.
+              Has to include a protocol Prefix (e.g. `http://`)
+            '';
+            example = "https://your_spotify.example.org";
+          };
+          API_ENDPOINT = mkOption {
+            type = str;
+            description = ''
+              The endpoint of your server
+              This api has to be reachable from the device you use the website from not from the server.
+              This means that for example you may need two nginx virtual hosts if you want to expose this on the
+              internet.
+              Has to include a protocol Prefix (e.g. `http://`)
+            '';
+            example = "https://localhost:3000";
+          };
+          SPOTIFY_PUBLIC = mkOption {
+            type = str;
+            description = ''
+              The public client ID of your Spotify application.
+              Refer to: [Creating the Spotify Application](https://github.com/Yooooomi/your_spotify#creating-the-spotify-application)
+            '';
+          };
+          MONGO_ENDPOINT = mkOption {
+            type = str;
+            description = ''The endpoint of the Mongo database.'';
+            default = "mongodb://localhost:27017/your_spotify";
+          };
+          PORT = mkOption {
+            type = port;
+            description = "The port of the api server";
+            default = 3000;
+          };
+        };
+      };
+    };
+  };
+
+  config = mkIf cfg.enable {
+    services.your_spotify.clientPackage = mkDefault (cfg.package.client.override {apiEndpoint = cfg.settings.API_ENDPOINT;});
+    systemd.services.your_spotify = {
+      after = ["network.target"];
+      script = ''
+        export SPOTIFY_SECRET=$(< "$CREDENTIALS_DIRECTORY/SPOTIFY_SECRET")
+        ${lib.getExe' cfg.package "your_spotify_migrate"}
+        exec ${lib.getExe cfg.package}
+      '';
+      serviceConfig = {
+        User = "your_spotify";
+        Group = "your_spotify";
+        DynamicUser = true;
+        EnvironmentFile = [configFile];
+        StateDirectory = "your_spotify";
+        LimitNOFILE = "1048576";
+        PrivateTmp = true;
+        PrivateDevices = true;
+        StateDirectoryMode = "0700";
+        Restart = "always";
+
+        LoadCredential = ["SPOTIFY_SECRET:${cfg.spotifySecretFile}"];
+
+        # Hardening
+        CapabilityBoundingSet = "";
+        LockPersonality = true;
+        #MemoryDenyWriteExecute = true; # Leads to coredump because V8 does JIT
+        PrivateUsers = true;
+        ProtectClock = true;
+        ProtectControlGroups = true;
+        ProtectHome = true;
+        ProtectHostname = true;
+        ProtectKernelLogs = true;
+        ProtectKernelModules = true;
+        ProtectKernelTunables = true;
+        ProtectProc = "invisible";
+        ProcSubset = "pid";
+        ProtectSystem = "strict";
+        RestrictAddressFamilies = [
+          "AF_INET"
+          "AF_INET6"
+          "AF_NETLINK"
+        ];
+        RestrictNamespaces = true;
+        RestrictRealtime = true;
+        SystemCallArchitectures = "native";
+        SystemCallFilter = [
+          "@system-service"
+          "@pkey"
+        ];
+        UMask = "0077";
+      };
+      wantedBy = ["multi-user.target"];
+    };
+    services.nginx = mkIf (cfg.nginxVirtualHost != null) {
+      enable = true;
+      virtualHosts.${cfg.nginxVirtualHost} = {
+        root = cfg.clientPackage;
+        locations."/".extraConfig = ''
+          add_header Content-Security-Policy "frame-ancestors 'none';" ;
+          add_header X-Content-Type-Options "nosniff" ;
+          try_files = $uri $uri/ /index.html ;
+        '';
+      };
+    };
+    services.mongodb = mkIf cfg.enableLocalDB {
+      enable = true;
+    };
+  };
+  meta.maintainers = with lib.maintainers; [patrickdag];
+}
diff --git a/nixos/modules/services/web-servers/bluemap.nix b/nixos/modules/services/web-servers/bluemap.nix
new file mode 100644
index 0000000000000..28eaad3db313e
--- /dev/null
+++ b/nixos/modules/services/web-servers/bluemap.nix
@@ -0,0 +1,311 @@
+{ config, lib, pkgs, ... }:
+let
+  cfg = config.services.bluemap;
+  format = pkgs.formats.hocon { };
+
+  coreConfig = format.generate "core.conf" cfg.coreSettings;
+  webappConfig = format.generate "webapp.conf" cfg.webappSettings;
+  webserverConfig = format.generate "webserver.conf" cfg.webserverSettings;
+
+  mapsFolder = pkgs.linkFarm "maps"
+    (lib.attrsets.mapAttrs' (name: value:
+      lib.nameValuePair "${name}.conf"
+        (format.generate "${name}.conf" value))
+      cfg.maps);
+
+  storageFolder = pkgs.linkFarm "storage"
+    (lib.attrsets.mapAttrs' (name: value:
+      lib.nameValuePair "${name}.conf"
+        (format.generate "${name}.conf" value))
+      cfg.storage);
+
+  configFolder = pkgs.linkFarm "bluemap-config" {
+    "maps" = mapsFolder;
+    "storages" = storageFolder;
+    "core.conf" = coreConfig;
+    "webapp.conf" = webappConfig;
+    "webserver.conf" = webserverConfig;
+    "resourcepacks" = pkgs.linkFarm "resourcepacks" cfg.resourcepacks;
+  };
+
+  inherit (lib) mkOption;
+in {
+  options.services.bluemap = {
+    enable = lib.mkEnableOption "bluemap";
+
+    eula = mkOption {
+      type = lib.types.bool;
+      description = ''
+        By changing this option to true you confirm that you own a copy of minecraft Java Edition,
+        and that you agree to minecrafts EULA.
+      '';
+      default = false;
+    };
+
+    defaultWorld = mkOption {
+      type = lib.types.path;
+      description = ''
+        The world used by the default map ruleset.
+        If you configure your own maps you do not need to set this.
+      '';
+      example = lib.literalExpression "\${config.services.minecraft.dataDir}/world";
+    };
+
+    enableRender = mkOption {
+      type = lib.types.bool;
+      description = "Enable rendering";
+      default = true;
+    };
+
+    webRoot = mkOption {
+      type = lib.types.path;
+      default = "/var/lib/bluemap/web";
+      description = "The directory for saving and serving the webapp and the maps";
+    };
+
+    enableNginx = mkOption {
+      type = lib.types.bool;
+      default = true;
+      description = "Enable configuring a virtualHost for serving the bluemap webapp";
+    };
+
+    host = mkOption {
+      type = lib.types.str;
+      default = "bluemap.${config.networking.domain}";
+      defaultText = lib.literalExpression "bluemap.\${config.networking.domain}";
+      description = "Domain to configure nginx for";
+    };
+
+    onCalendar = mkOption {
+      type = lib.types.str;
+      description = ''
+        How often to trigger rendering the map,
+        in the format of a systemd timer onCalendar configuration.
+        See {manpage}`systemd.timer(5)`.
+      '';
+      default = "*-*-* 03:10:00";
+    };
+
+    coreSettings = mkOption {
+      type = lib.types.submodule {
+        freeformType = format.type;
+        options = {
+          data = mkOption {
+            type = lib.types.path;
+            description = "Folder for where bluemap stores its data";
+            default = "/var/lib/bluemap";
+          };
+          metrics = lib.mkEnableOption "Sending usage metrics containing the version of bluemap in use";
+        };
+      };
+      description = "Settings for the core.conf file, [see upstream docs](https://github.com/BlueMap-Minecraft/BlueMap/blob/master/BlueMapCommon/src/main/resources/de/bluecolored/bluemap/config/core.conf).";
+    };
+
+    webappSettings = mkOption {
+      type = lib.types.submodule {
+        freeformType = format.type;
+      };
+      default = {
+        enabled = true;
+        webroot = cfg.webRoot;
+      };
+      defaultText = lib.literalExpression ''
+        {
+          enabled = true;
+          webroot = config.services.bluemap.webRoot;
+        }
+      '';
+      description = "Settings for the webapp.conf file, see [upstream docs](https://github.com/BlueMap-Minecraft/BlueMap/blob/master/BlueMapCommon/src/main/resources/de/bluecolored/bluemap/config/webapp.conf).";
+    };
+
+    webserverSettings = mkOption {
+      type = lib.types.submodule {
+        freeformType = format.type;
+        options = {
+          enabled = mkOption {
+            type = lib.types.bool;
+            description = ''
+              Enable bluemap's built-in webserver.
+              Disabled by default in nixos for use of nginx directly.
+            '';
+            default = false;
+          };
+        };
+      };
+      default = { };
+      description = ''
+        Settings for the webserver.conf file, usually not required.
+        [See upstream docs](https://github.com/BlueMap-Minecraft/BlueMap/blob/master/BlueMapCommon/src/main/resources/de/bluecolored/bluemap/config/webserver.conf).
+      '';
+    };
+
+    maps = mkOption {
+      type = lib.types.attrsOf (lib.types.submodule {
+        freeformType = format.type;
+        options = {
+          world = lib.mkOption {
+            type = lib.types.path;
+            description = "Path to world folder containing the dimension to render";
+          };
+        };
+      });
+      default = {
+        "overworld" = {
+          world = "${cfg.defaultWorld}";
+          ambient-light = 0.1;
+          cave-detection-ocean-floor = -5;
+        };
+
+        "nether" = {
+          world = "${cfg.defaultWorld}/DIM-1";
+          sorting = 100;
+          sky-color = "#290000";
+          void-color = "#150000";
+          ambient-light = 0.6;
+          world-sky-light = 0;
+          remove-caves-below-y = -10000;
+          cave-detection-ocean-floor = -5;
+          cave-detection-uses-block-light = true;
+          max-y = 90;
+        };
+
+        "end" = {
+          world = "${cfg.defaultWorld}/DIM1";
+          sorting = 200;
+          sky-color = "#080010";
+          void-color = "#080010";
+          ambient-light = 0.6;
+          world-sky-light = 0;
+          remove-caves-below-y = -10000;
+          cave-detection-ocean-floor = -5;
+        };
+      };
+      defaultText = lib.literalExpression ''
+        {
+          "overworld" = {
+            world = "''${cfg.defaultWorld}";
+            ambient-light = 0.1;
+            cave-detection-ocean-floor = -5;
+          };
+
+          "nether" = {
+            world = "''${cfg.defaultWorld}/DIM-1";
+            sorting = 100;
+            sky-color = "#290000";
+            void-color = "#150000";
+            ambient-light = 0.6;
+            world-sky-light = 0;
+            remove-caves-below-y = -10000;
+            cave-detection-ocean-floor = -5;
+            cave-detection-uses-block-light = true;
+            max-y = 90;
+          };
+
+          "end" = {
+            world = "''${cfg.defaultWorld}/DIM1";
+            sorting = 200;
+            sky-color = "#080010";
+            void-color = "#080010";
+            ambient-light = 0.6;
+            world-sky-light = 0;
+            remove-caves-below-y = -10000;
+            cave-detection-ocean-floor = -5;
+          };
+        };
+      '';
+      description = ''
+        Settings for files in `maps/`.
+        If you define anything here you must define everything yourself.
+        See the default for an example with good options for the different world types.
+        For valid values [consult upstream docs](https://github.com/BlueMap-Minecraft/BlueMap/blob/master/BlueMapCommon/src/main/resources/de/bluecolored/bluemap/config/maps/map.conf).
+      '';
+    };
+
+    storage = mkOption {
+      type = lib.types.attrsOf (lib.types.submodule {
+        freeformType = format.type;
+        options = {
+          storage-type = mkOption {
+            type = lib.types.enum [ "FILE" "SQL" ];
+            description = "Type of storage config";
+            default = "FILE";
+          };
+        };
+      });
+      description = ''
+        Where the rendered map will be stored.
+        Unless you are doing something advanced you should probably leave this alone and configure webRoot instead.
+        [See upstream docs](https://github.com/BlueMap-Minecraft/BlueMap/tree/master/BlueMapCommon/src/main/resources/de/bluecolored/bluemap/config/storages)
+      '';
+      default = {
+        "file" = {
+          root = "${cfg.webRoot}/maps";
+        };
+      };
+      defaultText = lib.literalExpression ''
+        {
+          "file" = {
+            root = "''${config.services.bluemap.webRoot}/maps";
+          };
+        }
+      '';
+    };
+
+    resourcepacks = mkOption {
+      type = lib.types.attrsOf lib.types.pathInStore;
+      default = { };
+      description = "A set of resourcepacks to use, loaded in alphabetical order";
+    };
+  };
+
+
+  config = lib.mkIf cfg.enable {
+    assertions =
+      [ { assertion = config.services.bluemap.eula;
+          message = ''
+            You have enabled bluemap but have not accepted minecraft's EULA.
+            You can achieve this through setting `services.bluemap.eula = true`
+          '';
+        }
+      ];
+
+    services.bluemap.coreSettings.accept-download = cfg.eula;
+
+    systemd.services."render-bluemap-maps" = lib.mkIf cfg.enableRender {
+      serviceConfig = {
+        Type = "oneshot";
+        Group = "nginx";
+        UMask = "026";
+      };
+      script = ''
+        ${lib.getExe pkgs.bluemap} -c ${configFolder} -gs -r
+      '';
+    };
+
+    systemd.timers."render-bluemap-maps" = lib.mkIf cfg.enableRender {
+      wantedBy = [ "timers.target" ];
+      timerConfig = {
+        OnCalendar = cfg.onCalendar;
+        Persistent = true;
+        Unit = "render-bluemap-maps.service";
+      };
+    };
+
+    services.nginx.virtualHosts = lib.mkIf cfg.enableNginx {
+      "${cfg.host}" = {
+        root = config.services.bluemap.webRoot;
+        locations = {
+          "~* ^/maps/[^/]*/tiles/[^/]*.json$".extraConfig = ''
+            error_page 404 =200 /assets/emptyTile.json;
+            gzip_static always;
+          '';
+          "~* ^/maps/[^/]*/tiles/[^/]*.png$".tryFiles = "$uri =204";
+        };
+      };
+    };
+  };
+
+  meta = {
+    maintainers = with lib.maintainers; [ dandellion h7x4 ];
+  };
+}
diff --git a/nixos/modules/services/web-servers/caddy/default.nix b/nixos/modules/services/web-servers/caddy/default.nix
index 1cd1448c7d567..064a0c71b586b 100644
--- a/nixos/modules/services/web-servers/caddy/default.nix
+++ b/nixos/modules/services/web-servers/caddy/default.nix
@@ -365,7 +365,7 @@ in
         # If the empty string is assigned to this option, the list of commands to start is reset, prior assignments of this option will have no effect.
         ExecStart = [ "" ''${cfg.package}/bin/caddy run ${runOptions} ${optionalString cfg.resume "--resume"}'' ];
         # Validating the configuration before applying it ensures we’ll get a proper error that will be reported when switching to the configuration
-        ExecReload = [ "" ''${cfg.package}/bin/caddy reload ${runOptions} --force'' ];
+        ExecReload = [ "" ] ++ lib.optional cfg.enableReload "${lib.getExe cfg.package} reload ${runOptions} --force";
         User = cfg.user;
         Group = cfg.group;
         ReadWritePaths = [ cfg.dataDir ];
diff --git a/nixos/modules/services/web-servers/garage.nix b/nixos/modules/services/web-servers/garage.nix
index 39ea8f21b126f..8d1966aee091b 100644
--- a/nixos/modules/services/web-servers/garage.nix
+++ b/nixos/modules/services/web-servers/garage.nix
@@ -10,7 +10,7 @@ in
 {
   meta = {
     doc = ./garage.md;
-    maintainers = with pkgs.lib.maintainers; [ raitobezarius ];
+    maintainers = [ ];
   };
 
   options.services.garage = {
@@ -49,15 +49,15 @@ in
 
           data_dir = mkOption {
             default = "/var/lib/garage/data";
-            type = types.path;
-            description = "The main data storage, put this on your large storage (e.g. high capacity HDD)";
-          };
-
-          replication_mode = mkOption {
-            default = "none";
-            type = types.enum ([ "none" "1" "2" "3" "2-dangerous" "3-dangerous" "3-degraded" 1 2 3 ]);
-            apply = v: toString v;
-            description = "Garage replication mode, defaults to none, see: <https://garagehq.deuxfleurs.fr/documentation/reference-manual/configuration/#replication-mode> for reference.";
+            example = [ {
+              path = "/var/lib/garage/data";
+              capacity = "2T";
+            } ];
+            type = with types; either path (listOf attrs);
+            description = ''
+              The directory in which Garage will store the data blocks of objects. This folder can be placed on an HDD.
+              Since v0.9.0, Garage supports multiple data directories, refer to https://garagehq.deuxfleurs.fr/documentation/reference-manual/configuration/#data_dir for the exact format.
+            '';
           };
         };
       };
@@ -71,6 +71,44 @@ in
   };
 
   config = mkIf cfg.enable {
+
+    assertions = [
+      # We removed our module-level default for replication_mode. If a user upgraded
+      # to garage 1.0.0 while relying on the module-level default, they would be left
+      # with a config which evaluates and builds, but then garage refuses to start
+      # because either replication_factor or replication_mode is required.
+      # The replication_factor option also was `toString`'ed before, which is
+      # now not possible anymore, so we prompt the user to change it to a string
+      # if present.
+      # These assertions can be removed in NixOS 24.11, when all users have been
+      # warned once.
+      {
+        assertion = (cfg.settings ? replication_factor || cfg.settings ? replication_mode) || lib.versionOlder cfg.package "1.0.0";
+        message = ''
+          Garage 1.0.0 requires an explicit replication factor to be set.
+          Please set replication_factor to 1 explicitly to preserve the previous behavior.
+          https://git.deuxfleurs.fr/Deuxfleurs/garage/src/tag/v1.0.0/doc/book/reference-manual/configuration.md#replication_factor
+
+        '';
+      }
+      {
+        assertion = lib.isString (cfg.settings.replication_mode or "");
+        message = ''
+          The explicit `replication_mode` option in `services.garage.settings`
+          has been removed and is now handled by the freeform settings in order
+          to allow it being completely absent (for Garage 1.x).
+          That module option previously `toString`'ed the value it's configured
+          with, which is now no longer possible.
+
+          You're still using a non-string here, please manually set it to
+          a string, or migrate to the separate setting keys introduced in 1.x.
+
+          Refer to https://garagehq.deuxfleurs.fr/documentation/working-documents/migration-1/
+          for the migration guide.
+        '';
+      }
+    ];
+
     environment.etc."garage.toml" = {
       source = configFile;
     };
diff --git a/nixos/modules/services/web-servers/nginx/default.nix b/nixos/modules/services/web-servers/nginx/default.nix
index 08fab09e1e559..f9720c3629353 100644
--- a/nixos/modules/services/web-servers/nginx/default.nix
+++ b/nixos/modules/services/web-servers/nginx/default.nix
@@ -142,7 +142,11 @@ let
       default_type application/octet-stream;
   '';
 
-  configFile = pkgs.writers.writeNginxConfig "nginx.conf" ''
+  configFile = (
+      if cfg.validateConfigFile
+      then pkgs.writers.writeNginxConfig
+      else pkgs.writeText
+    ) "nginx.conf" ''
     pid /run/nginx/nginx.pid;
     error_log ${cfg.logError};
     daemon off;
@@ -352,7 +356,7 @@ let
 
         # The acme-challenge location doesn't need to be added if we are not using any automated
         # certificate provisioning and can also be omitted when we use a certificate obtained via a DNS-01 challenge
-        acmeName = if vhost.useACMEHost != null then vhost.useACMEHost else vhostName;
+        acmeName = if vhost.useACMEHost != null then vhost.useACMEHost else vhost.serverName;
         acmeLocation = optionalString ((vhost.enableACME || vhost.useACMEHost != null) && config.security.acme.certs.${acmeName}.dnsProvider == null)
           # Rule for legitimate ACME Challenge requests (like /.well-known/acme-challenge/xxxxxxxxx)
           # We use ^~ here, so that we don't check any regexes (which could
@@ -1082,6 +1086,9 @@ in
         '';
         description = "Declarative vhost config";
       };
+      validateConfigFile = lib.mkEnableOption ''
+        Validate configuration with pkgs.writeNginxConfig.
+      '' // { default = true; };
     };
   };
 
diff --git a/nixos/modules/services/x11/desktop-managers/mate.nix b/nixos/modules/services/x11/desktop-managers/mate.nix
index beae07b70dbfe..19235be4aa8d5 100644
--- a/nixos/modules/services/x11/desktop-managers/mate.nix
+++ b/nixos/modules/services/x11/desktop-managers/mate.nix
@@ -84,6 +84,7 @@ in
       programs.system-config-printer.enable = (mkIf config.services.printing.enable (mkDefault true));
 
       services.gnome.at-spi2-core.enable = true;
+      services.gnome.glib-networking.enable = true;
       services.gnome.gnome-keyring.enable = true;
       services.udev.packages = [ pkgs.mate.mate-settings-daemon ];
       services.gvfs.enable = true;
diff --git a/nixos/modules/services/x11/window-managers/qtile.nix b/nixos/modules/services/x11/window-managers/qtile.nix
index 78152283a0a58..700ead8366008 100644
--- a/nixos/modules/services/x11/window-managers/qtile.nix
+++ b/nixos/modules/services/x11/window-managers/qtile.nix
@@ -4,7 +4,6 @@ with lib;
 
 let
   cfg = config.services.xserver.windowManager.qtile;
-  pyEnv = pkgs.python3.withPackages (p: [ (cfg.package.unwrapped or cfg.package) ] ++ (cfg.extraPackages p));
 in
 
 {
@@ -48,13 +47,24 @@ in
           ];
         '';
       };
+
+    finalPackage = mkOption {
+      type = types.package;
+      visible = false;
+      readOnly = true;
+      description = "The resulting Qtile package, bundled with extra packages";
+    };
   };
 
   config = mkIf cfg.enable {
+    services.xserver.windowManager.qtile.finalPackage = pkgs.python3.withPackages (p:
+      [ (cfg.package.unwrapped or cfg.package) ] ++ (cfg.extraPackages p)
+    );
+
     services.xserver.windowManager.session = [{
       name = "qtile";
       start = ''
-        ${pyEnv}/bin/qtile start -b ${cfg.backend} \
+        ${cfg.finalPackage}/bin/qtile start -b ${cfg.backend} \
         ${optionalString (cfg.configFile != null)
         "--config \"${cfg.configFile}\""} &
         waitPID=$!
diff --git a/nixos/modules/services/x11/xserver.nix b/nixos/modules/services/x11/xserver.nix
index e13c273746701..5a86d055c2719 100644
--- a/nixos/modules/services/x11/xserver.nix
+++ b/nixos/modules/services/x11/xserver.nix
@@ -728,9 +728,6 @@ in
             rm -f /tmp/.X0-lock
           '';
 
-        # TODO: move declaring the systemd service to its own mkIf
-        script = mkIf (config.systemd.services.display-manager.enable == true) "${config.services.displayManager.execCmd}";
-
         # Stop restarting if the display manager stops (crashes) 2 times
         # in one minute. Starting X typically takes 3-4s.
         startLimitIntervalSec = 30;
diff --git a/nixos/modules/system/activation/switchable-system.nix b/nixos/modules/system/activation/switchable-system.nix
index d5bd8cc1dc115..d70fefd0920b4 100644
--- a/nixos/modules/system/activation/switchable-system.nix
+++ b/nixos/modules/system/activation/switchable-system.nix
@@ -4,52 +4,93 @@ let
 
   perlWrapped = pkgs.perl.withPackages (p: with p; [ ConfigIniFiles FileSlurp ]);
 
+  description = extra: ''
+    Whether to include the capability to switch configurations.
+
+    Disabling this makes the system unable to be reconfigured via `nixos-rebuild`.
+
+    ${extra}
+  '';
+
 in
 
 {
 
-  options = {
-    system.switch.enable = lib.mkOption {
+  options.system.switch = {
+    enable = lib.mkOption {
       type = lib.types.bool;
       default = true;
-      description = ''
-        Whether to include the capability to switch configurations.
-
-        Disabling this makes the system unable to be reconfigured via `nixos-rebuild`.
-
+      description = description ''
         This is good for image based appliances where updates are handled
         outside the image. Reducing features makes the image lighter and
         slightly more secure.
       '';
     };
-  };
 
-  config = lib.mkIf config.system.switch.enable {
-    system.activatableSystemBuilderCommands = ''
-      mkdir $out/bin
-      substitute ${./switch-to-configuration.pl} $out/bin/switch-to-configuration \
-        --subst-var out \
-        --subst-var-by toplevel ''${!toplevelVar} \
-        --subst-var-by coreutils "${pkgs.coreutils}" \
-        --subst-var-by distroId ${lib.escapeShellArg config.system.nixos.distroId} \
-        --subst-var-by installBootLoader ${lib.escapeShellArg config.system.build.installBootLoader} \
-        --subst-var-by localeArchive "${config.i18n.glibcLocales}/lib/locale/locale-archive" \
-        --subst-var-by perl "${perlWrapped}" \
-        --subst-var-by shell "${pkgs.bash}/bin/sh" \
-        --subst-var-by su "${pkgs.shadow.su}/bin/su" \
-        --subst-var-by systemd "${config.systemd.package}" \
-        --subst-var-by utillinux "${pkgs.util-linux}" \
-        ;
-
-      chmod +x $out/bin/switch-to-configuration
-      ${lib.optionalString (pkgs.stdenv.hostPlatform == pkgs.stdenv.buildPlatform) ''
-        if ! output=$(${perlWrapped}/bin/perl -c $out/bin/switch-to-configuration 2>&1); then
-          echo "switch-to-configuration syntax is not valid:"
-          echo "$output"
-          exit 1
-        fi
-      ''}
-    '';
+    enableNg = lib.mkOption {
+      type = lib.types.bool;
+      default = false;
+      description = description ''
+        Whether to use `switch-to-configuration-ng`, an experimental
+        re-implementation of `switch-to-configuration` with the goal of
+        replacing the original.
+      '';
+    };
   };
 
+  config = lib.mkMerge [
+    {
+      assertions = [{
+        assertion = with config.system.switch; enable -> !enableNg;
+        message = "Only one of system.switch.enable and system.switch.enableNg may be enabled at a time";
+      }];
+    }
+    (lib.mkIf config.system.switch.enable {
+      system.activatableSystemBuilderCommands = ''
+        mkdir $out/bin
+        substitute ${./switch-to-configuration.pl} $out/bin/switch-to-configuration \
+          --subst-var out \
+          --subst-var-by toplevel ''${!toplevelVar} \
+          --subst-var-by coreutils "${pkgs.coreutils}" \
+          --subst-var-by distroId ${lib.escapeShellArg config.system.nixos.distroId} \
+          --subst-var-by installBootLoader ${lib.escapeShellArg config.system.build.installBootLoader} \
+          --subst-var-by localeArchive "${config.i18n.glibcLocales}/lib/locale/locale-archive" \
+          --subst-var-by perl "${perlWrapped}" \
+          --subst-var-by shell "${pkgs.bash}/bin/sh" \
+          --subst-var-by su "${pkgs.shadow.su}/bin/su" \
+          --subst-var-by systemd "${config.systemd.package}" \
+          --subst-var-by utillinux "${pkgs.util-linux}" \
+          ;
+
+        chmod +x $out/bin/switch-to-configuration
+        ${lib.optionalString (pkgs.stdenv.hostPlatform == pkgs.stdenv.buildPlatform) ''
+          if ! output=$(${perlWrapped}/bin/perl -c $out/bin/switch-to-configuration 2>&1); then
+            echo "switch-to-configuration syntax is not valid:"
+            echo "$output"
+            exit 1
+          fi
+        ''}
+      '';
+    })
+    (lib.mkIf config.system.switch.enableNg {
+      # Use a subshell so we can source makeWrapper's setup hook without
+      # affecting the rest of activatableSystemBuilderCommands.
+      system.activatableSystemBuilderCommands = ''
+        (
+          source ${pkgs.buildPackages.makeWrapper}/nix-support/setup-hook
+
+          mkdir $out/bin
+          ln -sf ${lib.getExe pkgs.switch-to-configuration-ng} $out/bin/switch-to-configuration
+          wrapProgram $out/bin/switch-to-configuration \
+            --set OUT $out \
+            --set TOPLEVEL ''${!toplevelVar} \
+            --set DISTRO_ID ${lib.escapeShellArg config.system.nixos.distroId} \
+            --set INSTALL_BOOTLOADER ${lib.escapeShellArg config.system.build.installBootLoader} \
+            --set LOCALE_ARCHIVE ${config.i18n.glibcLocales}/lib/locale/locale-archive \
+            --set SYSTEMD ${config.systemd.package}
+        )
+      '';
+    })
+  ];
+
 }
diff --git a/nixos/modules/system/boot/binfmt.nix b/nixos/modules/system/boot/binfmt.nix
index 3605ce56910ed..1d702442f7f66 100644
--- a/nixos/modules/system/boot/binfmt.nix
+++ b/nixos/modules/system/boot/binfmt.nix
@@ -280,7 +280,7 @@ in {
   };
 
   config = {
-    boot.binfmt.registrations = builtins.listToAttrs (map (system: {
+    boot.binfmt.registrations = builtins.listToAttrs (map (system: assert system != pkgs.stdenv.hostPlatform.system; {
       name = system;
       value = { config, ... }: let
         interpreter = getEmulator system;
diff --git a/nixos/modules/system/boot/resolved.nix b/nixos/modules/system/boot/resolved.nix
index 64a15179438fe..b658a7a2dc05e 100644
--- a/nixos/modules/system/boot/resolved.nix
+++ b/nixos/modules/system/boot/resolved.nix
@@ -7,6 +7,20 @@ let
   dnsmasqResolve = config.services.dnsmasq.enable &&
                    config.services.dnsmasq.resolveLocalQueries;
 
+  resolvedConf = ''
+    [Resolve]
+    ${optionalString (config.networking.nameservers != [])
+      "DNS=${concatStringsSep " " config.networking.nameservers}"}
+    ${optionalString (cfg.fallbackDns != null)
+      "FallbackDNS=${concatStringsSep " " cfg.fallbackDns}"}
+    ${optionalString (cfg.domains != [])
+      "Domains=${concatStringsSep " " cfg.domains}"}
+    LLMNR=${cfg.llmnr}
+    DNSSEC=${cfg.dnssec}
+    DNSOverTLS=${cfg.dnsovertls}
+    ${config.services.resolved.extraConfig}
+  '';
+
 in
 {
 
@@ -126,60 +140,87 @@ in
       '';
     };
 
-  };
-
-  config = mkIf cfg.enable {
-
-    assertions = [
-      { assertion = !config.networking.useHostResolvConf;
-        message = "Using host resolv.conf is not supported with systemd-resolved";
-      }
-    ];
-
-    users.users.systemd-resolve.group = "systemd-resolve";
-
-    # add resolve to nss hosts database if enabled and nscd enabled
-    # system.nssModules is configured in nixos/modules/system/boot/systemd.nix
-    # added with order 501 to allow modules to go before with mkBefore
-    system.nssDatabases.hosts = (mkOrder 501 ["resolve [!UNAVAIL=return]"]);
-
-    systemd.additionalUpstreamSystemUnits = [
-      "systemd-resolved.service"
-    ];
-
-    systemd.services.systemd-resolved = {
-      wantedBy = [ "multi-user.target" ];
-      aliases = [ "dbus-org.freedesktop.resolve1.service" ];
-      restartTriggers = [ config.environment.etc."systemd/resolved.conf".source ];
-    };
-
-    environment.etc = {
-      "systemd/resolved.conf".text = ''
-        [Resolve]
-        ${optionalString (config.networking.nameservers != [])
-          "DNS=${concatStringsSep " " config.networking.nameservers}"}
-        ${optionalString (cfg.fallbackDns != null)
-          "FallbackDNS=${concatStringsSep " " cfg.fallbackDns}"}
-        ${optionalString (cfg.domains != [])
-          "Domains=${concatStringsSep " " cfg.domains}"}
-        LLMNR=${cfg.llmnr}
-        DNSSEC=${cfg.dnssec}
-        DNSOverTLS=${cfg.dnsovertls}
-        ${config.services.resolved.extraConfig}
+    boot.initrd.services.resolved.enable = mkOption {
+      default = config.boot.initrd.systemd.network.enable;
+      defaultText = "config.boot.initrd.systemd.network.enable";
+      description = ''
+        Whether to enable resolved for stage 1 networking.
+        Uses the toplevel 'services.resolved' options for 'resolved.conf'
       '';
-
-      # symlink the dynamic stub resolver of resolv.conf as recommended by upstream:
-      # https://www.freedesktop.org/software/systemd/man/systemd-resolved.html#/etc/resolv.conf
-      "resolv.conf".source = "/run/systemd/resolve/stub-resolv.conf";
-    } // optionalAttrs dnsmasqResolve {
-      "dnsmasq-resolv.conf".source = "/run/systemd/resolve/resolv.conf";
     };
 
-    # If networkmanager is enabled, ask it to interface with resolved.
-    networking.networkmanager.dns = "systemd-resolved";
-
-    networking.resolvconf.package = pkgs.systemd;
-
   };
 
+  config = mkMerge [
+    (mkIf cfg.enable {
+
+      assertions = [
+        { assertion = !config.networking.useHostResolvConf;
+          message = "Using host resolv.conf is not supported with systemd-resolved";
+        }
+      ];
+
+      users.users.systemd-resolve.group = "systemd-resolve";
+
+      # add resolve to nss hosts database if enabled and nscd enabled
+      # system.nssModules is configured in nixos/modules/system/boot/systemd.nix
+      # added with order 501 to allow modules to go before with mkBefore
+      system.nssDatabases.hosts = (mkOrder 501 ["resolve [!UNAVAIL=return]"]);
+
+      systemd.additionalUpstreamSystemUnits = [
+        "systemd-resolved.service"
+      ];
+
+      systemd.services.systemd-resolved = {
+        wantedBy = [ "sysinit.target" ];
+        aliases = [ "dbus-org.freedesktop.resolve1.service" ];
+        restartTriggers = [ config.environment.etc."systemd/resolved.conf".source ];
+      };
+
+      environment.etc = {
+        "systemd/resolved.conf".text = resolvedConf;
+
+        # symlink the dynamic stub resolver of resolv.conf as recommended by upstream:
+        # https://www.freedesktop.org/software/systemd/man/systemd-resolved.html#/etc/resolv.conf
+        "resolv.conf".source = "/run/systemd/resolve/stub-resolv.conf";
+      } // optionalAttrs dnsmasqResolve {
+        "dnsmasq-resolv.conf".source = "/run/systemd/resolve/resolv.conf";
+      };
+
+      # If networkmanager is enabled, ask it to interface with resolved.
+      networking.networkmanager.dns = "systemd-resolved";
+
+      networking.resolvconf.package = pkgs.systemd;
+
+    })
+
+    (mkIf config.boot.initrd.services.resolved.enable {
+
+      assertions = [
+        {
+          assertion = config.boot.initrd.systemd.enable;
+          message = "'boot.initrd.services.resolved.enable' can only be enabled with systemd stage 1.";
+        }
+      ];
+
+      boot.initrd.systemd = {
+        contents = {
+          "/etc/tmpfiles.d/resolv.conf".text =
+            "L /etc/resolv.conf - - - - /run/systemd/resolve/stub-resolv.conf";
+          "/etc/systemd/resolved.conf".text = resolvedConf;
+        };
+
+        additionalUpstreamUnits = ["systemd-resolved.service"];
+        users.systemd-resolve = {};
+        groups.systemd-resolve = {};
+        storePaths = ["${config.boot.initrd.systemd.package}/lib/systemd/systemd-resolved"];
+        services.systemd-resolved = {
+          wantedBy = ["sysinit.target"];
+          aliases = [ "dbus-org.freedesktop.resolve1.service" ];
+        };
+      };
+
+    })
+  ];
+
 }
diff --git a/nixos/modules/system/boot/systemd/initrd.nix b/nixos/modules/system/boot/systemd/initrd.nix
index cc32b2a15e7ce..6107a2594baf8 100644
--- a/nixos/modules/system/boot/systemd/initrd.nix
+++ b/nixos/modules/system/boot/systemd/initrd.nix
@@ -473,8 +473,8 @@ in {
         "${cfg.package.util-linux}/bin/umount"
         "${cfg.package.util-linux}/bin/sulogin"
 
-        # required for script services
-        "${pkgs.runtimeShell}"
+        # required for script services, and some tools like xfs still want the sh symlink
+        "${pkgs.bash}/bin"
 
         # so NSS can look up usernames
         "${pkgs.glibc}/lib/libnss_files.so.2"
diff --git a/nixos/modules/tasks/filesystems/zfs.nix b/nixos/modules/tasks/filesystems/zfs.nix
index 2c749d45d7a15..b75817a011cbd 100644
--- a/nixos/modules/tasks/filesystems/zfs.nix
+++ b/nixos/modules/tasks/filesystems/zfs.nix
@@ -441,21 +441,45 @@ in
           {manpage}`systemd.time(7)`.
         '';
       };
+
+      randomizedDelaySec = mkOption {
+        default = "6h";
+        type = types.str;
+        example = "12h";
+        description = ''
+          Add a randomized delay before each ZFS trim.
+          The delay will be chosen between zero and this value.
+          This value must be a time span in the format specified by
+          {manpage}`systemd.time(7)`
+        '';
+      };
     };
 
     services.zfs.autoScrub = {
       enable = mkEnableOption "periodic scrubbing of ZFS pools";
 
       interval = mkOption {
-        default = "Sun, 02:00";
+        default = "monthly";
         type = types.str;
-        example = "daily";
+        example = "quarterly";
         description = ''
           Systemd calendar expression when to scrub ZFS pools. See
           {manpage}`systemd.time(7)`.
         '';
       };
 
+      randomizedDelaySec = mkOption {
+        default = "6h";
+        type = types.str;
+        example = "12h";
+        description = ''
+          Add a randomized delay before each ZFS autoscrub.
+          The delay will be chosen between zero and this value.
+          This value must be a time span in the format specified by
+          {manpage}`systemd.time(7)`
+        '';
+      };
+
       pools = mkOption {
         default = [];
         type = types.listOf types.str;
@@ -862,6 +886,7 @@ in
         timerConfig = {
           OnCalendar = cfgScrub.interval;
           Persistent = "yes";
+          RandomizedDelaySec = cfgScrub.randomizedDelaySec;
         };
       };
     })
@@ -879,7 +904,10 @@ in
         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";
+      systemd.timers.zpool-trim.timerConfig = {
+        Persistent = "yes";
+        RandomizedDelaySec = cfgTrim.randomizedDelaySec;
+      };
     })
   ];
 }
diff --git a/nixos/modules/testing/test-instrumentation.nix b/nixos/modules/testing/test-instrumentation.nix
index 28abbe66adafb..2b365bc555855 100644
--- a/nixos/modules/testing/test-instrumentation.nix
+++ b/nixos/modules/testing/test-instrumentation.nix
@@ -218,6 +218,8 @@ in
 
     services.displayManager.logToJournal = true;
 
+    services.logrotate.enable = mkOverride 150 false;
+
     # Make sure we use the Guest Agent from the QEMU package for testing
     # to reduce the closure size required for the tests.
     services.qemuGuest.package = pkgs.qemu_test.ga;
diff --git a/nixos/modules/virtualisation/lxc-image-metadata.nix b/nixos/modules/virtualisation/lxc-image-metadata.nix
index 2c0568b4c4682..38d955798f3e0 100644
--- a/nixos/modules/virtualisation/lxc-image-metadata.nix
+++ b/nixos/modules/virtualisation/lxc-image-metadata.nix
@@ -87,10 +87,10 @@ in {
       contents = [
         {
           source = toYAML "metadata.yaml" {
-            architecture = builtins.elemAt (builtins.match "^([a-z0-9_]+).+" (toString pkgs.system)) 0;
+            architecture = builtins.elemAt (builtins.match "^([a-z0-9_]+).+" (toString pkgs.stdenv.hostPlatform.system)) 0;
             creation_date = 1;
             properties = {
-              description = "${config.system.nixos.distroName} ${config.system.nixos.codeName} ${config.system.nixos.label} ${pkgs.system}";
+              description = "${config.system.nixos.distroName} ${config.system.nixos.codeName} ${config.system.nixos.label} ${pkgs.stdenv.hostPlatform.system}";
               os = "${config.system.nixos.distroId}";
               release = "${config.system.nixos.codeName}";
             };
diff --git a/nixos/modules/virtualisation/qemu-vm.nix b/nixos/modules/virtualisation/qemu-vm.nix
index c30f4577fdd86..3b81cfaf2b8ca 100644
--- a/nixos/modules/virtualisation/qemu-vm.nix
+++ b/nixos/modules/virtualisation/qemu-vm.nix
@@ -912,7 +912,7 @@ in
           "ppc64-linux" = "tpm-spapr";
           "armv7-linux" = "tpm-tis-device";
           "aarch64-linux" = "tpm-tis-device";
-        }.${pkgs.hostPlatform.system} or (throw "Unsupported system for TPM2 emulation in QEMU"));
+        }.${pkgs.stdenv.hostPlatform.system} or (throw "Unsupported system for TPM2 emulation in QEMU"));
         defaultText = ''
           Based on the guest platform Linux system:
 
diff --git a/nixos/release-combined.nix b/nixos/release-combined.nix
index d1773da9afa6f..10834da35207e 100644
--- a/nixos/release-combined.nix
+++ b/nixos/release-combined.nix
@@ -43,14 +43,14 @@ in rec {
       name = "nixos-${nixos.channel.version}";
       meta = {
         description = "Release-critical builds for the NixOS channel";
-        maintainers = with pkgs.lib.maintainers; [ eelco ];
+        maintainers = with pkgs.lib.maintainers; [ ];
       };
       constituents = pkgs.lib.concatLists [
         [ "nixos.channel" ]
         (onFullSupported "nixos.dummy")
         (onAllSupported "nixos.iso_minimal")
         (onSystems ["x86_64-linux" "aarch64-linux"] "nixos.amazonImage")
-        (onFullSupported "nixos.iso_plasma5")
+        (onFullSupported "nixos.iso_plasma6")
         (onFullSupported "nixos.iso_gnome")
         (onFullSupported "nixos.manual")
         (onSystems ["x86_64-linux"] "nixos.ova")
@@ -112,7 +112,7 @@ in rec {
         (onFullSupported "nixos.tests.latestKernel.login")
         (onFullSupported "nixos.tests.lightdm")
         (onFullSupported "nixos.tests.login")
-        (onFullSupported "nixos.tests.misc")
+        (onFullSupported "nixos.tests.misc.default")
         (onFullSupported "nixos.tests.mutableUsers")
         (onFullSupported "nixos.tests.nat.firewall")
         (onFullSupported "nixos.tests.nat.standalone")
diff --git a/nixos/release-small.nix b/nixos/release-small.nix
index 091c2b1f305be..b87a58f5eee83 100644
--- a/nixos/release-small.nix
+++ b/nixos/release-small.nix
@@ -98,7 +98,7 @@ in rec {
     name = "nixos-${nixos.channel.version}";
     meta = {
       description = "Release-critical builds for the NixOS channel";
-      maintainers = [ lib.maintainers.eelco ];
+      maintainers = [ ];
     };
     constituents = lib.flatten [
       [
@@ -124,7 +124,7 @@ in rec {
         "nixos.tests.firewall"
         "nixos.tests.ipv6"
         "nixos.tests.login"
-        "nixos.tests.misc"
+        "nixos.tests.misc.default"
         "nixos.tests.nat.firewall"
         "nixos.tests.nat.standalone"
         "nixos.tests.nfs4.simple"
diff --git a/nixos/tests/acme.nix b/nixos/tests/acme.nix
index d63a77fcdd23c..511d3c589faef 100644
--- a/nixos/tests/acme.nix
+++ b/nixos/tests/acme.nix
@@ -99,7 +99,14 @@
               serverAliases = [ "${server}-wildcard-alias.example.test" ];
               useACMEHost = "example.test";
             };
-          };
+          } // (lib.optionalAttrs (server == "nginx") {
+            # The nginx module supports using a different key than the hostname
+            different-key = vhostBaseData // {
+              serverName = "${server}-different-key.example.test";
+              serverAliases = [ "${server}-different-key-alias.example.test" ];
+              enableACME = true;
+            };
+          });
         };
 
         # Used to determine if service reload was triggered
@@ -653,20 +660,20 @@ in {
           webserver.succeed("systemctl restart caddy.service")
           check_connection_key_bits(client, "a.example.test", "384")
 
-      domains = ["http", "dns", "wildcard"]
-      for server, logsrc in [
-          ("nginx", "journalctl -n 30 -u nginx.service"),
-          ("httpd", "tail -n 30 /var/log/httpd/*.log"),
+      common_domains = ["http", "dns", "wildcard"]
+      for server, logsrc, domains in [
+          ("nginx", "journalctl -n 30 -u nginx.service", common_domains + ["different-key"]),
+          ("httpd", "tail -n 30 /var/log/httpd/*.log", common_domains),
       ]:
           wait_for_server = lambda: webserver.wait_for_unit(f"{server}.service")
           with subtest(f"Works with {server}"):
               try:
                   switch_to(webserver, server)
-                  # Skip wildcard domain for this check ([:-1])
-                  for domain in domains[:-1]:
-                      webserver.wait_for_unit(
-                          f"acme-finished-{server}-{domain}.example.test.target"
-                      )
+                  for domain in domains:
+                      if domain != "wildcard":
+                          webserver.wait_for_unit(
+                              f"acme-finished-{server}-{domain}.example.test.target"
+                          )
               except Exception as err:
                   _, output = webserver.execute(
                       f"{logsrc} && ls -al /var/lib/acme/acme-challenge"
@@ -676,8 +683,9 @@ in {
 
               wait_for_server()
 
-              for domain in domains[:-1]:
-                  check_issuer(webserver, f"{server}-{domain}.example.test", "pebble")
+              for domain in domains:
+                  if domain != "wildcard":
+                      check_issuer(webserver, f"{server}-{domain}.example.test", "pebble")
               for domain in domains:
                   check_connection(client, f"{server}-{domain}.example.test")
                   check_connection(client, f"{server}-{domain}-alias.example.test")
diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix
index ba876fe31fc04..035c288c22e5c 100644
--- a/nixos/tests/all-tests.nix
+++ b/nixos/tests/all-tests.nix
@@ -130,6 +130,7 @@ in {
   apparmor = handleTest ./apparmor.nix {};
   archi = handleTest ./archi.nix {};
   armagetronad = handleTest ./armagetronad.nix {};
+  artalk = handleTest ./artalk.nix {};
   atd = handleTest ./atd.nix {};
   atop = handleTest ./atop.nix {};
   atuin = handleTest ./atuin.nix {};
@@ -144,6 +145,7 @@ in {
   bcachefs = handleTestOn ["x86_64-linux" "aarch64-linux"] ./bcachefs.nix {};
   beanstalkd = handleTest ./beanstalkd.nix {};
   bees = handleTest ./bees.nix {};
+  benchexec = handleTest ./benchexec.nix {};
   binary-cache = handleTest ./binary-cache.nix {};
   bind = handleTest ./bind.nix {};
   bird = handleTest ./bird.nix {};
@@ -204,6 +206,7 @@ in {
   code-server = handleTest ./code-server.nix {};
   coder = handleTest ./coder.nix {};
   collectd = handleTest ./collectd.nix {};
+  commafeed = handleTest ./commafeed.nix {};
   connman = handleTest ./connman.nix {};
   consul = handleTest ./consul.nix {};
   consul-template = handleTest ./consul-template.nix {};
@@ -243,6 +246,7 @@ in {
   deepin = handleTest ./deepin.nix {};
   deluge = handleTest ./deluge.nix {};
   dendrite = handleTest ./matrix/dendrite.nix {};
+  devpi-server = handleTest ./devpi-server.nix {};
   dex-oidc = handleTest ./dex-oidc.nix {};
   dhparams = handleTest ./dhparams.nix {};
   disable-installer-tools = handleTest ./disable-installer-tools.nix {};
@@ -308,6 +312,7 @@ in {
   fenics = handleTest ./fenics.nix {};
   ferm = handleTest ./ferm.nix {};
   ferretdb = handleTest ./ferretdb.nix {};
+  filesender = handleTest ./filesender.nix {};
   filesystems-overlayfs = runTest ./filesystems-overlayfs.nix;
   firefly-iii = handleTest ./firefly-iii.nix {};
   firefox = handleTest ./firefox.nix { firefoxPackage = pkgs.firefox; };
@@ -424,7 +429,8 @@ in {
   icingaweb2 = handleTest ./icingaweb2.nix {};
   iftop = handleTest ./iftop.nix {};
   incron = handleTest ./incron.nix {};
-  incus = pkgs.recurseIntoAttrs (handleTest ./incus { inherit handleTestOn; });
+  incus = pkgs.recurseIntoAttrs (handleTest ./incus { inherit handleTestOn; inherit (pkgs) incus; });
+  incus-lts = pkgs.recurseIntoAttrs (handleTest ./incus { inherit handleTestOn; });
   influxdb = handleTest ./influxdb.nix {};
   influxdb2 = handleTest ./influxdb2.nix {};
   initrd-network-openvpn = handleTestOn [ "x86_64-linux" "i686-linux" ] ./initrd-network-openvpn {};
@@ -585,7 +591,7 @@ in {
   mysql-backup = handleTest ./mysql/mysql-backup.nix {};
   mysql-replication = handleTest ./mysql/mysql-replication.nix {};
   n8n = handleTest ./n8n.nix {};
-  nagios = handleTest ./nagios.nix {};
+  nagios = handleTestOn [ "x86_64-linux" "aarch64-linux" ] ./nagios.nix {};
   nar-serve = handleTest ./nar-serve.nix {};
   nat.firewall = handleTest ./nat.nix { withFirewall = true; };
   nat.standalone = handleTest ./nat.nix { withFirewall = false; };
@@ -610,6 +616,7 @@ in {
   # TODO: put in networking.nix after the test becomes more complete
   networkingProxy = handleTest ./networking-proxy.nix {};
   nextcloud = handleTest ./nextcloud {};
+  nextjs-ollama-llm-ui = runTest ./web-apps/nextjs-ollama-llm-ui.nix;
   nexus = handleTest ./nexus.nix {};
   # TODO: Test nfsv3 + Kerberos
   nfs3 = handleTest ./nfs { version = 3; };
@@ -756,6 +763,7 @@ in {
   pretix = runTest ./web-apps/pretix.nix;
   printing-socket = handleTest ./printing.nix { socket = true; };
   printing-service = handleTest ./printing.nix { socket = false; };
+  private-gpt = handleTest ./private-gpt.nix {};
   privoxy = handleTest ./privoxy.nix {};
   prometheus = handleTest ./prometheus.nix {};
   prometheus-exporters = handleTest ./prometheus-exporters.nix {};
@@ -870,7 +878,8 @@ in {
   swap-random-encryption = handleTest ./swap-random-encryption.nix {};
   sway = handleTest ./sway.nix {};
   swayfx = handleTest ./swayfx.nix {};
-  switchTest = handleTest ./switch-test.nix {};
+  switchTest = handleTest ./switch-test.nix { ng = false; };
+  switchTestNg = handleTest ./switch-test.nix { ng = true; };
   sympa = handleTest ./sympa.nix {};
   syncthing = handleTest ./syncthing.nix {};
   syncthing-no-settings = handleTest ./syncthing-no-settings.nix {};
@@ -883,7 +892,7 @@ in {
   systemd-binfmt = handleTestOn ["x86_64-linux"] ./systemd-binfmt.nix {};
   systemd-boot = handleTest ./systemd-boot.nix {};
   systemd-bpf = handleTest ./systemd-bpf.nix {};
-  systemd-confinement = handleTest ./systemd-confinement.nix {};
+  systemd-confinement = handleTest ./systemd-confinement {};
   systemd-coredump = handleTest ./systemd-coredump.nix {};
   systemd-cryptenroll = handleTest ./systemd-cryptenroll.nix {};
   systemd-credentials-tpm2 = handleTest ./systemd-credentials-tpm2.nix {};
@@ -922,6 +931,7 @@ in {
   systemd-oomd = handleTest ./systemd-oomd.nix {};
   systemd-portabled = handleTest ./systemd-portabled.nix {};
   systemd-repart = handleTest ./systemd-repart.nix {};
+  systemd-resolved = handleTest ./systemd-resolved.nix {};
   systemd-shutdown = handleTest ./systemd-shutdown.nix {};
   systemd-sysupdate = runTest ./systemd-sysupdate.nix;
   systemd-sysusers-mutable = runTest ./systemd-sysusers-mutable.nix;
@@ -1000,7 +1010,7 @@ in {
   vault-dev = handleTest ./vault-dev.nix {};
   vault-postgresql = handleTest ./vault-postgresql.nix {};
   vaultwarden = handleTest ./vaultwarden.nix {};
-  vector = handleTest ./vector.nix {};
+  vector = handleTest ./vector {};
   vengi-tools = handleTest ./vengi-tools.nix {};
   victoriametrics = handleTest ./victoriametrics.nix {};
   vikunja = handleTest ./vikunja.nix {};
@@ -1036,7 +1046,9 @@ in {
   xterm = handleTest ./xterm.nix {};
   xxh = handleTest ./xxh.nix {};
   yabar = handleTest ./yabar.nix {};
+  ydotool = handleTest ./ydotool.nix {};
   yggdrasil = handleTest ./yggdrasil.nix {};
+  your_spotify = handleTest ./your_spotify.nix {};
   zammad = handleTest ./zammad.nix {};
   zeronet-conservancy = handleTest ./zeronet-conservancy.nix {};
   zfs = handleTest ./zfs.nix {};
diff --git a/nixos/tests/artalk.nix b/nixos/tests/artalk.nix
new file mode 100644
index 0000000000000..1338e5cd380c6
--- /dev/null
+++ b/nixos/tests/artalk.nix
@@ -0,0 +1,28 @@
+import ./make-test-python.nix (
+  { lib, pkgs, ... }:
+  {
+
+    name = "artalk";
+
+    meta = {
+      maintainers = with lib.maintainers; [ moraxyc ];
+    };
+
+    nodes.machine =
+      { pkgs, ... }:
+      {
+        environment.systemPackages = [ pkgs.curl ];
+        services.artalk = {
+          enable = true;
+        };
+      };
+
+    testScript = ''
+      machine.wait_for_unit("artalk.service")
+
+      machine.wait_for_open_port(23366)
+
+      machine.succeed("curl --fail --max-time 10 http://127.0.0.1:23366/")
+    '';
+  }
+)
diff --git a/nixos/tests/avahi.nix b/nixos/tests/avahi.nix
index d8f4d13340fbc..4ae2f919f2f7d 100644
--- a/nixos/tests/avahi.nix
+++ b/nixos/tests/avahi.nix
@@ -9,7 +9,7 @@
 import ./make-test-python.nix {
   name = "avahi";
   meta = with pkgs.lib.maintainers; {
-    maintainers = [ eelco ];
+    maintainers = [ ];
   };
 
   nodes = let
diff --git a/nixos/tests/ayatana-indicators.nix b/nixos/tests/ayatana-indicators.nix
index 5709ad2a1af69..cfd4d8099d112 100644
--- a/nixos/tests/ayatana-indicators.nix
+++ b/nixos/tests/ayatana-indicators.nix
@@ -28,8 +28,11 @@ in {
       enable = true;
       packages = with pkgs; [
         ayatana-indicator-datetime
+        ayatana-indicator-display
         ayatana-indicator-messages
+        ayatana-indicator-power
         ayatana-indicator-session
+        ayatana-indicator-sound
       ] ++ (with pkgs.lomiri; [
         lomiri-indicator-network
         telephony-service
@@ -40,6 +43,8 @@ in {
 
     services.accounts-daemon.enable = true; # messages
 
+    hardware.pulseaudio.enable = true; # sound
+
     # Lomiri-ish setup for Lomiri indicators
     # TODO move into a Lomiri module, once the package set is far enough for the DE to start
 
@@ -91,7 +96,7 @@ in {
 
     # Now check if all indicators were brought up successfully, and kill them for later
   '' + (runCommandOverAyatanaIndicators (service: let serviceExec = builtins.replaceStrings [ "." ] [ "-" ] service; in ''
-    machine.succeed("pgrep -u ${user} -f ${serviceExec}")
+    machine.wait_until_succeeds("pgrep -u ${user} -f ${serviceExec}")
     machine.succeed("pkill -f ${serviceExec}")
   '')) + ''
 
diff --git a/nixos/tests/benchexec.nix b/nixos/tests/benchexec.nix
new file mode 100644
index 0000000000000..3fc9ebc2c35f5
--- /dev/null
+++ b/nixos/tests/benchexec.nix
@@ -0,0 +1,54 @@
+import ./make-test-python.nix ({ pkgs, lib, ... }:
+let
+  user = "alice";
+in
+{
+  name = "benchexec";
+
+  nodes.benchexec = {
+    imports = [ ./common/user-account.nix ];
+
+    programs.benchexec = {
+      enable = true;
+      users = [ user ];
+    };
+  };
+
+  testScript = { ... }:
+    let
+      runexec = lib.getExe' pkgs.benchexec "runexec";
+      echo = builtins.toString pkgs.benchexec;
+      test = lib.getExe (pkgs.writeShellApplication rec {
+        name = "test";
+        meta.mainProgram = name;
+        text = "echo '${echo}'";
+      });
+      wd = "/tmp";
+      stdout = "${wd}/runexec.out";
+      stderr = "${wd}/runexec.err";
+    in
+    ''
+      start_all()
+      machine.wait_for_unit("multi-user.target")
+      benchexec.succeed(''''\
+          systemd-run \
+            --property='StandardOutput=file:${stdout}' \
+            --property='StandardError=file:${stderr}' \
+            --unit=runexec --wait --user --machine='${user}@' \
+            --working-directory ${wd} \
+          '${runexec}' \
+            --debug \
+            --read-only-dir / \
+            --hidden-dir /home \
+            '${test}' \
+      '''')
+      benchexec.succeed("grep -s '${echo}' ${wd}/output.log")
+      benchexec.succeed("test \"$(grep -Ec '((start|wall|cpu)time|memory)=' ${stdout})\" = 4")
+      benchexec.succeed("! grep -E '(WARNING|ERROR)' ${stderr}")
+    '';
+
+  interactive.nodes.benchexec.services.kmscon = {
+    enable = true;
+    fonts = [{ name = "Fira Code"; package = pkgs.fira-code; }];
+  };
+})
diff --git a/nixos/tests/bittorrent.nix b/nixos/tests/bittorrent.nix
index 473b05d4c98e8..b5f5982743a13 100644
--- a/nixos/tests/bittorrent.nix
+++ b/nixos/tests/bittorrent.nix
@@ -36,7 +36,7 @@ in
 {
   name = "bittorrent";
   meta = with pkgs.lib.maintainers; {
-    maintainers = [ domenkozar eelco rob bobvanderlinden ];
+    maintainers = [ domenkozar rob bobvanderlinden ];
   };
 
   nodes = {
diff --git a/nixos/tests/castopod.nix b/nixos/tests/castopod.nix
index 3257cd3d363c7..57e035354d23e 100644
--- a/nixos/tests/castopod.nix
+++ b/nixos/tests/castopod.nix
@@ -98,6 +98,7 @@ import ./make-test-python.nix ({ pkgs, lib, ... }:
             driver = Firefox(options=options, service=service)
             driver = Firefox(options=options)
             driver.implicitly_wait(30)
+            driver.set_page_load_timeout(60)
 
             # install ##########################################################
 
@@ -207,7 +208,7 @@ import ./make-test-python.nix ({ pkgs, lib, ... }:
             text = ''
               out=/tmp/podcast.mp3
               sox -n -r 48000 -t wav - synth ${targetPodcastDuration} sine 440 `
-              `| lame --noreplaygain -cbr -q 9 -b 320 - $out
+              `| lame --noreplaygain --cbr -q 9 -b 320 - $out
               FILESIZE="$(stat -c%s $out)"
               [ "$FILESIZE" -gt 0 ]
               [ "$FILESIZE" -le "${toString targetPodcastSize}" ]
diff --git a/nixos/tests/commafeed.nix b/nixos/tests/commafeed.nix
new file mode 100644
index 0000000000000..7b65720818a9b
--- /dev/null
+++ b/nixos/tests/commafeed.nix
@@ -0,0 +1,21 @@
+import ./make-test-python.nix (
+  { lib, ... }:
+  {
+    name = "commafeed";
+
+    nodes.server = {
+      services.commafeed = {
+        enable = true;
+      };
+    };
+
+    testScript = ''
+      server.start()
+      server.wait_for_unit("commafeed.service")
+      server.wait_for_open_port(8082)
+      server.succeed("curl --fail --silent http://localhost:8082")
+    '';
+
+    meta.maintainers = [ lib.maintainers.raroh73 ];
+  }
+)
diff --git a/nixos/tests/containers-bridge.nix b/nixos/tests/containers-bridge.nix
index d2e16299edaad..3001db33ba5a3 100644
--- a/nixos/tests/containers-bridge.nix
+++ b/nixos/tests/containers-bridge.nix
@@ -8,7 +8,7 @@ in
 import ./make-test-python.nix ({ pkgs, lib, ... }: {
   name = "containers-bridge";
   meta = {
-    maintainers = with lib.maintainers; [ aristid aszlig eelco kampfschlaefer ];
+    maintainers = with lib.maintainers; [ aristid aszlig kampfschlaefer ];
   };
 
   nodes.machine =
diff --git a/nixos/tests/containers-imperative.nix b/nixos/tests/containers-imperative.nix
index fff00e4f73a85..ea1046b40354e 100644
--- a/nixos/tests/containers-imperative.nix
+++ b/nixos/tests/containers-imperative.nix
@@ -1,7 +1,7 @@
 import ./make-test-python.nix ({ pkgs, lib, ... }: {
   name = "containers-imperative";
   meta = {
-    maintainers = with lib.maintainers; [ aristid aszlig eelco kampfschlaefer ];
+    maintainers = with lib.maintainers; [ aristid aszlig kampfschlaefer ];
   };
 
   nodes.machine =
diff --git a/nixos/tests/containers-ip.nix b/nixos/tests/containers-ip.nix
index ecff99a3f0c25..034e5d660415a 100644
--- a/nixos/tests/containers-ip.nix
+++ b/nixos/tests/containers-ip.nix
@@ -14,7 +14,7 @@ let
 in import ./make-test-python.nix ({ pkgs, lib, ... }: {
   name = "containers-ipv4-ipv6";
   meta = {
-    maintainers = with lib.maintainers; [ aristid aszlig eelco kampfschlaefer ];
+    maintainers = with lib.maintainers; [ aristid aszlig kampfschlaefer ];
   };
 
   nodes.machine =
diff --git a/nixos/tests/containers-portforward.nix b/nixos/tests/containers-portforward.nix
index b8c7aabc5a50b..1a9880fe93133 100644
--- a/nixos/tests/containers-portforward.nix
+++ b/nixos/tests/containers-portforward.nix
@@ -8,7 +8,7 @@ in
 import ./make-test-python.nix ({ pkgs, lib, ... }: {
   name = "containers-portforward";
   meta = {
-    maintainers = with lib.maintainers; [ aristid aszlig eelco kampfschlaefer ianwookim ];
+    maintainers = with lib.maintainers; [ aristid aszlig kampfschlaefer ianwookim ];
   };
 
   nodes.machine =
diff --git a/nixos/tests/devpi-server.nix b/nixos/tests/devpi-server.nix
new file mode 100644
index 0000000000000..2a16d49724dbc
--- /dev/null
+++ b/nixos/tests/devpi-server.nix
@@ -0,0 +1,35 @@
+import ./make-test-python.nix ({pkgs, ...}: let
+  server-port = 3141;
+in {
+  name = "devpi-server";
+  meta = with pkgs.lib.maintainers; {
+    maintainers = [cafkafk];
+  };
+
+  nodes = {
+    devpi = {...}: {
+      services.devpi-server = {
+        enable = true;
+        host = "0.0.0.0";
+        port = server-port;
+        openFirewall = true;
+        secretFile = pkgs.writeText "devpi-secret" "v263P+V3YGDYUyfYL/RBURw+tCPMDw94R/iCuBNJrDhaYrZYjpA6XPFVDDH8ViN20j77y2PHoMM/U0opNkVQ2g==";
+      };
+    };
+
+    client1 = {...}: {
+      environment.systemPackages = with pkgs; [
+        devpi-client
+        jq
+      ];
+    };
+  };
+
+  testScript = ''
+    start_all()
+    devpi.wait_for_unit("devpi-server.service")
+    devpi.wait_for_open_port(${builtins.toString server-port})
+
+    client1.succeed("devpi getjson http://devpi:${builtins.toString server-port}")
+  '';
+})
diff --git a/nixos/tests/elk.nix b/nixos/tests/elk.nix
index b5a8cb532ae0a..87c82877fe109 100644
--- a/nixos/tests/elk.nix
+++ b/nixos/tests/elk.nix
@@ -16,7 +16,7 @@ let
     import ./make-test-python.nix ({
     inherit name;
     meta = with pkgs.lib.maintainers; {
-      maintainers = [ eelco offline basvandijk ];
+      maintainers = [ offline basvandijk ];
     };
     nodes = {
       one =
diff --git a/nixos/tests/fcitx5/default.nix b/nixos/tests/fcitx5/default.nix
index c113f2e2c052c..feea621f6b5b2 100644
--- a/nixos/tests/fcitx5/default.nix
+++ b/nixos/tests/fcitx5/default.nix
@@ -89,10 +89,13 @@ rec {
             machine.succeed("xauth merge ${xauth}")
             machine.sleep(5)
 
+            machine.wait_until_succeeds("pgrep fcitx5")
             machine.succeed("su - ${user.name} -c 'kill $(pgrep fcitx5)'")
             machine.sleep(1)
 
             machine.succeed("su - ${user.name} -c 'alacritty >&2 &'")
+            machine.wait_for_window("alice@machine")
+
             machine.succeed("su - ${user.name} -c 'fcitx5 >&2 &'")
             machine.sleep(10)
 
diff --git a/nixos/tests/filesender.nix b/nixos/tests/filesender.nix
new file mode 100644
index 0000000000000..9274ddbf7e90e
--- /dev/null
+++ b/nixos/tests/filesender.nix
@@ -0,0 +1,137 @@
+import ./make-test-python.nix ({ pkgs, lib, ... }: {
+  name = "filesender";
+  meta = {
+    maintainers = with lib.maintainers; [ nhnn ];
+    broken = pkgs.stdenv.isAarch64; # selenium.common.exceptions.WebDriverException: Message: Unsupported platform/architecture combination: linux/aarch64
+  };
+
+  nodes.filesender = { ... }: let
+    format = pkgs.formats.php { };
+  in {
+    networking.firewall.allowedTCPPorts = [ 80 ];
+
+    services.filesender.enable = true;
+    services.filesender.localDomain = "filesender";
+    services.filesender.settings = {
+      auth_sp_saml_authentication_source = "default";
+      auth_sp_saml_uid_attribute = "uid";
+      storage_filesystem_path = "/tmp";
+      site_url = "http://filesender";
+      force_ssl = false;
+      admin = "";
+      admin_email = "admin@localhost";
+      email_reply_to = "noreply@localhost";
+    };
+    services.simplesamlphp.filesender = {
+      settings = {
+        baseurlpath = "http://filesender/saml";
+        "module.enable".exampleauth = true;
+      };
+      authSources = {
+        admin = [ "core:AdminPassword" ];
+        default = format.lib.mkMixedArray [ "exampleauth:UserPass" ] {
+          "user:password" = {
+            uid = [ "user" ];
+            cn = [ "user" ];
+            mail = [ "user@nixos.org" ];
+          };
+        };
+      };
+    };
+  };
+
+  nodes.client =
+    { pkgs
+    , nodes
+    , ...
+    }:
+    let
+      filesenderIP = (builtins.head (nodes.filesender.networking.interfaces.eth1.ipv4.addresses)).address;
+    in
+    {
+      networking.hosts.${filesenderIP} = [ "filesender" ];
+
+      environment.systemPackages =
+        let
+          username = "user";
+          password = "password";
+          browser-test =
+            pkgs.writers.writePython3Bin "browser-test"
+              {
+                libraries = [ pkgs.python3Packages.selenium ];
+                flakeIgnore = [ "E124" "E501" ];
+              } ''
+              from selenium.webdriver.common.by import By
+              from selenium.webdriver import Firefox
+              from selenium.webdriver.firefox.options import Options
+              from selenium.webdriver.firefox.firefox_profile import FirefoxProfile
+              from selenium.webdriver.firefox.service import Service
+              from selenium.webdriver.support.ui import WebDriverWait
+              from selenium.webdriver.support import expected_conditions as EC
+              from subprocess import STDOUT
+              import string
+              import random
+              import logging
+              import time
+              selenium_logger = logging.getLogger("selenium")
+              selenium_logger.setLevel(logging.DEBUG)
+              selenium_logger.addHandler(logging.StreamHandler())
+              profile = FirefoxProfile()
+              profile.set_preference("browser.download.folderList", 2)
+              profile.set_preference("browser.download.manager.showWhenStarting", False)
+              profile.set_preference("browser.download.dir", "/tmp/firefox")
+              profile.set_preference("browser.helperApps.neverAsk.saveToDisk", "text/plain;text/txt")
+              options = Options()
+              options.profile = profile
+              options.add_argument('--headless')
+              service = Service(log_output=STDOUT)
+              driver = Firefox(options=options)
+              driver.set_window_size(1024, 768)
+              driver.implicitly_wait(30)
+              driver.get('http://filesender/')
+              wait = WebDriverWait(driver, 20)
+              wait.until(EC.title_contains("FileSender"))
+              driver.find_element(By.ID, "btn_logon").click()
+              wait.until(EC.title_contains("Enter your username and password"))
+              driver.find_element(By.ID, 'username').send_keys(
+                  '${username}'
+              )
+              driver.find_element(By.ID, 'password').send_keys(
+                  '${password}'
+              )
+              driver.find_element(By.ID, "submit_button").click()
+              wait.until(EC.title_contains("FileSender"))
+              wait.until(EC.presence_of_element_located((By.ID, "topmenu_logoff")))
+              test_string = "".join(random.choices(string.ascii_uppercase + string.digits, k=20))
+              with open("/tmp/test_file.txt", "w") as file:
+                  file.write(test_string)
+              driver.find_element(By.ID, "files").send_keys("/tmp/test_file.txt")
+              time.sleep(2)
+              driver.find_element(By.CSS_SELECTOR, '.start').click()
+              wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, ".download_link")))
+              download_link = driver.find_element(By.CSS_SELECTOR, '.download_link > textarea').get_attribute('value').strip()
+              driver.get(download_link)
+              wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, ".download")))
+              driver.find_element(By.CSS_SELECTOR, '.download').click()
+              wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, ".ui-dialog-buttonset > button:nth-child(2)")))
+              driver.find_element(By.CSS_SELECTOR, ".ui-dialog-buttonset > button:nth-child(2)").click()
+              driver.close()
+              driver.quit()
+            '';
+        in
+        [
+          pkgs.firefox-unwrapped
+          pkgs.geckodriver
+          browser-test
+        ];
+    };
+
+  testScript = ''
+    start_all()
+    filesender.wait_for_file("/run/phpfpm/filesender.sock")
+    filesender.wait_for_open_port(80)
+    if "If you have received an invitation to access this site as a guest" not in client.wait_until_succeeds("curl -sS -f http://filesender"):
+      raise Exception("filesender returned invalid html")
+    client.succeed("browser-test")
+  '';
+})
diff --git a/nixos/tests/firefox.nix b/nixos/tests/firefox.nix
index fbea95dc75235..6418e029f80d9 100644
--- a/nixos/tests/firefox.nix
+++ b/nixos/tests/firefox.nix
@@ -1,9 +1,9 @@
-import ./make-test-python.nix ({ pkgs, firefoxPackage, ... }:
+import ./make-test-python.nix ({ lib, pkgs, firefoxPackage, ... }:
 {
   name = firefoxPackage.pname;
 
   meta = with pkgs.lib.maintainers; {
-    maintainers = [ eelco shlevy ];
+    maintainers = [ shlevy ];
   };
 
   nodes.machine =
@@ -55,7 +55,7 @@ import ./make-test-python.nix ({ pkgs, firefoxPackage, ... }:
     };
 
   testScript = let
-    exe = firefoxPackage.unwrapped.binaryName;
+    exe = lib.getExe firefoxPackage;
   in ''
       from contextlib import contextmanager
 
diff --git a/nixos/tests/firewall.nix b/nixos/tests/firewall.nix
index dd7551f143a5e..34e8bda60eef5 100644
--- a/nixos/tests/firewall.nix
+++ b/nixos/tests/firewall.nix
@@ -3,7 +3,7 @@
 import ./make-test-python.nix ( { pkgs, nftables, ... } : {
   name = "firewall" + pkgs.lib.optionalString nftables "-nftables";
   meta = with pkgs.lib.maintainers; {
-    maintainers = [ eelco ];
+    maintainers = [ ];
   };
 
   nodes =
diff --git a/nixos/tests/garage/default.nix b/nixos/tests/garage/default.nix
index a42236e9a5bbe..b7f9bb4b865bd 100644
--- a/nixos/tests/garage/default.nix
+++ b/nixos/tests/garage/default.nix
@@ -51,4 +51,5 @@ in
   [
     "0_8"
     "0_9"
+    "1_x"
   ]
diff --git a/nixos/tests/garage/with-3node-replication.nix b/nixos/tests/garage/with-3node-replication.nix
index d4387b198d976..266a1082893f7 100644
--- a/nixos/tests/garage/with-3node-replication.nix
+++ b/nixos/tests/garage/with-3node-replication.nix
@@ -7,10 +7,10 @@ args@{ mkNode, ver, ... }:
   };
 
   nodes = {
-    node1 = mkNode { replicationMode = 3; publicV6Address = "fc00:1::1"; };
-    node2 = mkNode { replicationMode = 3; publicV6Address = "fc00:1::2"; };
-    node3 = mkNode { replicationMode = 3; publicV6Address = "fc00:1::3"; };
-    node4 = mkNode { replicationMode = 3; publicV6Address = "fc00:1::4"; };
+    node1 = mkNode { replicationMode = "3"; publicV6Address = "fc00:1::1"; };
+    node2 = mkNode { replicationMode = "3"; publicV6Address = "fc00:1::2"; };
+    node3 = mkNode { replicationMode = "3"; publicV6Address = "fc00:1::3"; };
+    node4 = mkNode { replicationMode = "3"; publicV6Address = "fc00:1::4"; };
   };
 
   testScript = ''
diff --git a/nixos/tests/incus/container.nix b/nixos/tests/incus/container.nix
index f6bc295448e28..10262cf2132b8 100644
--- a/nixos/tests/incus/container.nix
+++ b/nixos/tests/incus/container.nix
@@ -1,4 +1,4 @@
-import ../make-test-python.nix ({ pkgs, lib, extra ? {}, name ? "incus-container", ... } :
+import ../make-test-python.nix ({ pkgs, lib, extra ? {}, name ? "incus-container", incus ? pkgs.incus-lts, ... } :
 
 let
   releases = import ../../release.nix {
@@ -28,7 +28,10 @@ in
       memorySize = 1024;
       diskSize = 4096;
 
-      incus.enable = true;
+      incus = {
+        enable = true;
+        package = incus;
+      };
     };
     networking.nftables.enable = true;
   };
diff --git a/nixos/tests/incus/default.nix b/nixos/tests/incus/default.nix
index d778928a3b9f5..c33bf1600f27a 100644
--- a/nixos/tests/incus/default.nix
+++ b/nixos/tests/incus/default.nix
@@ -3,24 +3,27 @@
   config ? { },
   pkgs ? import ../../.. { inherit system config; },
   handleTestOn,
+  incus ? pkgs.incus-lts,
 }:
 {
   container-legacy-init = import ./container.nix {
     name = "container-legacy-init";
-    inherit system pkgs;
+    inherit incus system pkgs;
   };
   container-systemd-init = import ./container.nix {
     name = "container-systemd-init";
-    inherit system pkgs;
+    inherit incus system pkgs;
     extra = {
       boot.initrd.systemd.enable = true;
     };
   };
-  incusd-options = import ./incusd-options.nix { inherit system pkgs; };
-  lxd-to-incus = import ./lxd-to-incus.nix { inherit system pkgs; };
-  openvswitch = import ./openvswitch.nix { inherit system pkgs; };
-  socket-activated = import ./socket-activated.nix { inherit system pkgs; };
-  storage = import ./storage.nix { inherit system pkgs; };
-  ui = import ./ui.nix { inherit system pkgs; };
-  virtual-machine = handleTestOn [ "x86_64-linux" ] ./virtual-machine.nix { inherit system pkgs; };
+  incusd-options = import ./incusd-options.nix { inherit incus system pkgs; };
+  lxd-to-incus = import ./lxd-to-incus.nix { inherit incus system pkgs; };
+  openvswitch = import ./openvswitch.nix { inherit incus system pkgs; };
+  socket-activated = import ./socket-activated.nix { inherit incus system pkgs; };
+  storage = import ./storage.nix { inherit incus system pkgs; };
+  ui = import ./ui.nix { inherit incus system pkgs; };
+  virtual-machine = handleTestOn [ "x86_64-linux" ] ./virtual-machine.nix {
+    inherit incus system pkgs;
+  };
 }
diff --git a/nixos/tests/incus/incusd-options.nix b/nixos/tests/incus/incusd-options.nix
index b1e7f497fe3e7..7b3a4d726e38e 100644
--- a/nixos/tests/incus/incusd-options.nix
+++ b/nixos/tests/incus/incusd-options.nix
@@ -1,7 +1,12 @@
 # this is a set of tests for non-default options. typically the default options
 # will be handled by the other tests
 import ../make-test-python.nix (
-  { pkgs, lib, ... }:
+  {
+    pkgs,
+    lib,
+    incus ? pkgs.incus-lts,
+    ...
+  }:
 
   let
     releases = import ../../release.nix {
@@ -29,6 +34,7 @@ import ../make-test-python.nix (
 
         incus = {
           enable = true;
+          package = incus;
           softDaemonRestart = false;
 
           preseed = {
diff --git a/nixos/tests/incus/lxd-to-incus.nix b/nixos/tests/incus/lxd-to-incus.nix
index e93b76591eca4..66f78cbd33b40 100644
--- a/nixos/tests/incus/lxd-to-incus.nix
+++ b/nixos/tests/incus/lxd-to-incus.nix
@@ -1,6 +1,11 @@
 import ../make-test-python.nix (
 
-  { pkgs, lib, ... }:
+  {
+    pkgs,
+    lib,
+    incus ? pkgs.incus-lts,
+    ...
+  }:
 
   let
     releases = import ../../release.nix { configuration.documentation.enable = lib.mkForce false; };
@@ -65,7 +70,10 @@ import ../make-test-python.nix (
             ];
           };
 
-          incus.enable = true;
+          incus = {
+            enable = true;
+            package = incus;
+          };
         };
         networking.nftables.enable = true;
       };
diff --git a/nixos/tests/incus/openvswitch.nix b/nixos/tests/incus/openvswitch.nix
index 5d4aef031ad0a..1cead99080e7a 100644
--- a/nixos/tests/incus/openvswitch.nix
+++ b/nixos/tests/incus/openvswitch.nix
@@ -1,4 +1,4 @@
-import ../make-test-python.nix ({ pkgs, lib, ... } :
+import ../make-test-python.nix ({ pkgs, lib, incus ? pkgs.incus-lts, ... } :
 
 {
   name = "incus-openvswitch";
@@ -9,7 +9,11 @@ import ../make-test-python.nix ({ pkgs, lib, ... } :
 
   nodes.machine = { lib, ... }: {
     virtualisation = {
-      incus.enable = true;
+      incus = {
+        enable = true;
+        package = incus;
+      };
+
       vswitch.enable = true;
       incus.preseed = {
         networks = [
diff --git a/nixos/tests/incus/socket-activated.nix b/nixos/tests/incus/socket-activated.nix
index 59caf1090fbd8..55c5496396e91 100644
--- a/nixos/tests/incus/socket-activated.nix
+++ b/nixos/tests/incus/socket-activated.nix
@@ -1,4 +1,4 @@
-import ../make-test-python.nix ({ pkgs, lib, ... } :
+import ../make-test-python.nix ({ pkgs, lib, incus ? pkgs.incus-lts, ... } :
 
 {
   name = "incus-socket-activated";
@@ -9,8 +9,11 @@ import ../make-test-python.nix ({ pkgs, lib, ... } :
 
   nodes.machine = { lib, ... }: {
     virtualisation = {
-      incus.enable = true;
-      incus.socketActivation = true;
+      incus = {
+        enable = true;
+        package = incus;
+        socketActivation = true;
+      };
     };
     networking.nftables.enable = true;
   };
diff --git a/nixos/tests/incus/storage.nix b/nixos/tests/incus/storage.nix
index 190f4f7451c20..05ea6ba996eb2 100644
--- a/nixos/tests/incus/storage.nix
+++ b/nixos/tests/incus/storage.nix
@@ -1,5 +1,10 @@
 import ../make-test-python.nix (
-  { pkgs, lib, ... }:
+  {
+    pkgs,
+    lib,
+    incus ? pkgs.incus-lts,
+    ...
+  }:
 
   {
     name = "incus-storage";
@@ -19,7 +24,10 @@ import ../make-test-python.nix (
 
         virtualisation = {
           emptyDiskImages = [ 2048 ];
-          incus.enable = true;
+          incus = {
+            enable = true;
+            package = incus;
+          };
         };
       };
 
diff --git a/nixos/tests/incus/ui.nix b/nixos/tests/incus/ui.nix
index 837eb14844cea..a255d6fabe839 100644
--- a/nixos/tests/incus/ui.nix
+++ b/nixos/tests/incus/ui.nix
@@ -1,4 +1,4 @@
-import ../make-test-python.nix ({ pkgs, lib, ... }: {
+import ../make-test-python.nix ({ pkgs, lib, incus ? pkgs.incus-lts, ... }: {
   name = "incus-ui";
 
   meta = {
@@ -7,7 +7,10 @@ import ../make-test-python.nix ({ pkgs, lib, ... }: {
 
   nodes.machine = { lib, ... }: {
     virtualisation = {
-      incus.enable = true;
+      incus = {
+        enable = true;
+        package = incus;
+      };
       incus.ui.enable = true;
     };
     networking.nftables.enable = true;
diff --git a/nixos/tests/incus/virtual-machine.nix b/nixos/tests/incus/virtual-machine.nix
index c460447f7832d..70e54191d3304 100644
--- a/nixos/tests/incus/virtual-machine.nix
+++ b/nixos/tests/incus/virtual-machine.nix
@@ -1,4 +1,4 @@
-import ../make-test-python.nix ({ pkgs, lib, ... }:
+import ../make-test-python.nix ({ pkgs, lib, incus ? pkgs.incus-lts, ... }:
 
 let
   releases = import ../../release.nix {
@@ -33,7 +33,10 @@ in
       # Provide a TPM to test vTPM support for guests
       tpm.enable = true;
 
-      incus.enable = true;
+      incus = {
+        enable = true;
+        package = incus;
+      };
     };
     networking.nftables.enable = true;
   };
diff --git a/nixos/tests/initrd-network.nix b/nixos/tests/initrd-network.nix
index f2483b7393de4..abbc3d0fce822 100644
--- a/nixos/tests/initrd-network.nix
+++ b/nixos/tests/initrd-network.nix
@@ -1,7 +1,7 @@
 import ./make-test-python.nix ({ pkgs, lib, ...} : {
   name = "initrd-network";
 
-  meta.maintainers = [ pkgs.lib.maintainers.eelco ];
+  meta.maintainers = [ ];
 
   nodes.machine = { ... }: {
     imports = [ ../modules/profiles/minimal.nix ];
diff --git a/nixos/tests/installer-systemd-stage-1.nix b/nixos/tests/installer-systemd-stage-1.nix
index 1dd55dada042a..00205f9417718 100644
--- a/nixos/tests/installer-systemd-stage-1.nix
+++ b/nixos/tests/installer-systemd-stage-1.nix
@@ -19,7 +19,7 @@
     luksroot
     luksroot-format1
     luksroot-format2
-    # lvm
+    lvm
     separateBoot
     separateBootFat
     separateBootZfs
diff --git a/nixos/tests/installer.nix b/nixos/tests/installer.nix
index 7e835041eb39f..3f57a64333dda 100644
--- a/nixos/tests/installer.nix
+++ b/nixos/tests/installer.nix
@@ -249,12 +249,11 @@ let
       with subtest("Check whether nixos-rebuild works"):
           target.succeed("nixos-rebuild switch >&2")
 
-      # FIXME: Nix 2.4 broke nixos-option, someone has to fix it.
-      # with subtest("Test nixos-option"):
-      #     kernel_modules = target.succeed("nixos-option boot.initrd.kernelModules")
-      #     assert "virtio_console" in kernel_modules
-      #     assert "List of modules" in kernel_modules
-      #     assert "qemu-guest.nix" in kernel_modules
+      with subtest("Test nixos-option"):
+          kernel_modules = target.succeed("nixos-option boot.initrd.kernelModules")
+          assert "virtio_console" in kernel_modules
+          assert "List of modules" in kernel_modules
+          assert "qemu-guest.nix" in kernel_modules
 
       target.shutdown()
 
@@ -975,6 +974,9 @@ in {
           "mount LABEL=nixos /mnt",
       )
     '';
+    extraConfig = optionalString systemdStage1 ''
+      boot.initrd.services.lvm.enable = true;
+    '';
   };
 
   # Boot off an encrypted root partition with the default LUKS header format
diff --git a/nixos/tests/ipv6.nix b/nixos/tests/ipv6.nix
index 75faa6f602010..7f91457fa5ea8 100644
--- a/nixos/tests/ipv6.nix
+++ b/nixos/tests/ipv6.nix
@@ -4,7 +4,7 @@
 import ./make-test-python.nix ({ pkgs, lib, ...} : {
   name = "ipv6";
   meta = with pkgs.lib.maintainers; {
-    maintainers = [ eelco ];
+    maintainers = [ ];
   };
 
   nodes =
diff --git a/nixos/tests/jenkins.nix b/nixos/tests/jenkins.nix
index a8f6210006547..d7394c866c143 100644
--- a/nixos/tests/jenkins.nix
+++ b/nixos/tests/jenkins.nix
@@ -7,7 +7,7 @@
 import ./make-test-python.nix ({ pkgs, ...} : {
   name = "jenkins";
   meta = with pkgs.lib.maintainers; {
-    maintainers = [ bjornfor coconnor domenkozar eelco ];
+    maintainers = [ bjornfor coconnor domenkozar ];
   };
 
   nodes = {
diff --git a/nixos/tests/k3s/default.nix b/nixos/tests/k3s/default.nix
index 512dc06ee77ec..297b05a4e4a74 100644
--- a/nixos/tests/k3s/default.nix
+++ b/nixos/tests/k3s/default.nix
@@ -1,16 +1,20 @@
-{ system ? builtins.currentSystem
-, pkgs ? import ../../.. { inherit system; }
-, lib ? pkgs.lib
+{
+  system ? builtins.currentSystem,
+  pkgs ? import ../../.. { inherit system; },
+  lib ? pkgs.lib,
 }:
 let
   allK3s = lib.filterAttrs (n: _: lib.strings.hasPrefix "k3s_" n) pkgs;
 in
 {
   # Testing K3s with Etcd backend
-  etcd = lib.mapAttrs (_: k3s: import ./etcd.nix {
-    inherit system pkgs k3s;
-    inherit (pkgs) etcd;
-  }) allK3s;
+  etcd = lib.mapAttrs (
+    _: k3s:
+    import ./etcd.nix {
+      inherit system pkgs k3s;
+      inherit (pkgs) etcd;
+    }
+  ) allK3s;
   # Run a single node k3s cluster and verify a pod can run
   single-node = lib.mapAttrs (_: k3s: import ./single-node.nix { inherit system pkgs k3s; }) allK3s;
   # Run a multi-node k3s cluster and verify pod networking works across nodes
diff --git a/nixos/tests/k3s/etcd.nix b/nixos/tests/k3s/etcd.nix
index d6e9a294adb13..ac0aa90472516 100644
--- a/nixos/tests/k3s/etcd.nix
+++ b/nixos/tests/k3s/etcd.nix
@@ -1,100 +1,130 @@
-import ../make-test-python.nix ({ pkgs, lib, k3s, etcd, ... }:
-
-{
-  name = "${k3s.name}-etcd";
-
-  nodes = {
-
-    etcd = { ... }: {
-      services.etcd = {
-        enable = true;
-        openFirewall = true;
-        listenClientUrls = [ "http://192.168.1.1:2379" "http://127.0.0.1:2379" ];
-        listenPeerUrls = [ "http://192.168.1.1:2380" ];
-        initialAdvertisePeerUrls = [ "http://192.168.1.1:2380" ];
-        initialCluster = [ "etcd=http://192.168.1.1:2380" ];
-      };
-      networking = {
-        useDHCP = false;
-        defaultGateway = "192.168.1.1";
-        interfaces.eth1.ipv4.addresses = pkgs.lib.mkForce [
-          { address = "192.168.1.1"; prefixLength = 24; }
-        ];
-      };
-    };
+import ../make-test-python.nix (
+  {
+    pkgs,
+    lib,
+    k3s,
+    etcd,
+    ...
+  }:
+
+  {
+    name = "${k3s.name}-etcd";
+
+    nodes = {
+
+      etcd =
+        { ... }:
+        {
+          services.etcd = {
+            enable = true;
+            openFirewall = true;
+            listenClientUrls = [
+              "http://192.168.1.1:2379"
+              "http://127.0.0.1:2379"
+            ];
+            listenPeerUrls = [ "http://192.168.1.1:2380" ];
+            initialAdvertisePeerUrls = [ "http://192.168.1.1:2380" ];
+            initialCluster = [ "etcd=http://192.168.1.1:2380" ];
+          };
+          networking = {
+            useDHCP = false;
+            defaultGateway = "192.168.1.1";
+            interfaces.eth1.ipv4.addresses = pkgs.lib.mkForce [
+              {
+                address = "192.168.1.1";
+                prefixLength = 24;
+              }
+            ];
+          };
+        };
 
-    k3s = { pkgs, ... }: {
-      environment.systemPackages = with pkgs; [ jq ];
-      # k3s uses enough resources the default vm fails.
-      virtualisation.memorySize = 1536;
-      virtualisation.diskSize = 4096;
-
-      services.k3s = {
-        enable = true;
-        role = "server";
-        extraFlags = builtins.toString [
-          "--datastore-endpoint=\"http://192.168.1.1:2379\""
-          "--disable" "coredns"
-          "--disable" "local-storage"
-          "--disable" "metrics-server"
-          "--disable" "servicelb"
-          "--disable" "traefik"
-          "--node-ip" "192.168.1.2"
-        ];
-      };
-
-      networking = {
-        firewall = {
-          allowedTCPPorts = [ 2379 2380 6443 ];
-          allowedUDPPorts = [ 8472 ];
+      k3s =
+        { pkgs, ... }:
+        {
+          environment.systemPackages = with pkgs; [ jq ];
+          # k3s uses enough resources the default vm fails.
+          virtualisation.memorySize = 1536;
+          virtualisation.diskSize = 4096;
+
+          services.k3s = {
+            enable = true;
+            role = "server";
+            extraFlags = builtins.toString [
+              "--datastore-endpoint=\"http://192.168.1.1:2379\""
+              "--disable"
+              "coredns"
+              "--disable"
+              "local-storage"
+              "--disable"
+              "metrics-server"
+              "--disable"
+              "servicelb"
+              "--disable"
+              "traefik"
+              "--node-ip"
+              "192.168.1.2"
+            ];
+          };
+
+          networking = {
+            firewall = {
+              allowedTCPPorts = [
+                2379
+                2380
+                6443
+              ];
+              allowedUDPPorts = [ 8472 ];
+            };
+            useDHCP = false;
+            defaultGateway = "192.168.1.2";
+            interfaces.eth1.ipv4.addresses = pkgs.lib.mkForce [
+              {
+                address = "192.168.1.2";
+                prefixLength = 24;
+              }
+            ];
+          };
         };
-        useDHCP = false;
-        defaultGateway = "192.168.1.2";
-        interfaces.eth1.ipv4.addresses = pkgs.lib.mkForce [
-          { address = "192.168.1.2"; prefixLength = 24; }
-        ];
-      };
     };
 
-  };
-
-  testScript = ''
-    with subtest("should start etcd"):
-        etcd.start()
-        etcd.wait_for_unit("etcd.service")
+    testScript = ''
+      with subtest("should start etcd"):
+          etcd.start()
+          etcd.wait_for_unit("etcd.service")
 
-    with subtest("should wait for etcdctl endpoint status to succeed"):
-        etcd.wait_until_succeeds("etcdctl endpoint status")
+      with subtest("should wait for etcdctl endpoint status to succeed"):
+          etcd.wait_until_succeeds("etcdctl endpoint status")
 
-    with subtest("should start k3s"):
-        k3s.start()
-        k3s.wait_for_unit("k3s")
+      with subtest("should start k3s"):
+          k3s.start()
+          k3s.wait_for_unit("k3s")
 
-    with subtest("should test if kubectl works"):
-        k3s.wait_until_succeeds("k3s kubectl get node")
+      with subtest("should test if kubectl works"):
+          k3s.wait_until_succeeds("k3s kubectl get node")
 
-    with subtest("should wait for service account to show up; takes a sec"):
-        k3s.wait_until_succeeds("k3s kubectl get serviceaccount default")
+      with subtest("should wait for service account to show up; takes a sec"):
+          k3s.wait_until_succeeds("k3s kubectl get serviceaccount default")
 
-    with subtest("should create a sample secret object"):
-        k3s.succeed("k3s kubectl create secret generic nixossecret --from-literal thesecret=abacadabra")
+      with subtest("should create a sample secret object"):
+          k3s.succeed("k3s kubectl create secret generic nixossecret --from-literal thesecret=abacadabra")
 
-    with subtest("should check if secret is correct"):
-        k3s.wait_until_succeeds("[[ $(kubectl get secrets nixossecret -o json | jq -r .data.thesecret | base64 -d) == abacadabra ]]")
+      with subtest("should check if secret is correct"):
+          k3s.wait_until_succeeds("[[ $(kubectl get secrets nixossecret -o json | jq -r .data.thesecret | base64 -d) == abacadabra ]]")
 
-    with subtest("should have a secret in database"):
-        etcd.wait_until_succeeds("[[ $(etcdctl get /registry/secrets/default/nixossecret | head -c1 | wc -c) -ne 0 ]]")
+      with subtest("should have a secret in database"):
+          etcd.wait_until_succeeds("[[ $(etcdctl get /registry/secrets/default/nixossecret | head -c1 | wc -c) -ne 0 ]]")
 
-    with subtest("should delete the secret"):
-        k3s.succeed("k3s kubectl delete secret nixossecret")
+      with subtest("should delete the secret"):
+          k3s.succeed("k3s kubectl delete secret nixossecret")
 
-    with subtest("should not have a secret in database"):
-        etcd.wait_until_fails("[[ $(etcdctl get /registry/secrets/default/nixossecret | head -c1 | wc -c) -ne 0 ]]")
+      with subtest("should not have a secret in database"):
+          etcd.wait_until_fails("[[ $(etcdctl get /registry/secrets/default/nixossecret | head -c1 | wc -c) -ne 0 ]]")
 
-    with subtest("should shutdown k3s and etcd"):
-        k3s.shutdown()
-        etcd.shutdown()
-  '';
+      with subtest("should shutdown k3s and etcd"):
+          k3s.shutdown()
+          etcd.shutdown()
+    '';
 
-  meta.maintainers = etcd.meta.maintainers ++ k3s.meta.maintainers;
-})
+    meta.maintainers = etcd.meta.maintainers ++ k3s.meta.maintainers;
+  }
+)
diff --git a/nixos/tests/k3s/multi-node.nix b/nixos/tests/k3s/multi-node.nix
index 20279f3ca4b93..b618d2aff34c4 100644
--- a/nixos/tests/k3s/multi-node.nix
+++ b/nixos/tests/k3s/multi-node.nix
@@ -1,14 +1,30 @@
-import ../make-test-python.nix ({ pkgs, lib, k3s, ... }:
+import ../make-test-python.nix (
+  {
+    pkgs,
+    lib,
+    k3s,
+    ...
+  }:
   let
     imageEnv = pkgs.buildEnv {
       name = "k3s-pause-image-env";
-      paths = with pkgs; [ tini bashInteractive coreutils socat ];
+      paths = with pkgs; [
+        tini
+        bashInteractive
+        coreutils
+        socat
+      ];
     };
     pauseImage = pkgs.dockerTools.streamLayeredImage {
       name = "test.local/pause";
       tag = "local";
       contents = imageEnv;
-      config.Entrypoint = [ "/bin/tini" "--" "/bin/sleep" "inf" ];
+      config.Entrypoint = [
+        "/bin/tini"
+        "--"
+        "/bin/sleep"
+        "inf"
+      ];
     };
     # A daemonset that responds 'server' on port 8000
     networkTestDaemonset = pkgs.writeText "test.yml" ''
@@ -42,90 +58,135 @@ import ../make-test-python.nix ({ pkgs, lib, k3s, ... }:
     name = "${k3s.name}-multi-node";
 
     nodes = {
-      server = { pkgs, ... }: {
-        environment.systemPackages = with pkgs; [ gzip jq ];
-        # k3s uses enough resources the default vm fails.
-        virtualisation.memorySize = 1536;
-        virtualisation.diskSize = 4096;
-
-        services.k3s = {
-          inherit tokenFile;
-          enable = true;
-          role = "server";
-          package = k3s;
-          clusterInit = true;
-          extraFlags = builtins.toString [
-            "--disable" "coredns"
-            "--disable" "local-storage"
-            "--disable" "metrics-server"
-            "--disable" "servicelb"
-            "--disable" "traefik"
-            "--node-ip" "192.168.1.1"
-            "--pause-image" "test.local/pause:local"
+      server =
+        { pkgs, ... }:
+        {
+          environment.systemPackages = with pkgs; [
+            gzip
+            jq
+          ];
+          # k3s uses enough resources the default vm fails.
+          virtualisation.memorySize = 1536;
+          virtualisation.diskSize = 4096;
+
+          services.k3s = {
+            inherit tokenFile;
+            enable = true;
+            role = "server";
+            package = k3s;
+            clusterInit = true;
+            extraFlags = builtins.toString [
+              "--disable"
+              "coredns"
+              "--disable"
+              "local-storage"
+              "--disable"
+              "metrics-server"
+              "--disable"
+              "servicelb"
+              "--disable"
+              "traefik"
+              "--node-ip"
+              "192.168.1.1"
+              "--pause-image"
+              "test.local/pause:local"
+            ];
+          };
+          networking.firewall.allowedTCPPorts = [
+            2379
+            2380
+            6443
+          ];
+          networking.firewall.allowedUDPPorts = [ 8472 ];
+          networking.firewall.trustedInterfaces = [ "flannel.1" ];
+          networking.useDHCP = false;
+          networking.defaultGateway = "192.168.1.1";
+          networking.interfaces.eth1.ipv4.addresses = pkgs.lib.mkForce [
+            {
+              address = "192.168.1.1";
+              prefixLength = 24;
+            }
           ];
         };
-        networking.firewall.allowedTCPPorts = [ 2379 2380 6443 ];
-        networking.firewall.allowedUDPPorts = [ 8472 ];
-        networking.firewall.trustedInterfaces = [ "flannel.1" ];
-        networking.useDHCP = false;
-        networking.defaultGateway = "192.168.1.1";
-        networking.interfaces.eth1.ipv4.addresses = pkgs.lib.mkForce [
-          { address = "192.168.1.1"; prefixLength = 24; }
-        ];
-      };
-
-      server2 = { pkgs, ... }: {
-        environment.systemPackages = with pkgs; [ gzip jq ];
-        virtualisation.memorySize = 1536;
-        virtualisation.diskSize = 4096;
-
-        services.k3s = {
-          inherit tokenFile;
-          enable = true;
-          serverAddr = "https://192.168.1.1:6443";
-          clusterInit = false;
-          extraFlags = builtins.toString [
-            "--disable" "coredns"
-            "--disable" "local-storage"
-            "--disable" "metrics-server"
-            "--disable" "servicelb"
-            "--disable" "traefik"
-            "--node-ip" "192.168.1.3"
-            "--pause-image" "test.local/pause:local"
+
+      server2 =
+        { pkgs, ... }:
+        {
+          environment.systemPackages = with pkgs; [
+            gzip
+            jq
+          ];
+          virtualisation.memorySize = 1536;
+          virtualisation.diskSize = 4096;
+
+          services.k3s = {
+            inherit tokenFile;
+            enable = true;
+            serverAddr = "https://192.168.1.1:6443";
+            clusterInit = false;
+            extraFlags = builtins.toString [
+              "--disable"
+              "coredns"
+              "--disable"
+              "local-storage"
+              "--disable"
+              "metrics-server"
+              "--disable"
+              "servicelb"
+              "--disable"
+              "traefik"
+              "--node-ip"
+              "192.168.1.3"
+              "--pause-image"
+              "test.local/pause:local"
+            ];
+          };
+          networking.firewall.allowedTCPPorts = [
+            2379
+            2380
+            6443
+          ];
+          networking.firewall.allowedUDPPorts = [ 8472 ];
+          networking.firewall.trustedInterfaces = [ "flannel.1" ];
+          networking.useDHCP = false;
+          networking.defaultGateway = "192.168.1.3";
+          networking.interfaces.eth1.ipv4.addresses = pkgs.lib.mkForce [
+            {
+              address = "192.168.1.3";
+              prefixLength = 24;
+            }
           ];
         };
-        networking.firewall.allowedTCPPorts = [ 2379 2380 6443 ];
-        networking.firewall.allowedUDPPorts = [ 8472 ];
-        networking.firewall.trustedInterfaces = [ "flannel.1" ];
-        networking.useDHCP = false;
-        networking.defaultGateway = "192.168.1.3";
-        networking.interfaces.eth1.ipv4.addresses = pkgs.lib.mkForce [
-          { address = "192.168.1.3"; prefixLength = 24; }
-        ];
-      };
-
-      agent = { pkgs, ... }: {
-        virtualisation.memorySize = 1024;
-        virtualisation.diskSize = 2048;
-        services.k3s = {
-          inherit tokenFile;
-          enable = true;
-          role = "agent";
-          serverAddr = "https://192.168.1.3:6443";
-          extraFlags = lib.concatStringsSep " " [
-            "--pause-image" "test.local/pause:local"
-            "--node-ip" "192.168.1.2"
+
+      agent =
+        { pkgs, ... }:
+        {
+          virtualisation.memorySize = 1024;
+          virtualisation.diskSize = 2048;
+          services.k3s = {
+            inherit tokenFile;
+            enable = true;
+            role = "agent";
+            serverAddr = "https://192.168.1.3:6443";
+            extraFlags = lib.concatStringsSep " " [
+              "--pause-image"
+              "test.local/pause:local"
+              "--node-ip"
+              "192.168.1.2"
+            ];
+          };
+          networking.firewall.allowedTCPPorts = [ 6443 ];
+          networking.firewall.allowedUDPPorts = [ 8472 ];
+          networking.firewall.trustedInterfaces = [ "flannel.1" ];
+          networking.useDHCP = false;
+          networking.defaultGateway = "192.168.1.2";
+          networking.interfaces.eth1.ipv4.addresses = pkgs.lib.mkForce [
+            {
+              address = "192.168.1.2";
+              prefixLength = 24;
+            }
           ];
         };
-        networking.firewall.allowedTCPPorts = [ 6443 ];
-        networking.firewall.allowedUDPPorts = [ 8472 ];
-        networking.firewall.trustedInterfaces = [ "flannel.1" ];
-        networking.useDHCP = false;
-        networking.defaultGateway = "192.168.1.2";
-        networking.interfaces.eth1.ipv4.addresses = pkgs.lib.mkForce [
-          { address = "192.168.1.2"; prefixLength = 24; }
-        ];
-      };
     };
 
     meta.maintainers = k3s.meta.maintainers;
@@ -178,4 +239,5 @@ import ../make-test-python.nix ({ pkgs, lib, k3s, ... }:
       for m in machines:
           m.shutdown()
     '';
-  })
+  }
+)
diff --git a/nixos/tests/k3s/single-node.nix b/nixos/tests/k3s/single-node.nix
index b7ac5d9eeeac7..80d80a55ddf41 100644
--- a/nixos/tests/k3s/single-node.nix
+++ b/nixos/tests/k3s/single-node.nix
@@ -1,14 +1,29 @@
-import ../make-test-python.nix ({ pkgs, lib, k3s, ... }:
+import ../make-test-python.nix (
+  {
+    pkgs,
+    lib,
+    k3s,
+    ...
+  }:
   let
     imageEnv = pkgs.buildEnv {
       name = "k3s-pause-image-env";
-      paths = with pkgs; [ tini (hiPrio coreutils) busybox ];
+      paths = with pkgs; [
+        tini
+        (hiPrio coreutils)
+        busybox
+      ];
     };
     pauseImage = pkgs.dockerTools.streamLayeredImage {
       name = "test.local/pause";
       tag = "local";
       contents = imageEnv;
-      config.Entrypoint = [ "/bin/tini" "--" "/bin/sleep" "inf" ];
+      config.Entrypoint = [
+        "/bin/tini"
+        "--"
+        "/bin/sleep"
+        "inf"
+      ];
     };
     testPodYaml = pkgs.writeText "test.yml" ''
       apiVersion: v1
@@ -27,69 +42,83 @@ import ../make-test-python.nix ({ pkgs, lib, k3s, ... }:
     name = "${k3s.name}-single-node";
     meta.maintainers = k3s.meta.maintainers;
 
-    nodes.machine = { pkgs, ... }: {
-      environment.systemPackages = with pkgs; [ k3s gzip ];
+    nodes.machine =
+      { pkgs, ... }:
+      {
+        environment.systemPackages = with pkgs; [
+          k3s
+          gzip
+        ];
 
-      # k3s uses enough resources the default vm fails.
-      virtualisation.memorySize = 1536;
-      virtualisation.diskSize = 4096;
+        # k3s uses enough resources the default vm fails.
+        virtualisation.memorySize = 1536;
+        virtualisation.diskSize = 4096;
 
-      services.k3s.enable = true;
-      services.k3s.role = "server";
-      services.k3s.package = k3s;
-      # Slightly reduce resource usage
-      services.k3s.extraFlags = builtins.toString [
-        "--disable" "coredns"
-        "--disable" "local-storage"
-        "--disable" "metrics-server"
-        "--disable" "servicelb"
-        "--disable" "traefik"
-        "--pause-image" "test.local/pause:local"
-      ];
+        services.k3s.enable = true;
+        services.k3s.role = "server";
+        services.k3s.package = k3s;
+        # Slightly reduce resource usage
+        services.k3s.extraFlags = builtins.toString [
+          "--disable"
+          "coredns"
+          "--disable"
+          "local-storage"
+          "--disable"
+          "metrics-server"
+          "--disable"
+          "servicelb"
+          "--disable"
+          "traefik"
+          "--pause-image"
+          "test.local/pause:local"
+        ];
 
-      users.users = {
-        noprivs = {
-          isNormalUser = true;
-          description = "Can't access k3s by default";
-          password = "*";
+        users.users = {
+          noprivs = {
+            isNormalUser = true;
+            description = "Can't access k3s by default";
+            password = "*";
+          };
         };
       };
-    };
 
-    testScript = ''
-      start_all()
+    testScript =
+      ''
+        start_all()
 
-      machine.wait_for_unit("k3s")
-      machine.succeed("kubectl cluster-info")
-      machine.fail("sudo -u noprivs kubectl cluster-info")
+        machine.wait_for_unit("k3s")
+        machine.succeed("kubectl cluster-info")
+        machine.fail("sudo -u noprivs kubectl cluster-info")
       '' # Fix-Me: Tests fail for 'aarch64-linux' as: "CONFIG_CGROUP_FREEZER: missing (fail)"
-      + lib.optionalString (!pkgs.stdenv.isAarch64) ''machine.succeed("k3s check-config")'' + ''
+      + lib.optionalString (!pkgs.stdenv.isAarch64) ''machine.succeed("k3s check-config")''
+      + ''
 
-      machine.succeed(
-          "${pauseImage} | ctr image import -"
-      )
+        machine.succeed(
+            "${pauseImage} | ctr image import -"
+        )
 
-      # Also wait for our service account to show up; it takes a sec
-      machine.wait_until_succeeds("kubectl get serviceaccount default")
-      machine.succeed("kubectl apply -f ${testPodYaml}")
-      machine.succeed("kubectl wait --for 'condition=Ready' pod/test")
-      machine.succeed("kubectl delete -f ${testPodYaml}")
+        # Also wait for our service account to show up; it takes a sec
+        machine.wait_until_succeeds("kubectl get serviceaccount default")
+        machine.succeed("kubectl apply -f ${testPodYaml}")
+        machine.succeed("kubectl wait --for 'condition=Ready' pod/test")
+        machine.succeed("kubectl delete -f ${testPodYaml}")
 
-      # regression test for #176445
-      machine.fail("journalctl -o cat -u k3s.service | grep 'ipset utility not found'")
+        # regression test for #176445
+        machine.fail("journalctl -o cat -u k3s.service | grep 'ipset utility not found'")
 
-      with subtest("Run k3s-killall"):
-          # Call the killall script with a clean path to assert that
-          # all required commands are wrapped
-          output = machine.succeed("PATH= ${k3s}/bin/k3s-killall.sh 2>&1 | tee /dev/stderr")
-          assert "command not found" not in output, "killall script contains unknown command"
+        with subtest("Run k3s-killall"):
+            # Call the killall script with a clean path to assert that
+            # all required commands are wrapped
+            output = machine.succeed("PATH= ${k3s}/bin/k3s-killall.sh 2>&1 | tee /dev/stderr")
+            assert "command not found" not in output, "killall script contains unknown command"
 
-          # Check that killall cleaned up properly
-          machine.fail("systemctl is-active k3s.service")
-          machine.fail("systemctl list-units | grep containerd")
-          machine.fail("ip link show | awk -F': ' '{print $2}' | grep -e flannel -e cni0")
-          machine.fail("ip netns show | grep cni-")
+            # Check that killall cleaned up properly
+            machine.fail("systemctl is-active k3s.service")
+            machine.fail("systemctl list-units | grep containerd")
+            machine.fail("ip link show | awk -F': ' '{print $2}' | grep -e flannel -e cni0")
+            machine.fail("ip netns show | grep cni-")
 
-      machine.shutdown()
-    '';
-  })
+        machine.shutdown()
+      '';
+  }
+)
diff --git a/nixos/tests/keepalived.nix b/nixos/tests/keepalived.nix
index 16564511d85dc..052b36266d037 100644
--- a/nixos/tests/keepalived.nix
+++ b/nixos/tests/keepalived.nix
@@ -4,8 +4,8 @@ import ./make-test-python.nix ({ pkgs, lib, ... }: {
 
   nodes = {
     node1 = { pkgs, ... }: {
-      networking.firewall.extraCommands = "iptables -A INPUT -p vrrp -j ACCEPT";
       services.keepalived.enable = true;
+      services.keepalived.openFirewall = true;
       services.keepalived.vrrpInstances.test = {
         interface = "eth1";
         state = "MASTER";
@@ -16,8 +16,8 @@ import ./make-test-python.nix ({ pkgs, lib, ... }: {
       environment.systemPackages = [ pkgs.tcpdump ];
     };
     node2 = { pkgs, ... }: {
-      networking.firewall.extraCommands = "iptables -A INPUT -p vrrp -j ACCEPT";
       services.keepalived.enable = true;
+      services.keepalived.openFirewall = true;
       services.keepalived.vrrpInstances.test = {
         interface = "eth1";
         state = "MASTER";
diff --git a/nixos/tests/kernel-generic.nix b/nixos/tests/kernel-generic.nix
index 5f0e7b3e37cd7..11a3bf80c15e4 100644
--- a/nixos/tests/kernel-generic.nix
+++ b/nixos/tests/kernel-generic.nix
@@ -31,6 +31,8 @@ let
       linux_5_15_hardened
       linux_6_1_hardened
       linux_6_6_hardened
+      linux_6_8_hardened
+      linux_6_9_hardened
       linux_rt_5_4
       linux_rt_5_10
       linux_rt_5_15
diff --git a/nixos/tests/knot.nix b/nixos/tests/knot.nix
index eec94a22f2fa7..4441fed6ef507 100644
--- a/nixos/tests/knot.nix
+++ b/nixos/tests/knot.nix
@@ -190,6 +190,10 @@ in {
     primary.wait_for_unit("knot.service")
     secondary.wait_for_unit("knot.service")
 
+    for zone in ("example.com.", "sub.example.com."):
+        secondary.wait_until_succeeds(
+          f"knotc zone-status {zone} | grep -q 'serial: 2019031302'"
+        )
 
     def test(host, query_type, query, pattern):
         out = client.succeed(f"khost -t {query_type} {query} {host}").strip()
diff --git a/nixos/tests/login.nix b/nixos/tests/login.nix
index 67f5764a0a162..bcaee03175ad3 100644
--- a/nixos/tests/login.nix
+++ b/nixos/tests/login.nix
@@ -3,7 +3,7 @@ import ./make-test-python.nix ({ pkgs, latestKernel ? false, ... }:
 {
   name = "login";
   meta = with pkgs.lib.maintainers; {
-    maintainers = [ eelco ];
+    maintainers = [ ];
   };
 
   nodes.machine =
diff --git a/nixos/tests/logrotate.nix b/nixos/tests/logrotate.nix
index bcbe89c259ae5..f9c5e90609709 100644
--- a/nixos/tests/logrotate.nix
+++ b/nixos/tests/logrotate.nix
@@ -16,52 +16,60 @@ import ./make-test-python.nix ({ pkgs, ... }: rec {
   };
 
   nodes = {
-    defaultMachine = { ... }: { };
+    defaultMachine = { ... }: {
+      services.logrotate.enable = true;
+    };
     failingMachine = { ... }: {
-      services.logrotate.configFile = pkgs.writeText "logrotate.conf" ''
-        # self-written config file
-        su notarealuser notagroupeither
-      '';
+      services.logrotate = {
+        enable = true;
+        configFile = pkgs.writeText "logrotate.conf" ''
+          # self-written config file
+          su notarealuser notagroupeither
+        '';
+      };
     };
     machine = { config, ... }: {
       imports = [ importTest ];
 
-      services.logrotate.settings = {
-        # remove default frequency header and add another
-        header = {
-          frequency = null;
-          delaycompress = true;
-        };
-        # extra global setting... affecting nothing
-        last_line = {
-          global = true;
-          priority = 2000;
-          shred = true;
-        };
-        # using mail somewhere should add --mail to logrotate invocation
-        sendmail = {
-          mail = "user@domain.tld";
-        };
-        # postrotate should be suffixed by 'endscript'
-        postrotate = {
-          postrotate = "touch /dev/null";
-        };
-        # check checkConfig works as expected: there is nothing to check here
-        # except that the file build passes
-        checkConf = {
-          su = "root utmp";
-          createolddir = "0750 root utmp";
-          create = "root utmp";
-          "create " = "0750 root utmp";
-        };
-        # multiple paths should be aggregated
-        multipath = {
-          files = [ "file1" "file2" ];
-        };
-        # overriding imported path should keep existing attributes
-        # (e.g. olddir is still set)
-        import = {
-          notifempty = true;
+      services.logrotate = {
+        enable = true;
+        settings = {
+          # remove default frequency header and add another
+          header = {
+            frequency = null;
+            delaycompress = true;
+          };
+          # extra global setting... affecting nothing
+          last_line = {
+            global = true;
+            priority = 2000;
+            shred = true;
+          };
+          # using mail somewhere should add --mail to logrotate invocation
+          sendmail = {
+            mail = "user@domain.tld";
+          };
+          # postrotate should be suffixed by 'endscript'
+          postrotate = {
+            postrotate = "touch /dev/null";
+          };
+          # check checkConfig works as expected: there is nothing to check here
+          # except that the file build passes
+          checkConf = {
+            su = "root utmp";
+            createolddir = "0750 root utmp";
+            create = "root utmp";
+            "create " = "0750 root utmp";
+          };
+          # multiple paths should be aggregated
+          multipath = {
+            files = [ "file1" "file2" ];
+          };
+          # overriding imported path should keep existing attributes
+          # (e.g. olddir is still set)
+          import = {
+            notifempty = true;
+          };
         };
       };
     };
diff --git a/nixos/tests/lomiri.nix b/nixos/tests/lomiri.nix
index 9d6337e9977cb..99f04a303be31 100644
--- a/nixos/tests/lomiri.nix
+++ b/nixos/tests/lomiri.nix
@@ -19,9 +19,13 @@ in {
       inherit description password;
     };
 
+    # To control mouse via scripting
+    programs.ydotool.enable = true;
+
     services.desktopManager.lomiri.enable = lib.mkForce true;
     services.displayManager.defaultSession = lib.mkForce "lomiri";
 
+    # Help with OCR
     fonts.packages = [ pkgs.inconsolata ];
 
     environment = {
@@ -114,17 +118,9 @@ in {
   enableOCR = true;
 
   testScript = { nodes, ... }: ''
-    def open_starter():
-        """
-        Open the starter, and ensure it's opened.
-        """
-        machine.send_key("meta_l-a")
-        # Look for any of the default apps
-        machine.wait_for_text(r"(Search|System|Settings|Morph|Browser|Terminal|Alacritty)")
-
     def toggle_maximise():
         """
-        Send the keybind to maximise the current window.
+        Maximise the current window.
         """
         machine.send_key("ctrl-meta_l-up")
 
@@ -135,13 +131,43 @@ in {
         machine.send_key("esc")
         machine.sleep(5)
 
+    def mouse_click(xpos, ypos):
+        """
+        Move the mouse to a screen location and hit left-click.
+        """
+
+        # Need to reset to top-left, --absolute doesn't work?
+        machine.execute("ydotool mousemove -- -10000 -10000")
+        machine.sleep(2)
+
+        # Move
+        machine.execute(f"ydotool mousemove -- {xpos} {ypos}")
+        machine.sleep(2)
+
+        # Click (C0 - left button: down & up)
+        machine.execute("ydotool click 0xC0")
+        machine.sleep(2)
+
+    def open_starter():
+        """
+        Open the starter, and ensure it's opened.
+        """
+
+        # Using the keybind has a chance of instantly closing the menu again? Just click the button
+        mouse_click(20, 30)
+
+        # Look for Search box & GUI-less content-hub examples, highest chances of avoiding false positives
+        machine.wait_for_text(r"(Search|Export|Import|Share)")
+
     start_all()
     machine.wait_for_unit("multi-user.target")
 
     # Lomiri in greeter mode should work & be able to start a session
     with subtest("lomiri greeter works"):
         machine.wait_for_unit("display-manager.service")
-        # Start page shows current tie
+        machine.wait_until_succeeds("pgrep -u lightdm -f 'lomiri --mode=greeter'")
+
+        # Start page shows current time
         machine.wait_for_text(r"(AM|PM)")
         machine.screenshot("lomiri_greeter_launched")
 
@@ -152,7 +178,6 @@ in {
 
         # Login
         machine.send_chars("${password}\n")
-        # Best way I can think of to differenciate "Lomiri in LightDM greeter mode" from "Lomiri in user shell mode"
         machine.wait_until_succeeds("pgrep -u ${user} -f 'lomiri --mode=full-shell'")
 
     # The session should start, and not be stuck in i.e. a crash loop
@@ -196,6 +221,17 @@ in {
         machine.screenshot("alacritty_opens")
         machine.send_key("alt-f4")
 
+    # Morph is how we go online
+    with subtest("morph browser works"):
+        open_starter()
+        machine.send_chars("Morph\n")
+        machine.wait_for_text(r"(Bookmarks|address|site|visited any)")
+        machine.screenshot("morph_open")
+
+        # morph-browser has a separate VM test, there isn't anything new we could test here
+
+        # Keep it running, we're using it to check content-hub communication from LSS
+
     # LSS provides DE settings
     with subtest("system settings open"):
         open_starter()
@@ -231,64 +267,75 @@ in {
         machine.wait_for_text("Morph") # or Gallery, but Morph is already packaged
         machine.screenshot("settings_content-hub_peers")
 
-        # Sadly, it doesn't seem possible to actually select a peer and attempt a content-hub data exchange with just the keyboard
+        # Select Morph as content source
+        mouse_click(300, 100)
 
-        machine.send_key("alt-f4")
+        # Expect Morph to be brought into the foreground, with its Downloads page open
+        machine.wait_for_text("No downloads")
 
-    # Morph is how we go online
-    with subtest("morph browser works"):
-        open_starter()
-        machine.send_chars("Morph\n")
-        machine.wait_for_text(r"(Bookmarks|address|site|visited any)")
-        machine.screenshot("morph_open")
+        # If content-hub encounters a problem, it may have crashed the original application issuing the request.
+        # Check that it's still alive
+        machine.succeed("pgrep -u ${user} -f lomiri-system-settings")
 
-        # morph-browser has a separate VM test, there isn't anything new we could test here
+        machine.screenshot("content-hub_exchange")
 
-        machine.send_key("alt-f4")
+        # Testing any more would require more applications & setup, the fact that it's already being attempted is a good sign
+        machine.send_key("esc")
+
+        machine.send_key("alt-f4") # LSS
+        machine.sleep(2) # focus is slow to switch to second window, closing it *really* helps with OCR afterwards
+        machine.send_key("alt-f4") # Morph
 
     # The ayatana indicators are an important part of the experience, and they hold the only graphical way of exiting the session.
-    # Reaching them via the intended way requires wayland mouse control, but ydotool lacks a module for its daemon:
-    # https://github.com/NixOS/nixpkgs/issues/183659
-    # Luckily, there's a test app that also displays their contents, but it's abit inconsistent. Hopefully this is *good-enough*.
+    # There's a test app we could use that also displays their contents, but it's abit inconsistent.
     with subtest("ayatana indicators work"):
-        open_starter()
-        machine.send_chars("Indicators\n")
-        machine.wait_for_text(r"(Indicators|Client|List|network|datetime|session)")
+        mouse_click(735, 0) # the cog in the top-right, for the session indicator
+        machine.wait_for_text(r"(Notifications|Rotation|Battery|Sound|Time|Date|System)")
         machine.screenshot("indicators_open")
 
-        # Element tab order within the indicator menus is not fully deterministic
-        # Only check that the indicators are listed & their items load
+        # Indicator order within the menus *should* be fixed based on per-indicator order setting
+        # Session is the one we clicked, but the last we should test (logout). Go as far left as we can test.
+        machine.send_key("left")
+        machine.send_key("left")
+        machine.send_key("left")
+        machine.send_key("left")
+        machine.send_key("left")
+        # Notifications are usually empty, nothing to check there
+
+        with subtest("ayatana indicator display works"):
+            # We start on this, don't go right
+            machine.wait_for_text("Lock")
+            machine.screenshot("indicators_display")
 
         with subtest("lomiri indicator network works"):
-            # Select indicator-network
-            machine.send_key("tab")
-            # Don't go further down, first entry
-            machine.send_key("ret")
+            machine.send_key("right")
             machine.wait_for_text(r"(Flight|Wi-Fi)")
             machine.screenshot("indicators_network")
 
-        machine.send_key("shift-tab")
-        machine.send_key("ret")
-        machine.wait_for_text(r"(Indicators|Client|List|network|datetime|session)")
+        with subtest("ayatana indicator sound works"):
+            machine.send_key("right")
+            machine.wait_for_text(r"(Silent|Volume)")
+            machine.screenshot("indicators_sound")
+
+        with subtest("ayatana indicator power works"):
+            machine.send_key("right")
+            machine.wait_for_text(r"(Charge|Battery settings)")
+            machine.screenshot("indicators_power")
 
         with subtest("ayatana indicator datetime works"):
-            # Select ayatana-indicator-datetime
-            machine.send_key("tab")
-            machine.send_key("down")
-            machine.send_key("ret")
+            machine.send_key("right")
             machine.wait_for_text("Time and Date Settings")
             machine.screenshot("indicators_timedate")
 
-        machine.send_key("shift-tab")
-        machine.send_key("ret")
-        machine.wait_for_text(r"(Indicators|Client|List|network|datetime|session)")
-
         with subtest("ayatana indicator session works"):
-            # Select ayatana-indicator-session
-            machine.send_key("tab")
-            machine.send_key("down")
-            machine.send_key("ret")
+            machine.send_key("right")
             machine.wait_for_text("Log Out")
             machine.screenshot("indicators_session")
+
+            # We should be able to log out and return to the greeter
+            mouse_click(720, 280) # "Log Out"
+            mouse_click(400, 240) # confirm logout
+            machine.wait_until_fails("pgrep -u ${user} -f 'lomiri --mode=full-shell'")
+            machine.wait_until_succeeds("pgrep -u lightdm -f 'lomiri --mode=greeter'")
   '';
 })
diff --git a/nixos/tests/mediamtx.nix b/nixos/tests/mediamtx.nix
index 8cacd02631d95..f40c4a8cb5832 100644
--- a/nixos/tests/mediamtx.nix
+++ b/nixos/tests/mediamtx.nix
@@ -1,57 +1,60 @@
-import ./make-test-python.nix ({ pkgs, lib, ...} :
+import ./make-test-python.nix (
+  { pkgs, lib, ... }:
 
-{
-  name = "mediamtx";
-  meta.maintainers = with lib.maintainers; [ fpletz ];
+  {
+    name = "mediamtx";
+    meta.maintainers = with lib.maintainers; [ fpletz ];
 
-  nodes = {
-    machine = { config, ... }: {
-      services.mediamtx = {
-        enable = true;
-        settings = {
-          metrics = true;
-          paths.all.source = "publisher";
+    nodes = {
+      machine = {
+        services.mediamtx = {
+          enable = true;
+          settings = {
+            metrics = true;
+            paths.all.source = "publisher";
+          };
         };
-      };
 
-      systemd.services.rtmp-publish = {
-        description = "Publish an RTMP stream to mediamtx";
-        after = [ "mediamtx.service" ];
-        bindsTo = [ "mediamtx.service" ];
-        wantedBy = [ "multi-user.target" ];
-        serviceConfig = {
-          DynamicUser = true;
-          Restart = "on-failure";
-          RestartSec = "1s";
-          TimeoutStartSec = "10s";
-          ExecStart = "${lib.getBin pkgs.ffmpeg-headless}/bin/ffmpeg -re -f lavfi -i smptebars=size=800x600:rate=10 -c libx264 -f flv rtmp://localhost:1935/test";
+        systemd.services.rtmp-publish = {
+          description = "Publish an RTMP stream to mediamtx";
+          after = [ "mediamtx.service" ];
+          bindsTo = [ "mediamtx.service" ];
+          wantedBy = [ "multi-user.target" ];
+          serviceConfig = {
+            DynamicUser = true;
+            Restart = "on-failure";
+            RestartSec = "1s";
+            TimeoutStartSec = "10s";
+            ExecStart = "${lib.getBin pkgs.ffmpeg-headless}/bin/ffmpeg -re -f lavfi -i smptebars=size=800x600:rate=10 -c libx264 -f flv rtmp://localhost:1935/test";
+          };
         };
-      };
 
-      systemd.services.rtmp-receive = {
-        description = "Receive an RTMP stream from mediamtx";
-        after = [ "rtmp-publish.service" ];
-        bindsTo = [ "rtmp-publish.service" ];
-        wantedBy = [ "multi-user.target" ];
-        serviceConfig = {
-          DynamicUser = true;
-          Restart = "on-failure";
-          RestartSec = "1s";
-          TimeoutStartSec = "10s";
-          ExecStart = "${lib.getBin pkgs.ffmpeg-headless}/bin/ffmpeg -y -re -i rtmp://localhost:1935/test -f flv /dev/null";
+        systemd.services.rtmp-receive = {
+          description = "Receive an RTMP stream from mediamtx";
+          after = [ "rtmp-publish.service" ];
+          bindsTo = [ "rtmp-publish.service" ];
+          wantedBy = [ "multi-user.target" ];
+          serviceConfig = {
+            DynamicUser = true;
+            Restart = "on-failure";
+            RestartSec = "1s";
+            TimeoutStartSec = "10s";
+            ExecStart = "${lib.getBin pkgs.ffmpeg-headless}/bin/ffmpeg -y -re -i rtmp://localhost:1935/test -f flv /dev/null";
+          };
         };
       };
     };
-  };
 
-  testScript = ''
-    start_all()
+    testScript = ''
+      start_all()
 
-    machine.wait_for_unit("mediamtx.service")
-    machine.wait_for_unit("rtmp-publish.service")
-    machine.wait_for_unit("rtmp-receive.service")
-    machine.wait_for_open_port(9998)
-    machine.succeed("curl http://localhost:9998/metrics | grep '^rtmp_conns.*state=\"publish\".*1$'")
-    machine.succeed("curl http://localhost:9998/metrics | grep '^rtmp_conns.*state=\"read\".*1$'")
-  '';
-})
+      machine.wait_for_unit("mediamtx.service")
+      machine.wait_for_unit("rtmp-publish.service")
+      machine.sleep(10)
+      machine.wait_for_unit("rtmp-receive.service")
+      machine.wait_for_open_port(9998)
+      machine.succeed("curl http://localhost:9998/metrics | grep '^rtmp_conns.*state=\"publish\".*1$'")
+      machine.succeed("curl http://localhost:9998/metrics | grep '^rtmp_conns.*state=\"read\".*1$'")
+    '';
+  }
+)
diff --git a/nixos/tests/misc.nix b/nixos/tests/misc.nix
index e7842debba7a2..83e0f46be3ecf 100644
--- a/nixos/tests/misc.nix
+++ b/nixos/tests/misc.nix
@@ -1,164 +1,185 @@
 # Miscellaneous small tests that don't warrant their own VM run.
-
-import ./make-test-python.nix ({ lib, pkgs, ...} : let
-  foo = pkgs.writeText "foo" "Hello World";
-in {
-  name = "misc";
-  meta.maintainers = with lib.maintainers; [ eelco ];
-
-  nodes.machine =
-    { lib, ... }:
-    { swapDevices = lib.mkOverride 0
-        [ { device = "/root/swapfile"; size = 128; } ];
-      environment.variables.EDITOR = lib.mkOverride 0 "emacs";
-      documentation.nixos.enable = lib.mkOverride 0 true;
-      systemd.tmpfiles.rules = [ "d /tmp 1777 root root 10d" ];
-      systemd.tmpfiles.settings."10-test"."/tmp/somefile".d = {};
-      virtualisation.fileSystems = { "/tmp2" =
-        { fsType = "tmpfs";
-          options = [ "mode=1777" "noauto" ];
-        };
-        # Tests https://discourse.nixos.org/t/how-to-make-a-derivations-executables-have-the-s-permission/8555
-        "/user-mount/point" = {
-          device = "/user-mount/source";
-          fsType = "none";
-          options = [ "bind" "rw" "user" "noauto" ];
-        };
-        "/user-mount/denied-point" = {
-          device = "/user-mount/denied-source";
-          fsType = "none";
-          options = [ "bind" "rw" "noauto" ];
+{ pkgs, ... }:
+
+let
+  inherit (pkgs) lib;
+  tests = {
+    default = testsForPackage { nixPackage = pkgs.nix; };
+    lix = testsForPackage { nixPackage = pkgs.lix; };
+  };
+
+  testsForPackage = args: lib.recurseIntoAttrs {
+    # If the attribute is not named 'test'
+    # You will break all the universe on the release-*.nix side of things.
+    # `discoverTests` relies on `test` existence to perform a `callTest`.
+    test = testMiscFeatures args;
+    passthru.override = args': testsForPackage (args // args');
+  };
+
+  testMiscFeatures = { nixPackage, ... }: pkgs.testers.nixosTest (
+  let
+    foo = pkgs.writeText "foo" "Hello World";
+  in {
+    name = "misc";
+    meta.maintainers = with lib.maintainers; [ raitobezarius ];
+
+    nodes.machine =
+      { lib, ... }:
+      { swapDevices = lib.mkOverride 0
+          [ { device = "/root/swapfile"; size = 128; } ];
+        environment.variables.EDITOR = lib.mkOverride 0 "emacs";
+        documentation.nixos.enable = lib.mkOverride 0 true;
+        systemd.tmpfiles.rules = [ "d /tmp 1777 root root 10d" ];
+        systemd.tmpfiles.settings."10-test"."/tmp/somefile".d = {};
+        virtualisation.fileSystems = { "/tmp2" =
+          { fsType = "tmpfs";
+            options = [ "mode=1777" "noauto" ];
+          };
+          # Tests https://discourse.nixos.org/t/how-to-make-a-derivations-executables-have-the-s-permission/8555
+          "/user-mount/point" = {
+            device = "/user-mount/source";
+            fsType = "none";
+            options = [ "bind" "rw" "user" "noauto" ];
+          };
+          "/user-mount/denied-point" = {
+            device = "/user-mount/denied-source";
+            fsType = "none";
+            options = [ "bind" "rw" "noauto" ];
+          };
         };
+        systemd.automounts = lib.singleton
+          { wantedBy = [ "multi-user.target" ];
+            where = "/tmp2";
+          };
+        users.users.sybil = { isNormalUser = true; group = "wheel"; };
+        users.users.alice = { isNormalUser = true; };
+        security.sudo = { enable = true; wheelNeedsPassword = false; };
+        boot.kernel.sysctl."vm.swappiness" = 1;
+        boot.kernelParams = [ "vsyscall=emulate" ];
+        system.extraDependencies = [ foo ];
+
+        nix.package = nixPackage;
       };
-      systemd.automounts = lib.singleton
-        { wantedBy = [ "multi-user.target" ];
-          where = "/tmp2";
-        };
-      users.users.sybil = { isNormalUser = true; group = "wheel"; };
-      users.users.alice = { isNormalUser = true; };
-      security.sudo = { enable = true; wheelNeedsPassword = false; };
-      boot.kernel.sysctl."vm.swappiness" = 1;
-      boot.kernelParams = [ "vsyscall=emulate" ];
-      system.extraDependencies = [ foo ];
-    };
-
-  testScript =
-    ''
-      import json
-
-
-      def get_path_info(path):
-          result = machine.succeed(f"nix --option experimental-features nix-command path-info --json {path}")
-          parsed = json.loads(result)
-          return parsed
-
-
-      with subtest("nix-db"):
-          info = get_path_info("${foo}")
-          print(info)
-
-          if (
-              info[0]["narHash"]
-              != "sha256-BdMdnb/0eWy3EddjE83rdgzWWpQjfWPAj3zDIFMD3Ck="
-          ):
-              raise Exception("narHash not set")
-
-          if info[0]["narSize"] != 128:
-              raise Exception("narSize not set")
-
-      with subtest("nixos-version"):
-          machine.succeed("[ `nixos-version | wc -w` = 2 ]")
-
-      with subtest("nixos-rebuild"):
-          assert "NixOS module" in machine.succeed("nixos-rebuild --help")
-
-      with subtest("Sanity check for uid/gid assignment"):
-          assert "4" == machine.succeed("id -u messagebus").strip()
-          assert "4" == machine.succeed("id -g messagebus").strip()
-          assert "users:x:100:" == machine.succeed("getent group users").strip()
-
-      with subtest("Regression test for GMP aborts on QEMU."):
-          machine.succeed("expr 1 + 2")
-
-      with subtest("the swap file got created"):
-          machine.wait_for_unit("root-swapfile.swap")
-          machine.succeed("ls -l /root/swapfile | grep 134217728")
-
-      with subtest("whether kernel.poweroff_cmd is set"):
-          machine.succeed('[ -x "$(cat /proc/sys/kernel/poweroff_cmd)" ]')
-
-      with subtest("whether the io cgroupv2 controller is properly enabled"):
-          machine.succeed("grep -q '\\bio\\b' /sys/fs/cgroup/cgroup.controllers")
-
-      with subtest("whether we have a reboot record in wtmp"):
-          machine.shutdown
-          machine.wait_for_unit("multi-user.target")
-          machine.succeed("last | grep reboot >&2")
-
-      with subtest("whether we can override environment variables"):
-          machine.succeed('[ "$EDITOR" = emacs ]')
-
-      with subtest("whether hostname (and by extension nss_myhostname) works"):
-          assert "machine" == machine.succeed("hostname").strip()
-          assert "machine" == machine.succeed("hostname -s").strip()
-
-      with subtest("whether systemd-udevd automatically loads modules for our hardware"):
-          machine.succeed("systemctl start systemd-udev-settle.service")
-          machine.wait_for_unit("systemd-udev-settle.service")
-          assert "mousedev" in machine.succeed("lsmod")
-
-      with subtest("whether systemd-tmpfiles-clean works"):
-          machine.succeed(
-              "touch /tmp/foo", "systemctl start systemd-tmpfiles-clean", "[ -e /tmp/foo ]"
-          )
-          # move into the future
-          machine.succeed(
-              'date -s "@$(($(date +%s) + 1000000))"',
-              "systemctl start systemd-tmpfiles-clean",
-          )
-          machine.fail("[ -e /tmp/foo ]")
-
-      with subtest("whether systemd-tmpfiles settings works"):
-          machine.succeed("[ -e /tmp/somefile ]")
-
-      with subtest("whether automounting works"):
-          machine.fail("grep '/tmp2 tmpfs' /proc/mounts")
-          machine.succeed("touch /tmp2/x")
-          machine.succeed("grep '/tmp2 tmpfs' /proc/mounts")
-
-      with subtest(
-          "Whether mounting by a user is possible with the `user` option in fstab (#95444)"
-      ):
-          machine.succeed("mkdir -p /user-mount/source")
-          machine.succeed("touch /user-mount/source/file")
-          machine.succeed("chmod -R a+Xr /user-mount/source")
-          machine.succeed("mkdir /user-mount/point")
-          machine.succeed("chown alice:users /user-mount/point")
-          machine.succeed("su - alice -c 'mount /user-mount/point'")
-          machine.succeed("su - alice -c 'ls /user-mount/point/file'")
-      with subtest(
-          "Whether mounting by a user is denied without the `user` option in  fstab"
-      ):
-          machine.succeed("mkdir -p /user-mount/denied-source")
-          machine.succeed("touch /user-mount/denied-source/file")
-          machine.succeed("chmod -R a+Xr /user-mount/denied-source")
-          machine.succeed("mkdir /user-mount/denied-point")
-          machine.succeed("chown alice:users /user-mount/denied-point")
-          machine.fail("su - alice -c 'mount /user-mount/denied-point'")
-
-      with subtest("shell-vars"):
-          machine.succeed('[ -n "$NIX_PATH" ]')
-
-      with subtest("nix-db"):
-          machine.succeed("nix-store -qR /run/current-system | grep nixos-")
-
-      with subtest("Test sysctl"):
-          machine.wait_for_unit("systemd-sysctl.service")
-          assert "1" == machine.succeed("sysctl -ne vm.swappiness").strip()
-          machine.execute("sysctl vm.swappiness=60")
-          assert "60" == machine.succeed("sysctl -ne vm.swappiness").strip()
-
-      with subtest("Test boot parameters"):
-          assert "vsyscall=emulate" in machine.succeed("cat /proc/cmdline")
-    '';
-})
+
+    testScript =
+      ''
+        import json
+
+
+        def get_path_info(path):
+            result = machine.succeed(f"nix --option experimental-features nix-command path-info --json {path}")
+            parsed = json.loads(result)
+            return parsed
+
+
+        with subtest("nix-db"):
+            info = get_path_info("${foo}")
+            print(info)
+
+            if (
+                info[0]["narHash"]
+                != "sha256-BdMdnb/0eWy3EddjE83rdgzWWpQjfWPAj3zDIFMD3Ck="
+            ):
+                raise Exception("narHash not set")
+
+            if info[0]["narSize"] != 128:
+                raise Exception("narSize not set")
+
+        with subtest("nixos-version"):
+            machine.succeed("[ `nixos-version | wc -w` = 2 ]")
+
+        with subtest("nixos-rebuild"):
+            assert "NixOS module" in machine.succeed("nixos-rebuild --help")
+
+        with subtest("Sanity check for uid/gid assignment"):
+            assert "4" == machine.succeed("id -u messagebus").strip()
+            assert "4" == machine.succeed("id -g messagebus").strip()
+            assert "users:x:100:" == machine.succeed("getent group users").strip()
+
+        with subtest("Regression test for GMP aborts on QEMU."):
+            machine.succeed("expr 1 + 2")
+
+        with subtest("the swap file got created"):
+            machine.wait_for_unit("root-swapfile.swap")
+            machine.succeed("ls -l /root/swapfile | grep 134217728")
+
+        with subtest("whether kernel.poweroff_cmd is set"):
+            machine.succeed('[ -x "$(cat /proc/sys/kernel/poweroff_cmd)" ]')
+
+        with subtest("whether the io cgroupv2 controller is properly enabled"):
+            machine.succeed("grep -q '\\bio\\b' /sys/fs/cgroup/cgroup.controllers")
+
+        with subtest("whether we have a reboot record in wtmp"):
+            machine.shutdown
+            machine.wait_for_unit("multi-user.target")
+            machine.succeed("last | grep reboot >&2")
+
+        with subtest("whether we can override environment variables"):
+            machine.succeed('[ "$EDITOR" = emacs ]')
+
+        with subtest("whether hostname (and by extension nss_myhostname) works"):
+            assert "machine" == machine.succeed("hostname").strip()
+            assert "machine" == machine.succeed("hostname -s").strip()
+
+        with subtest("whether systemd-udevd automatically loads modules for our hardware"):
+            machine.succeed("systemctl start systemd-udev-settle.service")
+            machine.wait_for_unit("systemd-udev-settle.service")
+            assert "mousedev" in machine.succeed("lsmod")
+
+        with subtest("whether systemd-tmpfiles-clean works"):
+            machine.succeed(
+                "touch /tmp/foo", "systemctl start systemd-tmpfiles-clean", "[ -e /tmp/foo ]"
+            )
+            # move into the future
+            machine.succeed(
+                'date -s "@$(($(date +%s) + 1000000))"',
+                "systemctl start systemd-tmpfiles-clean",
+            )
+            machine.fail("[ -e /tmp/foo ]")
+
+        with subtest("whether systemd-tmpfiles settings works"):
+            machine.succeed("[ -e /tmp/somefile ]")
+
+        with subtest("whether automounting works"):
+            machine.fail("grep '/tmp2 tmpfs' /proc/mounts")
+            machine.succeed("touch /tmp2/x")
+            machine.succeed("grep '/tmp2 tmpfs' /proc/mounts")
+
+        with subtest(
+            "Whether mounting by a user is possible with the `user` option in fstab (#95444)"
+        ):
+            machine.succeed("mkdir -p /user-mount/source")
+            machine.succeed("touch /user-mount/source/file")
+            machine.succeed("chmod -R a+Xr /user-mount/source")
+            machine.succeed("mkdir /user-mount/point")
+            machine.succeed("chown alice:users /user-mount/point")
+            machine.succeed("su - alice -c 'mount /user-mount/point'")
+            machine.succeed("su - alice -c 'ls /user-mount/point/file'")
+        with subtest(
+            "Whether mounting by a user is denied without the `user` option in  fstab"
+        ):
+            machine.succeed("mkdir -p /user-mount/denied-source")
+            machine.succeed("touch /user-mount/denied-source/file")
+            machine.succeed("chmod -R a+Xr /user-mount/denied-source")
+            machine.succeed("mkdir /user-mount/denied-point")
+            machine.succeed("chown alice:users /user-mount/denied-point")
+            machine.fail("su - alice -c 'mount /user-mount/denied-point'")
+
+        with subtest("shell-vars"):
+            machine.succeed('[ -n "$NIX_PATH" ]')
+
+        with subtest("nix-db"):
+            machine.succeed("nix-store -qR /run/current-system | grep nixos-")
+
+        with subtest("Test sysctl"):
+            machine.wait_for_unit("systemd-sysctl.service")
+            assert "1" == machine.succeed("sysctl -ne vm.swappiness").strip()
+            machine.execute("sysctl vm.swappiness=60")
+            assert "60" == machine.succeed("sysctl -ne vm.swappiness").strip()
+
+        with subtest("Test boot parameters"):
+            assert "vsyscall=emulate" in machine.succeed("cat /proc/cmdline")
+      '';
+  });
+  in
+  tests
diff --git a/nixos/tests/mumble.nix b/nixos/tests/mumble.nix
index 8eee454721a13..12fa00b79bbf8 100644
--- a/nixos/tests/mumble.nix
+++ b/nixos/tests/mumble.nix
@@ -15,7 +15,7 @@ in
 {
   name = "mumble";
   meta = with pkgs.lib.maintainers; {
-    maintainers = [ thoughtpolice eelco ];
+    maintainers = [ thoughtpolice ];
   };
 
   nodes = {
diff --git a/nixos/tests/munin.nix b/nixos/tests/munin.nix
index e371b2dffa6b8..7b7bf6f41c046 100644
--- a/nixos/tests/munin.nix
+++ b/nixos/tests/munin.nix
@@ -4,7 +4,7 @@
 import ./make-test-python.nix ({ pkgs, ...} : {
   name = "munin";
   meta = with pkgs.lib.maintainers; {
-    maintainers = [ domenkozar eelco ];
+    maintainers = [ domenkozar ];
   };
 
   nodes = {
diff --git a/nixos/tests/mysql/common.nix b/nixos/tests/mysql/common.nix
index 1cf52347f4c74..ad54b0e00c1b3 100644
--- a/nixos/tests/mysql/common.nix
+++ b/nixos/tests/mysql/common.nix
@@ -4,7 +4,7 @@
     inherit (pkgs) mysql80;
   };
   perconaPackages = {
-    inherit (pkgs) percona-server_8_0;
+    inherit (pkgs) percona-server_lts percona-server_innovation;
   };
   mkTestName = pkg: "mariadb_${builtins.replaceStrings ["."] [""] (lib.versions.majorMinor pkg.version)}";
 }
diff --git a/nixos/tests/mysql/mysql.nix b/nixos/tests/mysql/mysql.nix
index 0a61f9d38fe2e..093da4f46aa10 100644
--- a/nixos/tests/mysql/mysql.nix
+++ b/nixos/tests/mysql/mysql.nix
@@ -146,6 +146,6 @@ in
   }) mariadbPackages)
   // (lib.mapAttrs (_: package: makeMySQLTest {
     inherit package;
-    name = "percona_8_0";
+    name = builtins.replaceStrings ["-"] ["_"] package.pname;
     hasMroonga = false; useSocketAuth = false;
   }) perconaPackages)
diff --git a/nixos/tests/nat.nix b/nixos/tests/nat.nix
index 0b617cea7774c..8b682a8b3aa7c 100644
--- a/nixos/tests/nat.nix
+++ b/nixos/tests/nat.nix
@@ -22,7 +22,7 @@ import ./make-test-python.nix ({ pkgs, lib, withFirewall, nftables ? false, ...
     name = "nat" + (lib.optionalString nftables "Nftables")
                  + (if withFirewall then "WithFirewall" else "Standalone");
     meta = with pkgs.lib.maintainers; {
-      maintainers = [ eelco rob ];
+      maintainers = [ rob ];
     };
 
     nodes =
diff --git a/nixos/tests/nfs/simple.nix b/nixos/tests/nfs/simple.nix
index 026da9563bc03..077c1d4109356 100644
--- a/nixos/tests/nfs/simple.nix
+++ b/nixos/tests/nfs/simple.nix
@@ -20,7 +20,7 @@ in
 {
   name = "nfs";
   meta = with pkgs.lib.maintainers; {
-    maintainers = [ eelco ];
+    maintainers = [ ];
   };
 
   nodes =
diff --git a/nixos/tests/openssh.nix b/nixos/tests/openssh.nix
index 2684b6f45e84e..140723a2df810 100644
--- a/nixos/tests/openssh.nix
+++ b/nixos/tests/openssh.nix
@@ -5,7 +5,7 @@ let inherit (import ./ssh-keys.nix pkgs)
 in {
   name = "openssh";
   meta = with pkgs.lib.maintainers; {
-    maintainers = [ aszlig eelco ];
+    maintainers = [ aszlig ];
   };
 
   nodes = {
diff --git a/nixos/tests/pgvecto-rs.nix b/nixos/tests/pgvecto-rs.nix
index cd871dab6a0f1..8d9d6c0b88f51 100644
--- a/nixos/tests/pgvecto-rs.nix
+++ b/nixos/tests/pgvecto-rs.nix
@@ -66,7 +66,7 @@ let
     '';
 
   };
-  applicablePostgresqlVersions = filterAttrs (_: value: versionAtLeast value.version "12") postgresql-versions;
+  applicablePostgresqlVersions = filterAttrs (_: value: versionAtLeast value.version "14") postgresql-versions;
 in
 mapAttrs'
   (name: package: {
diff --git a/nixos/tests/printing.nix b/nixos/tests/printing.nix
index 29c5d810f215a..b413996c67db8 100644
--- a/nixos/tests/printing.nix
+++ b/nixos/tests/printing.nix
@@ -9,7 +9,7 @@ import ./make-test-python.nix (
 {
   name = "printing";
   meta = with pkgs.lib.maintainers; {
-    maintainers = [ domenkozar eelco matthewbauer ];
+    maintainers = [ domenkozar matthewbauer ];
   };
 
   nodes.server = { ... }: {
diff --git a/nixos/tests/private-gpt.nix b/nixos/tests/private-gpt.nix
new file mode 100644
index 0000000000000..d19e167cc303c
--- /dev/null
+++ b/nixos/tests/private-gpt.nix
@@ -0,0 +1,27 @@
+import ./make-test-python.nix ({ pkgs, lib, ... }:
+let
+  mainPort = "8001";
+in
+{
+  name = "private-gpt";
+  meta = with lib.maintainers; {
+    maintainers = [ drupol ];
+  };
+
+  nodes = {
+    machine = { ... }: {
+      services.private-gpt = {
+        enable = true;
+      };
+    };
+  };
+
+  testScript = ''
+    machine.start()
+
+    machine.wait_for_unit("private-gpt.service")
+    machine.wait_for_open_port(${mainPort})
+
+    machine.succeed("curl http://127.0.0.1:${mainPort}")
+  '';
+})
diff --git a/nixos/tests/proxy.nix b/nixos/tests/proxy.nix
index f8a3d576903e3..ce7131b09a8ab 100644
--- a/nixos/tests/proxy.nix
+++ b/nixos/tests/proxy.nix
@@ -12,7 +12,7 @@ let
 in {
   name = "proxy";
   meta = with pkgs.lib.maintainers; {
-    maintainers = [ eelco ];
+    maintainers = [ ];
   };
 
   nodes = {
diff --git a/nixos/tests/quake3.nix b/nixos/tests/quake3.nix
index 2d8c5207001cb..4b7ca03b365b5 100644
--- a/nixos/tests/quake3.nix
+++ b/nixos/tests/quake3.nix
@@ -32,7 +32,7 @@ in
 rec {
   name = "quake3";
   meta = with lib.maintainers; {
-    maintainers = [ domenkozar eelco ];
+    maintainers = [ domenkozar ];
   };
 
   # TODO: lcov doesn't work atm
diff --git a/nixos/tests/rabbitmq.nix b/nixos/tests/rabbitmq.nix
index 040679e68d989..4b8921662b7f4 100644
--- a/nixos/tests/rabbitmq.nix
+++ b/nixos/tests/rabbitmq.nix
@@ -9,7 +9,7 @@ in
 {
   name = "rabbitmq";
   meta = with pkgs.lib.maintainers; {
-    maintainers = [ eelco offline ];
+    maintainers = [ offline ];
   };
 
   nodes.machine = {
diff --git a/nixos/tests/samba.nix b/nixos/tests/samba.nix
index 252c3dd9c76e9..53cdbbe1c40f1 100644
--- a/nixos/tests/samba.nix
+++ b/nixos/tests/samba.nix
@@ -3,7 +3,7 @@ import ./make-test-python.nix ({ pkgs, ... }:
 {
   name = "samba";
 
-  meta.maintainers = [ pkgs.lib.maintainers.eelco ];
+  meta.maintainers = [ ];
 
   nodes =
     { client =
diff --git a/nixos/tests/simple.nix b/nixos/tests/simple.nix
index c36287b4e843b..afd49d481a65d 100644
--- a/nixos/tests/simple.nix
+++ b/nixos/tests/simple.nix
@@ -1,7 +1,7 @@
 import ./make-test-python.nix ({ pkgs, ...} : {
   name = "simple";
   meta = with pkgs.lib.maintainers; {
-    maintainers = [ eelco ];
+    maintainers = [ ];
   };
 
   nodes.machine = { ... }: {
diff --git a/nixos/tests/smokeping.nix b/nixos/tests/smokeping.nix
index 04f8139642918..fe1ecad9969b0 100644
--- a/nixos/tests/smokeping.nix
+++ b/nixos/tests/smokeping.nix
@@ -11,7 +11,6 @@ import ./make-test-python.nix ({ pkgs, ...} : {
         networking.domain = "example.com"; # FQDN: sm.example.com
         services.smokeping = {
           enable = true;
-          port = 8081;
           mailHost = "127.0.0.2";
           probeConfig = ''
             + FPing
@@ -25,12 +24,19 @@ import ./make-test-python.nix ({ pkgs, ...} : {
   testScript = ''
     start_all()
     sm.wait_for_unit("smokeping")
-    sm.wait_for_unit("thttpd")
+    sm.wait_for_unit("nginx")
     sm.wait_for_file("/var/lib/smokeping/data/Local/LocalMachine.rrd")
-    sm.succeed("curl -s -f localhost:8081/smokeping.fcgi?target=Local")
+    sm.succeed("curl -s -f localhost/smokeping.fcgi?target=Local")
     # Check that there's a helpful page without explicit path as well.
-    sm.succeed("curl -s -f localhost:8081")
+    sm.succeed("curl -s -f localhost")
     sm.succeed("ls /var/lib/smokeping/cache/Local/LocalMachine_mini.png")
     sm.succeed("ls /var/lib/smokeping/cache/index.html")
+
+    # stop and start the service like nixos-rebuild would do
+    # see https://github.com/NixOS/nixpkgs/issues/265953)
+    sm.succeed("systemctl stop smokeping")
+    sm.succeed("systemctl start smokeping")
+    # ensure all services restarted properly
+    sm.succeed("systemctl --failed | grep -q '0 loaded units listed'")
   '';
 })
diff --git a/nixos/tests/stalwart-mail.nix b/nixos/tests/stalwart-mail.nix
index 634c0e2e39261..4075b32e2c1f7 100644
--- a/nixos/tests/stalwart-mail.nix
+++ b/nixos/tests/stalwart-mail.nix
@@ -1,120 +1,147 @@
 # Rudimentary test checking that the Stalwart email server can:
 # - receive some message through SMTP submission, then
 # - serve this message through IMAP.
+{
+  system ? builtins.currentSystem,
+  config ? { },
+  pkgs ? import ../../.. { inherit system config; },
 
+  lib ? pkgs.lib,
+}:
 let
   certs = import ./common/acme/server/snakeoil-certs.nix;
   domain = certs.domain;
-
-in import ./make-test-python.nix ({ lib, ... }: {
-  name = "stalwart-mail";
-
-  nodes.main = { pkgs, ... }: {
-    security.pki.certificateFiles = [ certs.ca.cert ];
-
-    services.stalwart-mail = {
-      enable = true;
-      settings = {
-        server.hostname = domain;
-
-        certificate."snakeoil" = {
-          cert = "file://${certs.${domain}.cert}";
-          private-key = "file://${certs.${domain}.key}";
-        };
-
-        server.tls = {
-          certificate = "snakeoil";
+  makeTest = import ./make-test-python.nix;
+  mkTestName =
+    pkg: "${pkg.pname}_${pkg.version}";
+  stalwartPackages = {
+    inherit (pkgs) stalwart-mail_0_6 stalwart-mail;
+  };
+  stalwartAtLeast = lib.versionAtLeast;
+  makeStalwartTest =
+    {
+      package,
+      name ? mkTestName package,
+    }:
+    makeTest {
+      inherit name;
+      meta.maintainers = with lib.maintainers; [
+        happysalada pacien onny
+      ];
+
+      nodes.machine = { lib, ... }: {
+
+        security.pki.certificateFiles = [ certs.ca.cert ];
+
+        services.stalwart-mail = {
           enable = true;
-          implicit = false;
-        };
-
-        server.listener = {
-          "smtp-submission" = {
-            bind = [ "[::]:587" ];
-            protocol = "smtp";
-          };
-
-          "imap" = {
-            bind = [ "[::]:143" ];
-            protocol = "imap";
+          inherit package;
+          settings = {
+            server.hostname = domain;
+
+            # TODO: Remove backwards compatibility as soon as we drop legacy version 0.6.0
+            certificate."snakeoil" = let
+              certPath = if stalwartAtLeast package.version "0.7.0" then "%{file://${certs.${domain}.cert}}%" else "file://${certs.${domain}.cert}";
+              keyPath = if stalwartAtLeast package.version "0.7.0" then "%{file:${certs.${domain}.key}}%" else "file://${certs.${domain}.key}";
+            in {
+              cert = certPath;
+              private-key = keyPath;
+            };
+
+            server.tls = {
+              certificate = "snakeoil";
+              enable = true;
+              implicit = false;
+            };
+
+            server.listener = {
+              "smtp-submission" = {
+                bind = [ "[::]:587" ];
+                protocol = "smtp";
+              };
+
+              "imap" = {
+                bind = [ "[::]:143" ];
+                protocol = "imap";
+              };
+            };
+
+            session.auth.mechanisms = "[plain]";
+            session.auth.directory = "'in-memory'";
+            storage.directory = "in-memory";
+
+            session.rcpt.directory = "'in-memory'";
+            queue.outbound.next-hop = "'local'";
+
+            directory."in-memory" = {
+              type = "memory";
+              # TODO: Remove backwards compatibility as soon as we drop legacy version 0.6.0
+              principals = let
+                condition = if stalwartAtLeast package.version "0.7.0" then "class" else "type";
+              in builtins.map (p: p // { ${condition} = "individual"; }) [
+                {
+                  name = "alice";
+                  secret = "foobar";
+                  email = [ "alice@${domain}" ];
+                }
+                {
+                  name = "bob";
+                  secret = "foobar";
+                  email = [ "bob@${domain}" ];
+                }
+              ];
+            };
           };
         };
 
-        session.auth.mechanisms = [ "PLAIN" ];
-        session.auth.directory = "in-memory";
-        storage.directory = "in-memory";  # shared with imap
-
-        session.rcpt.directory = "in-memory";
-        queue.outbound.next-hop = [ "local" ];
-
-        directory."in-memory" = {
-          type = "memory";
-          principals = [
-            {
-              type = "individual";
-              name = "alice";
-              secret = "foobar";
-              email = [ "alice@${domain}" ];
-            }
-            {
-              type = "individual";
-              name = "bob";
-              secret = "foobar";
-              email = [ "bob@${domain}" ];
-            }
-          ];
-        };
-      };
-    };
+        environment.systemPackages = [
+          (pkgs.writers.writePython3Bin "test-smtp-submission" { } ''
+            from smtplib import SMTP
+
+            with SMTP('localhost', 587) as smtp:
+                smtp.starttls()
+                smtp.login('alice', 'foobar')
+                smtp.sendmail(
+                    'alice@${domain}',
+                    'bob@${domain}',
+                    """
+                        From: alice@${domain}
+                        To: bob@${domain}
+                        Subject: Some test message
+
+                        This is a test message.
+                    """.strip()
+                )
+          '')
+
+          (pkgs.writers.writePython3Bin "test-imap-read" { } ''
+            from imaplib import IMAP4
+
+            with IMAP4('localhost') as imap:
+                imap.starttls()
+                status, [caps] = imap.login('bob', 'foobar')
+                assert status == 'OK'
+                imap.select()
+                status, [ref] = imap.search(None, 'ALL')
+                assert status == 'OK'
+                [msgId] = ref.split()
+                status, msg = imap.fetch(msgId, 'BODY[TEXT]')
+                assert status == 'OK'
+                assert msg[0][1].strip() == b'This is a test message.'
+          '')
+        ];
 
-    environment.systemPackages = [
-      (pkgs.writers.writePython3Bin "test-smtp-submission" { } ''
-        from smtplib import SMTP
-
-        with SMTP('localhost', 587) as smtp:
-            smtp.starttls()
-            smtp.login('alice', 'foobar')
-            smtp.sendmail(
-                'alice@${domain}',
-                'bob@${domain}',
-                """
-                    From: alice@${domain}
-                    To: bob@${domain}
-                    Subject: Some test message
-
-                    This is a test message.
-                """.strip()
-            )
-      '')
-
-      (pkgs.writers.writePython3Bin "test-imap-read" { } ''
-        from imaplib import IMAP4
-
-        with IMAP4('localhost') as imap:
-            imap.starttls()
-            status, [caps] = imap.login('bob', 'foobar')
-            assert status == 'OK'
-            imap.select()
-            status, [ref] = imap.search(None, 'ALL')
-            assert status == 'OK'
-            [msgId] = ref.split()
-            status, msg = imap.fetch(msgId, 'BODY[TEXT]')
-            assert status == 'OK'
-            assert msg[0][1].strip() == b'This is a test message.'
-      '')
-    ];
-  };
-
-  testScript = /* python */ ''
-    main.wait_for_unit("stalwart-mail.service")
-    main.wait_for_open_port(587)
-    main.wait_for_open_port(143)
+      };
 
-    main.succeed("test-smtp-submission")
-    main.succeed("test-imap-read")
-  '';
+      testScript = ''
+        start_all()
+        machine.wait_for_unit("stalwart-mail.service")
+        machine.wait_for_open_port(587)
+        machine.wait_for_open_port(143)
 
-  meta = {
-    maintainers = with lib.maintainers; [ happysalada pacien ];
-  };
-})
+        machine.succeed("test-smtp-submission")
+        machine.succeed("test-imap-read")
+      '';
+    };
+in
+lib.mapAttrs (_: package: makeStalwartTest { inherit package; }) stalwartPackages
diff --git a/nixos/tests/step-ca.nix b/nixos/tests/step-ca.nix
index a855b590232dd..184c35f6b85cc 100644
--- a/nixos/tests/step-ca.nix
+++ b/nixos/tests/step-ca.nix
@@ -62,6 +62,24 @@ import ./make-test-python.nix ({ pkgs, ... }:
             };
           };
 
+        caclientcaddy =
+          { config, pkgs, ... }: {
+            security.pki.certificateFiles = [ "${test-certificates}/root_ca.crt" ];
+
+            networking.firewall.allowedTCPPorts = [ 80 443 ];
+
+            services.caddy = {
+              enable = true;
+              virtualHosts."caclientcaddy".extraConfig = ''
+                respond "Welcome to Caddy!"
+
+                tls caddy@example.org {
+                  ca https://caserver:8443/acme/acme/directory
+                }
+              '';
+            };
+          };
+
         catester = { config, pkgs, ... }: {
           security.pki.certificateFiles = [ "${test-certificates}/root_ca.crt" ];
         };
@@ -71,7 +89,12 @@ import ./make-test-python.nix ({ pkgs, ... }:
       ''
         catester.start()
         caserver.wait_for_unit("step-ca.service")
+        caserver.wait_until_succeeds("journalctl -o cat -u step-ca.service | grep '${pkgs.step-ca.version}'")
+
         caclient.wait_for_unit("acme-finished-caclient.target")
         catester.succeed("curl https://caclient/ | grep \"Welcome to nginx!\"")
+
+        caclientcaddy.wait_for_unit("caddy.service")
+        catester.succeed("curl https://caclientcaddy/ | grep \"Welcome to Caddy!\"")
       '';
   })
diff --git a/nixos/tests/stub-ld.nix b/nixos/tests/stub-ld.nix
index 25161301741b7..72b0aebf3e6ce 100644
--- a/nixos/tests/stub-ld.nix
+++ b/nixos/tests/stub-ld.nix
@@ -45,10 +45,10 @@ import ./make-test-python.nix ({ lib, pkgs, ... }: {
           ${if32 "machine.succeed('test -L /${libDir32}/${ldsoBasename32}')"}
 
       with subtest("Try FHS executable"):
-          machine.copy_from_host('${test-exec.${pkgs.system}}','test-exec')
+          machine.copy_from_host('${test-exec.${pkgs.stdenv.hostPlatform.system}}','test-exec')
           machine.succeed('if test-exec/${exec-name} 2>outfile; then false; else [ $? -eq 127 ];fi')
           machine.succeed('grep -qi nixos outfile')
-          ${if32 "machine.copy_from_host('${test-exec.${pkgs32.system}}','test-exec32')"}
+          ${if32 "machine.copy_from_host('${test-exec.${pkgs32.stdenv.hostPlatform.system}}','test-exec32')"}
           ${if32 "machine.succeed('if test-exec32/${exec-name} 2>outfile32; then false; else [ $? -eq 127 ];fi')"}
           ${if32 "machine.succeed('grep -qi nixos outfile32')"}
 
diff --git a/nixos/tests/switch-test.nix b/nixos/tests/switch-test.nix
index 4a7bcd5a82264..d90e5bb088cee 100644
--- a/nixos/tests/switch-test.nix
+++ b/nixos/tests/switch-test.nix
@@ -1,6 +1,6 @@
 # Test configuration switching.
 
-import ./make-test-python.nix ({ lib, pkgs, ...} : let
+import ./make-test-python.nix ({ lib, pkgs, ng, ...} : let
 
   # Simple service that can either be socket-activated or that will
   # listen on port 1234 if not socket-activated.
@@ -48,6 +48,11 @@ in {
 
   nodes = {
     machine = { pkgs, lib, ... }: {
+      system.switch = {
+        enable = !ng;
+        enableNg = ng;
+      };
+
       environment.systemPackages = [ pkgs.socat ]; # for the socket activation stuff
       users.mutableUsers = false;
 
diff --git a/nixos/tests/systemd-confinement.nix b/nixos/tests/systemd-confinement.nix
deleted file mode 100644
index bde5b770ea50d..0000000000000
--- a/nixos/tests/systemd-confinement.nix
+++ /dev/null
@@ -1,184 +0,0 @@
-import ./make-test-python.nix {
-  name = "systemd-confinement";
-
-  nodes.machine = { pkgs, lib, ... }: let
-    testServer = pkgs.writeScript "testserver.sh" ''
-      #!${pkgs.runtimeShell}
-      export PATH=${lib.escapeShellArg "${pkgs.coreutils}/bin"}
-      ${lib.escapeShellArg pkgs.runtimeShell} 2>&1
-      echo "exit-status:$?"
-    '';
-
-    testClient = pkgs.writeScriptBin "chroot-exec" ''
-      #!${pkgs.runtimeShell} -e
-      output="$(echo "$@" | nc -NU "/run/test$(< /teststep).sock")"
-      ret="$(echo "$output" | sed -nre '$s/^exit-status:([0-9]+)$/\1/p')"
-      echo "$output" | head -n -1
-      exit "''${ret:-1}"
-    '';
-
-    mkTestStep = num: {
-      testScript,
-      config ? {},
-      serviceName ? "test${toString num}",
-    }: {
-      systemd.sockets.${serviceName} = {
-        description = "Socket for Test Service ${toString num}";
-        wantedBy = [ "sockets.target" ];
-        socketConfig.ListenStream = "/run/test${toString num}.sock";
-        socketConfig.Accept = true;
-      };
-
-      systemd.services."${serviceName}@" = {
-        description = "Confined Test Service ${toString num}";
-        confinement = (config.confinement or {}) // { enable = true; };
-        serviceConfig = (config.serviceConfig or {}) // {
-          ExecStart = testServer;
-          StandardInput = "socket";
-        };
-      } // removeAttrs config [ "confinement" "serviceConfig" ];
-
-      __testSteps = lib.mkOrder num (''
-        machine.succeed("echo ${toString num} > /teststep")
-      '' + testScript);
-    };
-
-  in {
-    imports = lib.imap1 mkTestStep [
-      { config.confinement.mode = "chroot-only";
-        testScript = ''
-          with subtest("chroot-only confinement"):
-              paths = machine.succeed('chroot-exec ls -1 / | paste -sd,').strip()
-              assert_eq(paths, "bin,nix,run")
-              uid = machine.succeed('chroot-exec id -u').strip()
-              assert_eq(uid, "0")
-              machine.succeed("chroot-exec chown 65534 /bin")
-        '';
-      }
-      { testScript = ''
-          with subtest("full confinement with APIVFS"):
-              machine.fail("chroot-exec ls -l /etc")
-              machine.fail("chroot-exec chown 65534 /bin")
-              assert_eq(machine.succeed('chroot-exec id -u').strip(), "0")
-              machine.succeed("chroot-exec chown 0 /bin")
-        '';
-      }
-      { config.serviceConfig.BindReadOnlyPaths = [ "/etc" ];
-        testScript = ''
-          with subtest("check existence of bind-mounted /etc"):
-              passwd = machine.succeed('chroot-exec cat /etc/passwd').strip()
-              assert len(passwd) > 0, "/etc/passwd must not be empty"
-        '';
-      }
-      { config.serviceConfig.User = "chroot-testuser";
-        config.serviceConfig.Group = "chroot-testgroup";
-        testScript = ''
-          with subtest("check if User/Group really runs as non-root"):
-              machine.succeed("chroot-exec ls -l /dev")
-              uid = machine.succeed('chroot-exec id -u').strip()
-              assert uid != "0", "UID of chroot-testuser shouldn't be 0"
-              machine.fail("chroot-exec touch /bin/test")
-        '';
-      }
-      (let
-        symlink = pkgs.runCommand "symlink" {
-          target = pkgs.writeText "symlink-target" "got me\n";
-        } "ln -s \"$target\" \"$out\"";
-      in {
-        config.confinement.packages = lib.singleton symlink;
-        testScript = ''
-          with subtest("check if symlinks are properly bind-mounted"):
-              machine.fail("chroot-exec test -e /etc")
-              text = machine.succeed('chroot-exec cat ${symlink}').strip()
-              assert_eq(text, "got me")
-        '';
-      })
-      { config.serviceConfig.User = "chroot-testuser";
-        config.serviceConfig.Group = "chroot-testgroup";
-        config.serviceConfig.StateDirectory = "testme";
-        testScript = ''
-          with subtest("check if StateDirectory works"):
-              machine.succeed("chroot-exec touch /tmp/canary")
-              machine.succeed('chroot-exec "echo works > /var/lib/testme/foo"')
-              machine.succeed('test "$(< /var/lib/testme/foo)" = works')
-              machine.succeed("test ! -e /tmp/canary")
-        '';
-      }
-      { testScript = ''
-          with subtest("check if /bin/sh works"):
-              machine.succeed(
-                  "chroot-exec test -e /bin/sh",
-                  'test "$(chroot-exec \'/bin/sh -c "echo bar"\')" = bar',
-              )
-        '';
-      }
-      { config.confinement.binSh = null;
-        testScript = ''
-          with subtest("check if suppressing /bin/sh works"):
-              machine.succeed("chroot-exec test ! -e /bin/sh")
-              machine.succeed('test "$(chroot-exec \'/bin/sh -c "echo foo"\')" != foo')
-        '';
-      }
-      { config.confinement.binSh = "${pkgs.hello}/bin/hello";
-        testScript = ''
-          with subtest("check if we can set /bin/sh to something different"):
-              machine.succeed("chroot-exec test -e /bin/sh")
-              machine.succeed('test "$(chroot-exec /bin/sh -g foo)" = foo')
-        '';
-      }
-      { config.environment.FOOBAR = pkgs.writeText "foobar" "eek\n";
-        testScript = ''
-          with subtest("check if only Exec* dependencies are included"):
-              machine.succeed('test "$(chroot-exec \'cat "$FOOBAR"\')" != eek')
-        '';
-      }
-      { config.environment.FOOBAR = pkgs.writeText "foobar" "eek\n";
-        config.confinement.fullUnit = true;
-        testScript = ''
-          with subtest("check if all unit dependencies are included"):
-              machine.succeed('test "$(chroot-exec \'cat "$FOOBAR"\')" = eek')
-        '';
-      }
-      { serviceName = "shipped-unitfile";
-        config.confinement.mode = "chroot-only";
-        testScript = ''
-          with subtest("check if shipped unit file still works"):
-              machine.succeed(
-                  'chroot-exec \'kill -9 $$ 2>&1 || :\' | '
-                  'grep -q "Too many levels of symbolic links"'
-              )
-        '';
-      }
-    ];
-
-    options.__testSteps = lib.mkOption {
-      type = lib.types.lines;
-      description = "All of the test steps combined as a single script.";
-    };
-
-    config.environment.systemPackages = lib.singleton testClient;
-    config.systemd.packages = lib.singleton (pkgs.writeTextFile {
-      name = "shipped-unitfile";
-      destination = "/etc/systemd/system/shipped-unitfile@.service";
-      text = ''
-        [Service]
-        SystemCallFilter=~kill
-        SystemCallErrorNumber=ELOOP
-      '';
-    });
-
-    config.users.groups.chroot-testgroup = {};
-    config.users.users.chroot-testuser = {
-      isSystemUser = true;
-      description = "Chroot Test User";
-      group = "chroot-testgroup";
-    };
-  };
-
-  testScript = { nodes, ... }: ''
-    def assert_eq(a, b):
-        assert a == b, f"{a} != {b}"
-
-    machine.wait_for_unit("multi-user.target")
-  '' + nodes.machine.config.__testSteps;
-}
diff --git a/nixos/tests/systemd-confinement/checkperms.py b/nixos/tests/systemd-confinement/checkperms.py
new file mode 100644
index 0000000000000..3c7ba279a3d20
--- /dev/null
+++ b/nixos/tests/systemd-confinement/checkperms.py
@@ -0,0 +1,187 @@
+import errno
+import os
+
+from enum import IntEnum
+from pathlib import Path
+
+
+class Accessibility(IntEnum):
+    """
+    The level of accessibility we have on a file or directory.
+
+    This is needed to assess the attack surface on the file system namespace we
+    have within a confined service. Higher levels mean more permissions for the
+    user and thus a bigger attack surface.
+    """
+    NONE = 0
+
+    # Directories can be listed or files can be read.
+    READABLE = 1
+
+    # This is for special file systems such as procfs and for stuff such as
+    # FIFOs or character special files. The reason why this has a lower value
+    # than WRITABLE is because those files are more restricted on what and how
+    # they can be written to.
+    SPECIAL = 2
+
+    # Another special case are sticky directories, which do allow write access
+    # but restrict deletion. This does *not* apply to sticky directories that
+    # are read-only.
+    STICKY = 3
+
+    # Essentially full permissions, the kind of accessibility we want to avoid
+    # in most cases.
+    WRITABLE = 4
+
+    def assert_on(self, path: Path) -> None:
+        """
+        Raise an AssertionError if the given 'path' allows for more
+        accessibility than 'self'.
+        """
+        actual = self.NONE
+
+        if path.is_symlink():
+            actual = self.READABLE
+        elif path.is_dir():
+            writable = True
+
+            dummy_file = path / 'can_i_write'
+            try:
+                dummy_file.touch()
+            except OSError as e:
+                if e.errno in [errno.EROFS, errno.EACCES]:
+                    writable = False
+                else:
+                    raise
+            else:
+                dummy_file.unlink()
+
+            if writable:
+                # The reason why we test this *after* we made sure it's
+                # writable is because we could have a sticky directory where
+                # the current user doesn't have write access.
+                if path.stat().st_mode & 0o1000 == 0o1000:
+                    actual = self.STICKY
+                else:
+                    actual = self.WRITABLE
+            else:
+                actual = self.READABLE
+        elif path.is_file():
+            try:
+                with path.open('rb') as fp:
+                    fp.read(1)
+                actual = self.READABLE
+            except PermissionError:
+                pass
+
+            writable = True
+            try:
+                with path.open('ab') as fp:
+                    fp.write('x')
+                    size = fp.tell()
+                    fp.truncate(size)
+            except PermissionError:
+                writable = False
+            except OSError as e:
+                if e.errno == errno.ETXTBSY:
+                    writable = os.access(path, os.W_OK)
+                elif e.errno == errno.EROFS:
+                    writable = False
+                else:
+                    raise
+
+            # Let's always try to fail towards being writable, so if *either*
+            # access(2) or a real write is successful it's writable. This is to
+            # make sure we don't accidentally introduce no-ops if we have bugs
+            # in the more complicated real write code above.
+            if writable or os.access(path, os.W_OK):
+                actual = self.WRITABLE
+        else:
+            # We need to be very careful when writing to or reading from
+            # special files (eg.  FIFOs), since they can possibly block. So if
+            # it's not a file, just trust that access(2) won't lie.
+            if os.access(path, os.R_OK):
+                actual = self.READABLE
+
+            if os.access(path, os.W_OK):
+                actual = self.SPECIAL
+
+        if actual > self:
+            stat = path.stat()
+            details = ', '.join([
+                f'permissions: {stat.st_mode & 0o7777:o}',
+                f'uid: {stat.st_uid}',
+                f'group: {stat.st_gid}',
+            ])
+
+            raise AssertionError(
+                f'Expected at most {self!r} but got {actual!r} for path'
+                f' {path} ({details}).'
+            )
+
+
+def is_special_fs(path: Path) -> bool:
+    """
+    Check whether the given path truly is a special file system such as procfs
+    or sysfs.
+    """
+    try:
+        if path == Path('/proc'):
+            return (path / 'version').read_text().startswith('Linux')
+        elif path == Path('/sys'):
+            return b'Linux' in (path / 'kernel' / 'notes').read_bytes()
+    except FileNotFoundError:
+        pass
+    return False
+
+
+def is_empty_dir(path: Path) -> bool:
+    try:
+        next(path.iterdir())
+        return False
+    except (StopIteration, PermissionError):
+        return True
+
+
+def _assert_permissions_in_directory(
+    directory: Path,
+    accessibility: Accessibility,
+    subdirs: dict[Path, Accessibility],
+) -> None:
+    accessibility.assert_on(directory)
+
+    for file in directory.iterdir():
+        if is_special_fs(file):
+            msg = f'Got unexpected special filesystem at {file}.'
+            assert subdirs.pop(file) == Accessibility.SPECIAL, msg
+        elif not file.is_symlink() and file.is_dir():
+            subdir_access = subdirs.pop(file, accessibility)
+            if is_empty_dir(file):
+                # Whenever we got an empty directory, we check the permission
+                # constraints on the current directory (except if specified
+                # explicitly in subdirs) because for example if we're non-root
+                # (the constraints of the current directory are thus
+                # Accessibility.READABLE), we really have to make sure that
+                # empty directories are *never* writable.
+                subdir_access.assert_on(file)
+            else:
+                _assert_permissions_in_directory(file, subdir_access, subdirs)
+        else:
+            subdirs.pop(file, accessibility).assert_on(file)
+
+
+def assert_permissions(subdirs: dict[str, Accessibility]) -> None:
+    """
+    Recursively check whether the file system conforms to the accessibility
+    specification we specified via 'subdirs'.
+    """
+    root = Path('/')
+    absolute_subdirs = {root / p: a for p, a in subdirs.items()}
+    _assert_permissions_in_directory(
+        root,
+        Accessibility.WRITABLE if os.getuid() == 0 else Accessibility.READABLE,
+        absolute_subdirs,
+    )
+    for file in absolute_subdirs.keys():
+        msg = f'Expected {file} to exist, but it was nowwhere to be found.'
+        raise AssertionError(msg)
diff --git a/nixos/tests/systemd-confinement/default.nix b/nixos/tests/systemd-confinement/default.nix
new file mode 100644
index 0000000000000..15d442d476b08
--- /dev/null
+++ b/nixos/tests/systemd-confinement/default.nix
@@ -0,0 +1,274 @@
+import ../make-test-python.nix {
+  name = "systemd-confinement";
+
+  nodes.machine = { pkgs, lib, ... }: let
+    testLib = pkgs.python3Packages.buildPythonPackage {
+      name = "confinement-testlib";
+      unpackPhase = ''
+        cat > setup.py <<EOF
+        from setuptools import setup
+        setup(name='confinement-testlib', py_modules=["checkperms"])
+        EOF
+        cp ${./checkperms.py} checkperms.py
+      '';
+    };
+
+    mkTest = name: testScript: pkgs.writers.writePython3 "${name}.py" {
+      libraries = [ pkgs.python3Packages.pytest testLib ];
+    } ''
+      # This runs our test script by using pytest's assertion rewriting, so
+      # that whenever we use "assert <something>", the actual values are
+      # printed rather than getting a generic AssertionError or the need to
+      # pass an explicit assertion error message.
+      import ast
+      from pathlib import Path
+      from _pytest.assertion.rewrite import rewrite_asserts
+
+      script = Path('${pkgs.writeText "${name}-main.py" ''
+        import errno, os, pytest, signal
+        from subprocess import run
+        from checkperms import Accessibility, assert_permissions
+
+        ${testScript}
+      ''}') # noqa
+      filename = str(script)
+      source = script.read_bytes()
+
+      tree = ast.parse(source, filename=filename)
+      rewrite_asserts(tree, source, filename)
+      exec(compile(tree, filename, 'exec', dont_inherit=True))
+    '';
+
+    mkTestStep = num: {
+      description,
+      testScript,
+      config ? {},
+      serviceName ? "test${toString num}",
+      rawUnit ? null,
+    }: {
+      systemd.packages = lib.optional (rawUnit != null) (pkgs.writeTextFile {
+        name = serviceName;
+        destination = "/etc/systemd/system/${serviceName}.service";
+        text = rawUnit;
+      });
+
+      systemd.services.${serviceName} = {
+        inherit description;
+        requiredBy = [ "multi-user.target" ];
+        confinement = (config.confinement or {}) // { enable = true; };
+        serviceConfig = (config.serviceConfig or {}) // {
+          ExecStart = mkTest serviceName testScript;
+          Type = "oneshot";
+        };
+      } // removeAttrs config [ "confinement" "serviceConfig" ];
+    };
+
+    parametrisedTests = lib.concatMap ({ user, privateTmp }: let
+      withTmp = if privateTmp then "with PrivateTmp" else "without PrivateTmp";
+
+      serviceConfig = if user == "static-user" then {
+        User = "chroot-testuser";
+        Group = "chroot-testgroup";
+      } else if user == "dynamic-user" then {
+        DynamicUser = true;
+      } else {};
+
+    in [
+      { description = "${user}, chroot-only confinement ${withTmp}";
+        config = {
+          confinement.mode = "chroot-only";
+          # Only set if privateTmp is true to ensure that the default is false.
+          serviceConfig = serviceConfig // lib.optionalAttrs privateTmp {
+            PrivateTmp = true;
+          };
+        };
+        testScript = if user == "root" then ''
+          assert os.getuid() == 0
+          assert os.getgid() == 0
+
+          assert_permissions({
+            'bin': Accessibility.READABLE,
+            'nix': Accessibility.READABLE,
+            'run': Accessibility.READABLE,
+            ${lib.optionalString privateTmp "'tmp': Accessibility.STICKY,"}
+            ${lib.optionalString privateTmp "'var': Accessibility.READABLE,"}
+            ${lib.optionalString privateTmp "'var/tmp': Accessibility.STICKY,"}
+          })
+        '' else ''
+          assert os.getuid() != 0
+          assert os.getgid() != 0
+
+          assert_permissions({
+            'bin': Accessibility.READABLE,
+            'nix': Accessibility.READABLE,
+            'run': Accessibility.READABLE,
+            ${lib.optionalString privateTmp "'tmp': Accessibility.STICKY,"}
+            ${lib.optionalString privateTmp "'var': Accessibility.READABLE,"}
+            ${lib.optionalString privateTmp "'var/tmp': Accessibility.STICKY,"}
+          })
+        '';
+      }
+      { description = "${user}, full APIVFS confinement ${withTmp}";
+        config = {
+          # Only set if privateTmp is false to ensure that the default is true.
+          serviceConfig = serviceConfig // lib.optionalAttrs (!privateTmp) {
+            PrivateTmp = false;
+          };
+        };
+        testScript = if user == "root" then ''
+          assert os.getuid() == 0
+          assert os.getgid() == 0
+
+          assert_permissions({
+            'bin': Accessibility.READABLE,
+            'nix': Accessibility.READABLE,
+            ${lib.optionalString privateTmp "'tmp': Accessibility.STICKY,"}
+            'run': Accessibility.WRITABLE,
+
+            'proc': Accessibility.SPECIAL,
+            'sys': Accessibility.SPECIAL,
+            'dev': Accessibility.WRITABLE,
+
+            ${lib.optionalString privateTmp "'var': Accessibility.READABLE,"}
+            ${lib.optionalString privateTmp "'var/tmp': Accessibility.STICKY,"}
+          })
+        '' else ''
+          assert os.getuid() != 0
+          assert os.getgid() != 0
+
+          assert_permissions({
+            'bin': Accessibility.READABLE,
+            'nix': Accessibility.READABLE,
+            ${lib.optionalString privateTmp "'tmp': Accessibility.STICKY,"}
+            'run': Accessibility.STICKY,
+
+            'proc': Accessibility.SPECIAL,
+            'sys': Accessibility.SPECIAL,
+            'dev': Accessibility.SPECIAL,
+            'dev/shm': Accessibility.STICKY,
+            'dev/mqueue': Accessibility.STICKY,
+
+            ${lib.optionalString privateTmp "'var': Accessibility.READABLE,"}
+            ${lib.optionalString privateTmp "'var/tmp': Accessibility.STICKY,"}
+          })
+        '';
+      }
+    ]) (lib.cartesianProductOfSets {
+      user = [ "root" "dynamic-user" "static-user" ];
+      privateTmp = [ true false ];
+    });
+
+  in {
+    imports = lib.imap1 mkTestStep (parametrisedTests ++ [
+      { description = "existence of bind-mounted /etc";
+        config.serviceConfig.BindReadOnlyPaths = [ "/etc" ];
+        testScript = ''
+          assert Path('/etc/passwd').read_text()
+        '';
+      }
+      (let
+        symlink = pkgs.runCommand "symlink" {
+          target = pkgs.writeText "symlink-target" "got me";
+        } "ln -s \"$target\" \"$out\"";
+      in {
+        description = "check if symlinks are properly bind-mounted";
+        config.confinement.packages = lib.singleton symlink;
+        testScript = ''
+          assert Path('${symlink}').read_text() == 'got me'
+        '';
+      })
+      { description = "check if StateDirectory works";
+        config.serviceConfig.User = "chroot-testuser";
+        config.serviceConfig.Group = "chroot-testgroup";
+        config.serviceConfig.StateDirectory = "testme";
+
+        # We restart on purpose here since we want to check whether the state
+        # directory actually persists.
+        config.serviceConfig.Restart = "on-failure";
+        config.serviceConfig.RestartMode = "direct";
+
+        testScript = ''
+          assert not Path('/tmp/canary').exists()
+          Path('/tmp/canary').touch()
+
+          if (foo := Path('/var/lib/testme/foo')).exists():
+            assert Path('/var/lib/testme/foo').read_text() == 'works'
+          else:
+            Path('/var/lib/testme/foo').write_text('works')
+            print('<4>Exiting with failure to check persistence on restart.')
+            raise SystemExit(1)
+        '';
+      }
+      { description = "check if /bin/sh works";
+        testScript = ''
+          assert Path('/bin/sh').exists()
+
+          result = run(
+            ['/bin/sh', '-c', 'echo -n bar'],
+            capture_output=True,
+            check=True,
+          )
+          assert result.stdout == b'bar'
+        '';
+      }
+      { description = "check if suppressing /bin/sh works";
+        config.confinement.binSh = null;
+        testScript = ''
+          assert not Path('/bin/sh').exists()
+          with pytest.raises(FileNotFoundError):
+            run(['/bin/sh', '-c', 'echo foo'])
+        '';
+      }
+      { description = "check if we can set /bin/sh to something different";
+        config.confinement.binSh = "${pkgs.hello}/bin/hello";
+        testScript = ''
+          assert Path('/bin/sh').exists()
+          result = run(
+            ['/bin/sh', '-g', 'foo'],
+            capture_output=True,
+            check=True,
+          )
+          assert result.stdout == b'foo\n'
+        '';
+      }
+      { description = "check if only Exec* dependencies are included";
+        config.environment.FOOBAR = pkgs.writeText "foobar" "eek";
+        testScript = ''
+          with pytest.raises(FileNotFoundError):
+            Path(os.environ['FOOBAR']).read_text()
+        '';
+      }
+      { description = "check if fullUnit includes all dependencies";
+        config.environment.FOOBAR = pkgs.writeText "foobar" "eek";
+        config.confinement.fullUnit = true;
+        testScript = ''
+          assert Path(os.environ['FOOBAR']).read_text() == 'eek'
+        '';
+      }
+      { description = "check if shipped unit file still works";
+        config.confinement.mode = "chroot-only";
+        rawUnit = ''
+          [Service]
+          SystemCallFilter=~kill
+          SystemCallErrorNumber=ELOOP
+        '';
+        testScript = ''
+          with pytest.raises(OSError) as excinfo:
+            os.kill(os.getpid(), signal.SIGKILL)
+          assert excinfo.value.errno == errno.ELOOP
+        '';
+      }
+    ]);
+
+    config.users.groups.chroot-testgroup = {};
+    config.users.users.chroot-testuser = {
+      isSystemUser = true;
+      description = "Chroot Test User";
+      group = "chroot-testgroup";
+    };
+  };
+
+  testScript = ''
+    machine.wait_for_unit("multi-user.target")
+  '';
+}
diff --git a/nixos/tests/systemd-initrd-luks-fido2.nix b/nixos/tests/systemd-initrd-luks-fido2.nix
index f9f75ab7f301c..207f51f4dd9b4 100644
--- a/nixos/tests/systemd-initrd-luks-fido2.nix
+++ b/nixos/tests/systemd-initrd-luks-fido2.nix
@@ -9,7 +9,6 @@ import ./make-test-python.nix ({ lib, pkgs, ... }: {
       # Booting off the encrypted disk requires having a Nix store available for the init script
       mountHostNixStore = true;
       useEFIBoot = true;
-      qemu.package = lib.mkForce (pkgs.qemu_test.override { canokeySupport = true; });
       qemu.options = [ "-device canokey,file=/tmp/canokey-file" ];
     };
     boot.loader.systemd-boot.enable = true;
diff --git a/nixos/tests/systemd-initrd-modprobe.nix b/nixos/tests/systemd-initrd-modprobe.nix
index 0f93492176b44..e563552a645fd 100644
--- a/nixos/tests/systemd-initrd-modprobe.nix
+++ b/nixos/tests/systemd-initrd-modprobe.nix
@@ -4,21 +4,21 @@ import ./make-test-python.nix ({ lib, pkgs, ... }: {
   nodes.machine = { pkgs, ... }: {
     testing.initrdBackdoor = true;
     boot.initrd.systemd.enable = true;
-    boot.initrd.kernelModules = [ "loop" ]; # Load module in initrd.
+    boot.initrd.kernelModules = [ "tcp_hybla" ]; # Load module in initrd.
     boot.extraModprobeConfig = ''
-      options loop max_loop=42
+      options tcp_hybla rtt0=42
     '';
   };
 
   testScript = ''
     machine.wait_for_unit("initrd.target")
-    max_loop = machine.succeed("cat /sys/module/loop/parameters/max_loop")
-    assert int(max_loop) == 42, "Parameter should be respected for initrd kernel modules"
+    rtt = machine.succeed("cat /sys/module/tcp_hybla/parameters/rtt0")
+    assert int(rtt) == 42, "Parameter should be respected for initrd kernel modules"
 
     # Make sure it sticks in stage 2
     machine.switch_root()
     machine.wait_for_unit("multi-user.target")
-    max_loop = machine.succeed("cat /sys/module/loop/parameters/max_loop")
-    assert int(max_loop) == 42, "Parameter should be respected for initrd kernel modules"
+    rtt = machine.succeed("cat /sys/module/tcp_hybla/parameters/rtt0")
+    assert int(rtt) == 42, "Parameter should be respected for initrd kernel modules"
   '';
 })
diff --git a/nixos/tests/systemd-resolved.nix b/nixos/tests/systemd-resolved.nix
new file mode 100644
index 0000000000000..3eedc17f4b34f
--- /dev/null
+++ b/nixos/tests/systemd-resolved.nix
@@ -0,0 +1,75 @@
+import ./make-test-python.nix ({ pkgs, lib, ... }: {
+  name = "systemd-resolved";
+  meta.maintainers = [ lib.maintainers.elvishjerricco ];
+
+  nodes.server = { lib, config, ... }: let
+    exampleZone = pkgs.writeTextDir "example.com.zone" ''
+      @ SOA ns.example.com. noc.example.com. 2019031301 86400 7200 3600000 172800
+      @       A       ${(lib.head config.networking.interfaces.eth1.ipv4.addresses).address}
+      @       AAAA    ${(lib.head config.networking.interfaces.eth1.ipv6.addresses).address}
+    '';
+  in {
+    networking.firewall.enable = false;
+    networking.useDHCP = false;
+
+    networking.interfaces.eth1.ipv6.addresses = lib.mkForce [
+      { address = "fd00::1"; prefixLength = 64; }
+    ];
+
+    services.knot = {
+      enable = true;
+      settings = {
+        server.listen = [
+          "0.0.0.0@53"
+          "::@53"
+        ];
+        template.default.storage = exampleZone;
+        zone."example.com".file = "example.com.zone";
+      };
+    };
+  };
+
+  nodes.client = { nodes, ... }: let
+    inherit (lib.head nodes.server.networking.interfaces.eth1.ipv4.addresses) address;
+  in {
+    networking.nameservers = [ address ];
+    networking.interfaces.eth1.ipv6.addresses = lib.mkForce [
+      { address = "fd00::2"; prefixLength = 64; }
+    ];
+    services.resolved.enable = true;
+    services.resolved.fallbackDns = [ ];
+    networking.useNetworkd = true;
+    networking.useDHCP = false;
+    systemd.network.networks."40-eth0".enable = false;
+
+    testing.initrdBackdoor = true;
+    boot.initrd = {
+      systemd.enable = true;
+      systemd.initrdBin = [ pkgs.iputils ];
+      network.enable = true;
+      services.resolved.enable = true;
+    };
+  };
+
+  testScript = { nodes, ... }: let
+    address4 = (lib.head nodes.server.networking.interfaces.eth1.ipv4.addresses).address;
+    address6 = (lib.head nodes.server.networking.interfaces.eth1.ipv6.addresses).address;
+  in ''
+    start_all()
+    server.wait_for_unit("multi-user.target")
+
+    def test_client():
+        query = client.succeed("resolvectl query example.com")
+        assert "${address4}" in query
+        assert "${address6}" in query
+        client.succeed("ping -4 -c 1 example.com")
+        client.succeed("ping -6 -c 1 example.com")
+
+    client.wait_for_unit("initrd.target")
+    test_client()
+    client.switch_root()
+
+    client.wait_for_unit("multi-user.target")
+    test_client()
+  '';
+})
diff --git a/nixos/tests/tayga.nix b/nixos/tests/tayga.nix
index 4aade67d74d0d..204391d1312f2 100644
--- a/nixos/tests/tayga.nix
+++ b/nixos/tests/tayga.nix
@@ -59,6 +59,7 @@ import ./make-test-python.nix ({ pkgs, lib, ... }:
           ];
         };
       };
+      programs.mtr.enable = true;
     };
 
     # The router is configured with static IPv4 addresses towards the server
@@ -120,6 +121,9 @@ import ./make-test-python.nix ({ pkgs, lib, ... }:
             prefixLength = 96;
           };
         };
+        mappings = {
+          "192.0.2.42" = "2001:db8::2";
+        };
       };
     };
 
@@ -171,6 +175,9 @@ import ./make-test-python.nix ({ pkgs, lib, ... }:
             prefixLength = 96;
           };
         };
+        mappings = {
+          "192.0.2.42" = "2001:db8::2";
+        };
       };
     };
 
@@ -199,7 +206,7 @@ import ./make-test-python.nix ({ pkgs, lib, ... }:
           ];
         };
       };
-      environment.systemPackages = [ pkgs.mtr ];
+      programs.mtr.enable = true;
     };
   };
 
@@ -225,10 +232,16 @@ import ./make-test-python.nix ({ pkgs, lib, ... }:
       with subtest("Wait for tayga"):
         router.wait_for_unit("tayga.service")
 
-      with subtest("Test ICMP"):
+      with subtest("Test ICMP server -> client"):
+        server.wait_until_succeeds("ping -c 3 192.0.2.42 >&2")
+
+      with subtest("Test ICMP and show a traceroute server -> client"):
+        server.wait_until_succeeds("mtr --show-ips --report-wide 192.0.2.42 >&2")
+
+      with subtest("Test ICMP client -> server"):
         client.wait_until_succeeds("ping -c 3 64:ff9b::100.64.0.2 >&2")
 
-      with subtest("Test ICMP and show a traceroute"):
+      with subtest("Test ICMP and show a traceroute client -> server"):
         client.wait_until_succeeds("mtr --show-ips --report-wide 64:ff9b::100.64.0.2 >&2")
 
       router.log(router.execute("systemd-analyze security tayga.service")[1])
diff --git a/nixos/tests/tigervnc.nix b/nixos/tests/tigervnc.nix
index ed575682d9338..b80cb49519c45 100644
--- a/nixos/tests/tigervnc.nix
+++ b/nixos/tests/tigervnc.nix
@@ -38,16 +38,18 @@ makeTest {
     server.succeed("Xvnc -geometry 720x576 :1 -PasswordFile vncpasswd >&2 &")
     server.wait_until_succeeds("nc -z localhost 5901", timeout=10)
     server.succeed("DISPLAY=:1 xwininfo -root | grep 720x576")
-    server.execute("DISPLAY=:1 display -size 360x200 -font sans -gravity south label:'HELLO VNC WORLD' >&2 &")
+    server.execute("DISPLAY=:1 display -size 360x200 -font sans -gravity south label:'HELLO VNC' >&2 &")
 
     client.wait_for_x()
     client.execute("vncviewer server:1 -PasswordFile vncpasswd >&2 &")
     client.wait_for_window(r"VNC")
     client.screenshot("screenshot")
     text = client.get_screen_text()
+
     # Displayed text
-    assert 'HELLO VNC WORLD' in text
+    assert 'HELLO VNC' in text
     # Client window title
-    assert 'TigerVNC' in text
+    # get_screen_text can't get correct string from screenshot
+    # assert 'TigerVNC' in text
   '';
 }
diff --git a/nixos/tests/udisks2.nix b/nixos/tests/udisks2.nix
index 8cc148750c7bc..b934f0b951562 100644
--- a/nixos/tests/udisks2.nix
+++ b/nixos/tests/udisks2.nix
@@ -2,6 +2,7 @@ import ./make-test-python.nix ({ pkgs, ... }:
 
 let
 
+  # FIXME: 404s
   stick = pkgs.fetchurl {
     url = "https://nixos.org/~eelco/nix/udisks-test.img.xz";
     sha256 = "0was1xgjkjad91nipzclaz5biv3m4b2nk029ga6nk7iklwi19l8b";
@@ -12,7 +13,7 @@ in
 {
   name = "udisks2";
   meta = with pkgs.lib.maintainers; {
-    maintainers = [ eelco ];
+    maintainers = [ ];
   };
 
   nodes.machine =
diff --git a/nixos/tests/vector.nix b/nixos/tests/vector.nix
deleted file mode 100644
index a55eb4e012c5b..0000000000000
--- a/nixos/tests/vector.nix
+++ /dev/null
@@ -1,37 +0,0 @@
-{ system ? builtins.currentSystem, config ? { }
-, pkgs ? import ../.. { inherit system config; } }:
-
-with import ../lib/testing-python.nix { inherit system pkgs; };
-with pkgs.lib;
-
-{
-  test1 = makeTest {
-    name = "vector-test1";
-    meta.maintainers = [ pkgs.lib.maintainers.happysalada ];
-
-    nodes.machine = { config, pkgs, ... }: {
-      services.vector = {
-        enable = true;
-        journaldAccess = true;
-        settings = {
-          sources.journald.type = "journald";
-
-          sinks = {
-            file = {
-              type = "file";
-              inputs = [ "journald" ];
-              path = "/var/lib/vector/logs.log";
-              encoding = { codec = "json"; };
-            };
-          };
-        };
-      };
-    };
-
-    # ensure vector is forwarding the messages appropriately
-    testScript = ''
-      machine.wait_for_unit("vector.service")
-      machine.wait_for_file("/var/lib/vector/logs.log")
-    '';
-  };
-}
diff --git a/nixos/tests/vector/api.nix b/nixos/tests/vector/api.nix
new file mode 100644
index 0000000000000..8aa3a0c1b771f
--- /dev/null
+++ b/nixos/tests/vector/api.nix
@@ -0,0 +1,39 @@
+import ../make-test-python.nix ({ lib, pkgs, ... }:
+
+{
+  name = "vector-api";
+  meta.maintainers = [ pkgs.lib.maintainers.happysalada ];
+
+  nodes.machineapi = { config, pkgs, ... }: {
+    services.vector = {
+      enable = true;
+      journaldAccess = false;
+      settings = {
+        api.enabled = true;
+
+        sources = {
+          demo_logs = {
+            type = "demo_logs";
+            format = "json";
+          };
+        };
+
+        sinks = {
+          file = {
+            type = "file";
+            inputs = [ "demo_logs" ];
+            path = "/var/lib/vector/logs.log";
+            encoding = { codec = "json"; };
+          };
+        };
+      };
+    };
+  };
+
+  testScript = ''
+    machineapi.wait_for_unit("vector")
+    machineapi.wait_for_open_port(8686)
+    machineapi.succeed("journalctl -o cat -u vector.service | grep 'API server running'")
+    machineapi.wait_until_succeeds("curl -sSf http://localhost:8686/health")
+  '';
+})
diff --git a/nixos/tests/vector/default.nix b/nixos/tests/vector/default.nix
new file mode 100644
index 0000000000000..990b067e81774
--- /dev/null
+++ b/nixos/tests/vector/default.nix
@@ -0,0 +1,11 @@
+{ system ? builtins.currentSystem
+, config ? { }
+, pkgs ? import ../../.. { inherit system config; }
+}:
+
+{
+  file-sink = import ./file-sink.nix { inherit system pkgs; };
+  api = import ./api.nix { inherit system pkgs; };
+  dnstap = import ./dnstap.nix { inherit system pkgs; };
+  nginx-clickhouse = import ./nginx-clickhouse.nix { inherit system pkgs; };
+}
diff --git a/nixos/tests/vector/dnstap.nix b/nixos/tests/vector/dnstap.nix
new file mode 100644
index 0000000000000..15d643311b604
--- /dev/null
+++ b/nixos/tests/vector/dnstap.nix
@@ -0,0 +1,118 @@
+import ../make-test-python.nix ({ lib, pkgs, ... }:
+
+let
+  dnstapSocket = "/var/run/vector/dnstap.sock";
+in
+{
+  name = "vector-dnstap";
+  meta.maintainers = [ pkgs.lib.maintainers.happysalada ];
+
+  nodes = {
+    unbound = { config, pkgs, ... }: {
+      networking.firewall.allowedUDPPorts = [ 53 ];
+
+      services.vector = {
+        enable = true;
+
+        settings = {
+          sources = {
+            dnstap = {
+              type = "dnstap";
+              multithreaded = true;
+              mode = "unix";
+              lowercase_hostnames = true;
+              socket_file_mode = 504;
+              socket_path = "${dnstapSocket}";
+            };
+          };
+
+          sinks = {
+            file = {
+              type = "file";
+              inputs = [ "dnstap" ];
+              path = "/var/lib/vector/logs.log";
+              encoding = { codec = "json"; };
+            };
+          };
+        };
+      };
+
+      systemd.services.vector.serviceConfig = {
+        RuntimeDirectory = "vector";
+        RuntimeDirectoryMode = "0770";
+      };
+
+      services.unbound = {
+        enable = true;
+        enableRootTrustAnchor = false;
+        package = pkgs.unbound-full;
+        settings = {
+          server = {
+            interface = [ "0.0.0.0" "::" ];
+            access-control = [ "192.168.1.0/24 allow" ];
+
+            domain-insecure = "local";
+            private-domain = "local";
+
+            local-zone = "local. static";
+            local-data = [
+              ''"test.local. 10800 IN A 192.168.123.5"''
+            ];
+          };
+
+          dnstap = {
+            dnstap-enable = "yes";
+            dnstap-socket-path = "${dnstapSocket}";
+            dnstap-send-identity = "yes";
+            dnstap-send-version = "yes";
+            dnstap-log-client-query-messages = "yes";
+            dnstap-log-client-response-messages = "yes";
+          };
+        };
+      };
+
+      systemd.services.unbound = {
+        after = [ "vector.service" ];
+        wants = [ "vector.service" ];
+        serviceConfig = {
+          # DNSTAP access
+          ReadWritePaths = [ "/var/run/vector" ];
+          SupplementaryGroups = [ "vector" ];
+        };
+      };
+    };
+
+    dnsclient = { config, pkgs, ... }: {
+      environment.systemPackages = [ pkgs.dig ];
+    };
+  };
+
+  testScript = ''
+    unbound.wait_for_unit("unbound")
+    unbound.wait_for_unit("vector")
+
+    unbound.wait_until_succeeds(
+      "journalctl -o cat -u vector.service | grep 'Socket permissions updated to 0o770'"
+    )
+    unbound.wait_until_succeeds(
+      "journalctl -o cat -u vector.service | grep 'component_type=dnstap' | grep 'Listening... path=\"${dnstapSocket}\"'"
+    )
+
+    unbound.wait_for_file("${dnstapSocket}")
+    unbound.succeed("test 770 -eq $(stat -c '%a' ${dnstapSocket})")
+
+    dnsclient.wait_for_unit("network-online.target")
+    dnsclient.succeed(
+      "dig @unbound test.local"
+    )
+
+    unbound.wait_for_file("/var/lib/vector/logs.log")
+
+    unbound.wait_until_succeeds(
+      "grep ClientQuery /var/lib/vector/logs.log | grep '\"domainName\":\"test.local.\"' | grep '\"rcodeName\":\"NoError\"'"
+    )
+    unbound.wait_until_succeeds(
+      "grep ClientResponse /var/lib/vector/logs.log | grep '\"domainName\":\"test.local.\"' | grep '\"rData\":\"192.168.123.5\"'"
+    )
+  '';
+})
diff --git a/nixos/tests/vector/file-sink.nix b/nixos/tests/vector/file-sink.nix
new file mode 100644
index 0000000000000..2220d20ac55c3
--- /dev/null
+++ b/nixos/tests/vector/file-sink.nix
@@ -0,0 +1,49 @@
+import ../make-test-python.nix ({ lib, pkgs, ... }:
+
+{
+  name = "vector-test1";
+  meta.maintainers = [ pkgs.lib.maintainers.happysalada ];
+
+  nodes.machine = { config, pkgs, ... }: {
+    services.vector = {
+      enable = true;
+      journaldAccess = true;
+      settings = {
+        sources = {
+          journald.type = "journald";
+
+          vector_metrics.type = "internal_metrics";
+
+          vector_logs.type = "internal_logs";
+        };
+
+        sinks = {
+          file = {
+            type = "file";
+            inputs = [ "journald" "vector_logs" ];
+            path = "/var/lib/vector/logs.log";
+            encoding = { codec = "json"; };
+          };
+
+          prometheus_exporter = {
+            type = "prometheus_exporter";
+            inputs = [ "vector_metrics" ];
+            address = "[::]:9598";
+          };
+        };
+      };
+    };
+  };
+
+  # ensure vector is forwarding the messages appropriately
+  testScript = ''
+    machine.wait_for_unit("vector.service")
+    machine.wait_for_open_port(9598)
+    machine.wait_until_succeeds("journalctl -o cat -u vector.service | grep 'version=\"${pkgs.vector.version}\"'")
+    machine.wait_until_succeeds("journalctl -o cat -u vector.service | grep 'API is disabled'")
+    machine.wait_until_succeeds("curl -sSf http://localhost:9598/metrics | grep vector_build_info")
+    machine.wait_until_succeeds("curl -sSf http://localhost:9598/metrics | grep vector_component_received_bytes_total | grep journald")
+    machine.wait_until_succeeds("curl -sSf http://localhost:9598/metrics | grep vector_utilization | grep prometheus_exporter")
+    machine.wait_for_file("/var/lib/vector/logs.log")
+  '';
+})
diff --git a/nixos/tests/vector/nginx-clickhouse.nix b/nixos/tests/vector/nginx-clickhouse.nix
new file mode 100644
index 0000000000000..3d99bac6ac161
--- /dev/null
+++ b/nixos/tests/vector/nginx-clickhouse.nix
@@ -0,0 +1,168 @@
+import ../make-test-python.nix ({ lib, pkgs, ... }:
+
+{
+  name = "vector-nginx-clickhouse";
+  meta.maintainers = [ pkgs.lib.maintainers.happysalada ];
+
+  nodes = {
+    clickhouse = { config, pkgs, ... }: {
+      virtualisation.memorySize = 4096;
+
+      # Clickhouse module can't listen on a non-loopback IP.
+      networking.firewall.allowedTCPPorts = [ 6000 ];
+      services.clickhouse.enable = true;
+
+      # Exercise Vector sink->source for now.
+      services.vector = {
+        enable = true;
+
+        settings = {
+          sources = {
+            vector_source = {
+              type = "vector";
+              address = "[::]:6000";
+            };
+          };
+
+          sinks = {
+            clickhouse = {
+              type = "clickhouse";
+              inputs = [ "vector_source" ];
+              endpoint = "http://localhost:8123";
+              database = "nginxdb";
+              table = "access_logs";
+              skip_unknown_fields = true;
+            };
+          };
+        };
+      };
+    };
+
+    nginx = { config, pkgs, ... }: {
+      services.nginx = {
+        enable = true;
+        virtualHosts.localhost = {};
+      };
+
+      services.vector = {
+        enable = true;
+
+        settings = {
+          sources = {
+            nginx_logs = {
+              type = "file";
+              include = [ "/var/log/nginx/access.log" ];
+              read_from = "end";
+            };
+          };
+
+          sinks = {
+            vector_sink = {
+              type = "vector";
+              inputs = [ "nginx_logs" ];
+              address = "clickhouse:6000";
+            };
+          };
+        };
+      };
+
+      systemd.services.vector.serviceConfig = {
+        SupplementaryGroups = [ "nginx" ];
+      };
+    };
+  };
+
+  testScript =
+  let
+    # work around quote/substitution complexity by Nix, Perl, bash and SQL.
+    databaseDDL = pkgs.writeText "database.sql" "CREATE DATABASE IF NOT EXISTS nginxdb";
+
+    tableDDL = pkgs.writeText "table.sql" ''
+      CREATE TABLE IF NOT EXISTS  nginxdb.access_logs (
+        message String
+      )
+      ENGINE = MergeTree()
+      ORDER BY tuple()
+    '';
+
+    # Graciously taken from https://clickhouse.com/docs/en/integrations/vector
+    tableView = pkgs.writeText "table-view.sql" ''
+      CREATE MATERIALIZED VIEW nginxdb.access_logs_view
+      (
+        RemoteAddr String,
+        Client String,
+        RemoteUser String,
+        TimeLocal DateTime,
+        RequestMethod String,
+        Request String,
+        HttpVersion String,
+        Status Int32,
+        BytesSent Int64,
+        UserAgent String
+      )
+      ENGINE = MergeTree()
+      ORDER BY RemoteAddr
+      POPULATE AS
+      WITH
+       splitByWhitespace(message) as split,
+       splitByRegexp('\S \d+ "([^"]*)"', message) as referer
+      SELECT
+        split[1] AS RemoteAddr,
+        split[2] AS Client,
+        split[3] AS RemoteUser,
+        parseDateTimeBestEffort(replaceOne(trim(LEADING '[' FROM split[4]), ':', ' ')) AS TimeLocal,
+        trim(LEADING '"' FROM split[6]) AS RequestMethod,
+        split[7] AS Request,
+        trim(TRAILING '"' FROM split[8]) AS HttpVersion,
+        split[9] AS Status,
+        split[10] AS BytesSent,
+        trim(BOTH '"' from referer[2]) AS UserAgent
+      FROM
+        (SELECT message FROM nginxdb.access_logs)
+    '';
+
+    selectQuery = pkgs.writeText "select.sql" "SELECT * from nginxdb.access_logs_view";
+  in
+  ''
+    clickhouse.wait_for_unit("clickhouse")
+    clickhouse.wait_for_open_port(8123)
+
+    clickhouse.wait_until_succeeds(
+      "journalctl -o cat -u clickhouse.service | grep 'Started ClickHouse server'"
+    )
+
+    clickhouse.wait_for_unit("vector")
+    clickhouse.wait_for_open_port(6000)
+
+    clickhouse.succeed(
+      "cat ${databaseDDL} | clickhouse-client"
+    )
+
+    clickhouse.succeed(
+      "cat ${tableDDL} | clickhouse-client"
+    )
+
+    clickhouse.succeed(
+      "cat ${tableView} | clickhouse-client"
+    )
+
+    nginx.wait_for_unit("nginx")
+    nginx.wait_for_open_port(80)
+    nginx.wait_for_unit("vector")
+    nginx.wait_until_succeeds(
+      "journalctl -o cat -u vector.service | grep 'Starting file server'"
+    )
+
+    nginx.succeed("curl http://localhost/")
+    nginx.succeed("curl http://localhost/")
+
+    nginx.wait_for_file("/var/log/nginx/access.log")
+    nginx.wait_until_succeeds(
+      "journalctl -o cat -u vector.service | grep 'Found new file to watch. file=/var/log/nginx/access.log'"
+    )
+
+    clickhouse.wait_until_succeeds(
+      "cat ${selectQuery} | clickhouse-client | grep 'curl'"
+    )
+  '';
+})
diff --git a/nixos/tests/virtualbox.nix b/nixos/tests/virtualbox.nix
index 3c2a391233dbd..5fce3ba548123 100644
--- a/nixos/tests/virtualbox.nix
+++ b/nixos/tests/virtualbox.nix
@@ -98,7 +98,6 @@ let
     cfg = (import ../lib/eval-config.nix {
       system = if use64bitGuest then "x86_64-linux" else "i686-linux";
       modules = [
-        ../modules/profiles/minimal.nix
         (testVMConfig vmName vmScript)
       ];
     }).config;
diff --git a/nixos/tests/web-apps/nextjs-ollama-llm-ui.nix b/nixos/tests/web-apps/nextjs-ollama-llm-ui.nix
new file mode 100644
index 0000000000000..3bb9d1e62aefe
--- /dev/null
+++ b/nixos/tests/web-apps/nextjs-ollama-llm-ui.nix
@@ -0,0 +1,22 @@
+{ lib, ... }:
+
+{
+  name = "nextjs-ollama-llm-ui";
+  meta.maintainers = with lib.maintainers; [ malteneuss ];
+
+  nodes.machine =
+    { pkgs, ... }:
+    {
+      services.nextjs-ollama-llm-ui = {
+        enable = true;
+        port = 8080;
+      };
+    };
+
+  testScript = ''
+    # Ensure the service is started and reachable
+    machine.wait_for_unit("nextjs-ollama-llm-ui.service")
+    machine.wait_for_open_port(8080)
+    machine.succeed("curl --fail http://127.0.0.1:8080")
+  '';
+}
diff --git a/nixos/tests/web-apps/pretalx.nix b/nixos/tests/web-apps/pretalx.nix
index a226639b076b4..cbb6580aa0515 100644
--- a/nixos/tests/web-apps/pretalx.nix
+++ b/nixos/tests/web-apps/pretalx.nix
@@ -5,13 +5,16 @@
   meta.maintainers = lib.teams.c3d2.members;
 
   nodes = {
-    pretalx = {
+    pretalx = { config, ... }: {
       networking.extraHosts = ''
         127.0.0.1 talks.local
       '';
 
       services.pretalx = {
         enable = true;
+        plugins = with config.services.pretalx.package.plugins; [
+          pages
+        ];
         nginx.domain = "talks.local";
         settings = {
           site.url = "http://talks.local";
@@ -27,5 +30,9 @@
     pretalx.wait_for_unit("pretalx-worker.service")
 
     pretalx.wait_until_succeeds("curl -q --fail http://talks.local/orga/")
+
+    pretalx.succeed("pretalx-manage --help")
+
+    pretalx.log(pretalx.succeed("systemd-analyze security pretalx-web.service"))
   '';
 }
diff --git a/nixos/tests/ydotool.nix b/nixos/tests/ydotool.nix
new file mode 100644
index 0000000000000..818ac6f2d50de
--- /dev/null
+++ b/nixos/tests/ydotool.nix
@@ -0,0 +1,115 @@
+import ./make-test-python.nix (
+  { pkgs, lib, ... }:
+  let
+    textInput = "This works.";
+    inputBoxText = "Enter input";
+    inputBox = pkgs.writeShellScript "zenity-input" ''
+      ${lib.getExe pkgs.gnome.zenity} --entry --text '${inputBoxText}:' > /tmp/output &
+    '';
+  in
+  {
+    name = "ydotool";
+
+    meta = {
+      maintainers = with lib.maintainers; [
+        OPNA2608
+        quantenzitrone
+      ];
+    };
+
+    nodes = {
+      headless =
+        { config, ... }:
+        {
+          imports = [ ./common/user-account.nix ];
+
+          users.users.alice.extraGroups = [ "ydotool" ];
+
+          programs.ydotool.enable = true;
+
+          services.getty.autologinUser = "alice";
+        };
+
+      x11 =
+        { config, ... }:
+        {
+          imports = [
+            ./common/user-account.nix
+            ./common/auto.nix
+            ./common/x11.nix
+          ];
+
+          users.users.alice.extraGroups = [ "ydotool" ];
+
+          programs.ydotool.enable = true;
+
+          test-support.displayManager.auto = {
+            enable = true;
+            user = "alice";
+          };
+
+          services.xserver.windowManager.dwm.enable = true;
+          services.displayManager.defaultSession = lib.mkForce "none+dwm";
+        };
+
+      wayland =
+        { config, ... }:
+        {
+          imports = [ ./common/user-account.nix ];
+
+          services.cage = {
+            enable = true;
+            user = "alice";
+          };
+
+          programs.ydotool.enable = true;
+
+          services.cage.program = inputBox;
+        };
+    };
+
+    enableOCR = true;
+
+    testScript =
+      { nodes, ... }:
+      ''
+        def as_user(cmd: str):
+          """
+          Return a shell command for running a shell command as a specific user.
+          """
+          return f"sudo -u alice -i {cmd}"
+
+        start_all()
+
+        # Headless
+        headless.wait_for_unit("multi-user.target")
+        headless.wait_for_text("alice")
+        headless.succeed(as_user("ydotool type 'echo ${textInput} > /tmp/output'")) # text input
+        headless.succeed(as_user("ydotool key 28:1 28:0")) # text input
+        headless.screenshot("headless_input")
+        headless.wait_for_file("/tmp/output")
+        headless.wait_until_succeeds("grep '${textInput}' /tmp/output") # text input
+
+        # X11
+        x11.wait_for_x()
+        x11.execute(as_user("${inputBox}"))
+        x11.wait_for_text("${inputBoxText}")
+        x11.succeed(as_user("ydotool type '${textInput}'")) # text input
+        x11.screenshot("x11_input")
+        x11.succeed(as_user("ydotool mousemove -a 400 110")) # mouse input
+        x11.succeed(as_user("ydotool click 0xC0")) # mouse input
+        x11.wait_for_file("/tmp/output")
+        x11.wait_until_succeeds("grep '${textInput}' /tmp/output") # text input
+
+        # Wayland
+        wayland.wait_for_unit("graphical.target")
+        wayland.wait_for_text("${inputBoxText}")
+        wayland.succeed("ydotool type '${textInput}'") # text input
+        wayland.screenshot("wayland_input")
+        wayland.succeed("ydotool mousemove -a 100 100") # mouse input
+        wayland.succeed("ydotool click 0xC0") # mouse input
+        wayland.wait_for_file("/tmp/output")
+        wayland.wait_until_succeeds("grep '${textInput}' /tmp/output") # text input
+      '';
+  }
+)
diff --git a/nixos/tests/your_spotify.nix b/nixos/tests/your_spotify.nix
new file mode 100644
index 0000000000000..a1fa0e459a8e1
--- /dev/null
+++ b/nixos/tests/your_spotify.nix
@@ -0,0 +1,33 @@
+import ./make-test-python.nix ({pkgs, ...}: {
+  name = "your_spotify";
+  meta = with pkgs.lib.maintainers; {
+    maintainers = [patrickdag];
+  };
+
+  nodes.machine = {
+    services.your_spotify = {
+      enable = true;
+      spotifySecretFile = pkgs.writeText "spotifySecretFile" "deadbeef";
+      settings = {
+        CLIENT_ENDPOINT = "http://localhost";
+        API_ENDPOINT = "http://localhost:3000";
+        SPOTIFY_PUBLIC = "beefdead";
+      };
+      enableLocalDB = true;
+      nginxVirtualHost = "localhost";
+    };
+  };
+
+  testScript = ''
+    machine.wait_for_unit("your_spotify.service")
+
+    machine.wait_for_open_port(3000)
+    machine.wait_for_open_port(80)
+
+    out = machine.succeed("curl --fail -X GET 'http://localhost:3000/'")
+    assert "Hello !" in out
+
+    out = machine.succeed("curl --fail -X GET 'http://localhost:80/'")
+    assert "<title>Your Spotify</title>" in out
+  '';
+})