about summary refs log tree commit diff
path: root/nixos/modules
diff options
context:
space:
mode:
Diffstat (limited to 'nixos/modules')
-rw-r--r--nixos/modules/config/fonts/ghostscript.nix2
-rw-r--r--nixos/modules/config/no-x-libs.nix9
-rw-r--r--nixos/modules/config/nsswitch.nix26
-rw-r--r--nixos/modules/config/swap.nix10
-rw-r--r--nixos/modules/config/terminfo.nix2
-rw-r--r--nixos/modules/config/xdg/portal.nix2
-rw-r--r--nixos/modules/config/xdg/terminal-exec.nix54
-rw-r--r--nixos/modules/hardware/graphics.nix126
-rw-r--r--nixos/modules/hardware/opengl.nix161
-rw-r--r--nixos/modules/hardware/openrazer.nix21
-rw-r--r--nixos/modules/hardware/printers.nix2
-rw-r--r--nixos/modules/hardware/video/amdgpu-pro.nix69
-rw-r--r--nixos/modules/hardware/video/intel-gpu-tools.nix25
-rw-r--r--nixos/modules/hardware/video/nvidia.nix882
-rw-r--r--nixos/modules/hardware/video/virtualbox.nix7
-rw-r--r--nixos/modules/hardware/xone.nix2
-rw-r--r--nixos/modules/image/repart-image.nix4
-rw-r--r--nixos/modules/installer/cd-dvd/installation-cd-graphical-calamares-plasma5.nix4
-rw-r--r--nixos/modules/installer/cd-dvd/installation-cd-graphical-plasma5.nix4
-rw-r--r--nixos/modules/installer/netboot/netboot.nix4
-rw-r--r--nixos/modules/installer/tools/nix-fallback-paths.nix10
-rw-r--r--nixos/modules/misc/locate.nix154
-rw-r--r--nixos/modules/misc/version.nix4
-rw-r--r--nixos/modules/module-list.nix39
-rw-r--r--nixos/modules/profiles/perlless.nix2
-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.nix18
-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/coolercontrol.nix8
-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.nix86
-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/fzf.nix2
-rw-r--r--nixos/modules/programs/gamemode.nix20
-rw-r--r--nixos/modules/programs/gamescope.nix36
-rw-r--r--nixos/modules/programs/gdk-pixbuf.nix (renamed from nixos/modules/services/x11/gdk-pixbuf.nix)12
-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/kubeswitch.nix18
-rw-r--r--nixos/modules/programs/ladybird.nix14
-rw-r--r--nixos/modules/programs/less.nix68
-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/miriway.nix2
-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.nix276
-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.nix118
-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/thunderbird.nix89
-rw-r--r--nixos/modules/programs/traceroute.nix8
-rw-r--r--nixos/modules/programs/turbovnc.nix12
-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.nix132
-rw-r--r--nixos/modules/programs/wayland/hyprlock.nix25
-rw-r--r--nixos/modules/programs/wayland/lib.nix12
-rw-r--r--nixos/modules/programs/wayland/river.nix72
-rw-r--r--nixos/modules/programs/wayland/sway.nix198
-rw-r--r--nixos/modules/programs/wayland/waybar.nix10
-rw-r--r--nixos/modules/programs/wayland/wayland-session.nix40
-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.nix27
-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.nix92
-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/acme/default.nix2
-rw-r--r--nixos/modules/security/ipa.nix16
-rw-r--r--nixos/modules/security/krb5/default.nix18
-rw-r--r--nixos/modules/security/krb5/krb5-conf-format.nix73
-rw-r--r--nixos/modules/security/systemd-confinement.nix36
-rw-r--r--nixos/modules/services/admin/docuum.nix30
-rw-r--r--nixos/modules/services/admin/meshcentral.nix2
-rw-r--r--nixos/modules/services/admin/pgadmin.nix10
-rw-r--r--nixos/modules/services/audio/alsa.nix3
-rw-r--r--nixos/modules/services/audio/mopidy.nix1
-rw-r--r--nixos/modules/services/audio/navidrome.nix191
-rw-r--r--nixos/modules/services/backup/borgbackup.nix34
-rw-r--r--nixos/modules/services/backup/restic.nix19
-rw-r--r--nixos/modules/services/cluster/k3s/default.nix44
-rw-r--r--nixos/modules/services/cluster/kubernetes/default.nix2
-rw-r--r--nixos/modules/services/cluster/rke2/default.nix311
-rw-r--r--nixos/modules/services/continuous-integration/hydra/default.nix2
-rw-r--r--nixos/modules/services/continuous-integration/jenkins/default.nix2
-rw-r--r--nixos/modules/services/databases/postgresql.md21
-rw-r--r--nixos/modules/services/desktop-managers/lomiri.nix16
-rw-r--r--nixos/modules/services/desktop-managers/plasma6.nix74
-rw-r--r--nixos/modules/services/desktops/espanso.nix11
-rw-r--r--nixos/modules/services/desktops/gnome/gnome-keyring.nix57
-rw-r--r--nixos/modules/services/display-managers/default.nix10
-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/editors/emacs.nix7
-rw-r--r--nixos/modules/services/games/archisteamfarm.nix9
-rw-r--r--nixos/modules/services/hardware/amdgpu.nix43
-rw-r--r--nixos/modules/services/hardware/amdvlk.nix59
-rw-r--r--nixos/modules/services/hardware/handheld-daemon.nix2
-rw-r--r--nixos/modules/services/hardware/kanata.nix76
-rw-r--r--nixos/modules/services/hardware/nvidia-container-toolkit/default.nix8
-rw-r--r--nixos/modules/services/hardware/nvidia-optimus.nix2
-rw-r--r--nixos/modules/services/hardware/power-profiles-daemon.nix6
-rw-r--r--nixos/modules/services/hardware/thermald.nix13
-rw-r--r--nixos/modules/services/hardware/udev.nix14
-rw-r--r--nixos/modules/services/home-automation/ebusd.nix2
-rw-r--r--nixos/modules/services/home-automation/home-assistant.nix5
-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/logging/journalwatch.nix4
-rw-r--r--nixos/modules/services/mail/mailman.nix2
-rw-r--r--nixos/modules/services/mail/postsrsd.nix9
-rw-r--r--nixos/modules/services/mail/public-inbox.nix2
-rw-r--r--nixos/modules/services/mail/stalwart-mail.nix163
-rw-r--r--nixos/modules/services/matrix/mautrix-signal.nix249
-rw-r--r--nixos/modules/services/matrix/synapse.nix2
-rw-r--r--nixos/modules/services/misc/amazon-ssm-agent.nix8
-rw-r--r--nixos/modules/services/misc/anki-sync-server.md2
-rw-r--r--nixos/modules/services/misc/bcg.nix6
-rw-r--r--nixos/modules/services/misc/devpi-server.nix132
-rw-r--r--nixos/modules/services/misc/forgejo.nix179
-rw-r--r--nixos/modules/services/misc/gitea.nix2
-rw-r--r--nixos/modules/services/misc/gollum.nix2
-rw-r--r--nixos/modules/services/misc/graphical-desktop.nix2
-rw-r--r--nixos/modules/services/misc/invidious-router.nix4
-rw-r--r--nixos/modules/services/misc/jellyfin.nix2
-rw-r--r--nixos/modules/services/misc/llama-cpp.nix1
-rw-r--r--nixos/modules/services/misc/mqtt2influxdb.nix3
-rw-r--r--nixos/modules/services/misc/ollama.nix56
-rw-r--r--nixos/modules/services/misc/open-webui.nix114
-rw-r--r--nixos/modules/services/misc/pghero.nix142
-rw-r--r--nixos/modules/services/misc/plex.nix29
-rw-r--r--nixos/modules/services/misc/portunus.nix23
-rw-r--r--nixos/modules/services/misc/private-gpt.nix121
-rw-r--r--nixos/modules/services/misc/renovate.nix153
-rw-r--r--nixos/modules/services/misc/snapper.nix305
-rw-r--r--nixos/modules/services/misc/sourcehut/service.nix9
-rw-r--r--nixos/modules/services/misc/tandoor-recipes.nix4
-rw-r--r--nixos/modules/services/misc/tzupdate.nix2
-rw-r--r--nixos/modules/services/misc/wastebin.nix2
-rw-r--r--nixos/modules/services/misc/zoneminder.nix2
-rw-r--r--nixos/modules/services/monitoring/alloy.nix80
-rw-r--r--nixos/modules/services/monitoring/arbtt.nix2
-rw-r--r--nixos/modules/services/monitoring/grafana-reporter.nix2
-rw-r--r--nixos/modules/services/monitoring/grafana.nix100
-rw-r--r--nixos/modules/services/monitoring/loki.nix15
-rw-r--r--nixos/modules/services/monitoring/netdata.nix65
-rw-r--r--nixos/modules/services/monitoring/prometheus/alertmanager-webhook-logger.nix70
-rw-r--r--nixos/modules/services/monitoring/prometheus/default.nix4
-rw-r--r--nixos/modules/services/monitoring/prometheus/exporters/bitcoin.nix4
-rw-r--r--nixos/modules/services/monitoring/scrutiny.nix4
-rw-r--r--nixos/modules/services/monitoring/zabbix-proxy.nix2
-rw-r--r--nixos/modules/services/network-filesystems/davfs2.nix59
-rw-r--r--nixos/modules/services/network-filesystems/samba.nix6
-rw-r--r--nixos/modules/services/networking/adguardhome.nix11
-rw-r--r--nixos/modules/services/networking/antennas.nix5
-rw-r--r--nixos/modules/services/networking/aria2.nix165
-rw-r--r--nixos/modules/services/networking/clatd.nix1
-rw-r--r--nixos/modules/services/networking/ddclient.nix22
-rw-r--r--nixos/modules/services/networking/frr.nix27
-rw-r--r--nixos/modules/services/networking/git-daemon.nix4
-rw-r--r--nixos/modules/services/networking/hostapd.nix17
-rw-r--r--nixos/modules/services/networking/inadyn.nix2
-rw-r--r--nixos/modules/services/networking/jotta-cli.md4
-rw-r--r--nixos/modules/services/networking/jotta-cli.nix4
-rw-r--r--nixos/modules/services/networking/kea.nix3
-rw-r--r--nixos/modules/services/networking/mihomo.nix1
-rw-r--r--nixos/modules/services/networking/mycelium.nix2
-rw-r--r--nixos/modules/services/networking/netbird.nix1
-rw-r--r--nixos/modules/services/networking/netbird/coturn.nix7
-rw-r--r--nixos/modules/services/networking/netbird/server.nix33
-rw-r--r--nixos/modules/services/networking/networkmanager.nix2
-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.nix10
-rw-r--r--nixos/modules/services/networking/smokeping.nix63
-rw-r--r--nixos/modules/services/networking/ssh/sshd.nix73
-rw-r--r--nixos/modules/services/networking/sunshine.nix6
-rw-r--r--nixos/modules/services/networking/tailscale-auth.nix2
-rw-r--r--nixos/modules/services/networking/tailscale.nix23
-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/networking/wstunnel.nix563
-rw-r--r--nixos/modules/services/networking/zerotierone.nix8
-rw-r--r--nixos/modules/services/search/qdrant.nix1
-rw-r--r--nixos/modules/services/search/quickwit.nix190
-rw-r--r--nixos/modules/services/security/bitwarden-directory-connector-cli.nix1
-rw-r--r--nixos/modules/services/security/oauth2-proxy-nginx.nix25
-rw-r--r--nixos/modules/services/security/oauth2-proxy.nix32
-rw-r--r--nixos/modules/services/security/sslmate-agent.nix2
-rw-r--r--nixos/modules/services/security/step-ca.nix4
-rw-r--r--nixos/modules/services/security/vaultwarden/default.nix47
-rw-r--r--nixos/modules/services/system/dbus.nix20
-rw-r--r--nixos/modules/services/system/kerberos/default.nix84
-rw-r--r--nixos/modules/services/system/kerberos/heimdal.nix105
-rw-r--r--nixos/modules/services/system/kerberos/kerberos-server.md55
-rw-r--r--nixos/modules/services/system/kerberos/mit.nix78
-rw-r--r--nixos/modules/services/system/nix-daemon.nix2
-rw-r--r--nixos/modules/services/torrent/flood.nix85
-rw-r--r--nixos/modules/services/torrent/transmission.nix5
-rw-r--r--nixos/modules/services/ttys/getty.nix3
-rw-r--r--nixos/modules/services/ttys/kmscon.nix2
-rw-r--r--nixos/modules/services/video/frigate.nix4
-rw-r--r--nixos/modules/services/video/photonvision.nix2
-rw-r--r--nixos/modules/services/wayland/cage.nix2
-rw-r--r--nixos/modules/services/wayland/hypridle.nix26
-rw-r--r--nixos/modules/services/web-apps/akkoma.nix16
-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/firefly-iii.nix98
-rw-r--r--nixos/modules/services/web-apps/flarum.nix210
-rw-r--r--nixos/modules/services/web-apps/freshrss.nix15
-rw-r--r--nixos/modules/services/web-apps/invoiceplane.nix34
-rw-r--r--nixos/modules/services/web-apps/keycloak.md12
-rw-r--r--nixos/modules/services/web-apps/keycloak.nix35
-rw-r--r--nixos/modules/services/web-apps/mastodon.nix67
-rw-r--r--nixos/modules/services/web-apps/mealie.nix3
-rw-r--r--nixos/modules/services/web-apps/miniflux.nix15
-rw-r--r--nixos/modules/services/web-apps/nextcloud-notify_push.nix3
-rw-r--r--nixos/modules/services/web-apps/nextcloud.md5
-rw-r--r--nixos/modules/services/web-apps/nextcloud.nix64
-rw-r--r--nixos/modules/services/web-apps/nextjs-ollama-llm-ui.nix87
-rw-r--r--nixos/modules/services/web-apps/node-red.nix12
-rw-r--r--nixos/modules/services/web-apps/plausible.nix9
-rw-r--r--nixos/modules/services/web-apps/pretalx.nix84
-rw-r--r--nixos/modules/services/web-apps/pretix.nix16
-rw-r--r--nixos/modules/services/web-apps/simplesamlphp.nix128
-rw-r--r--nixos/modules/services/web-apps/slskd.nix2
-rw-r--r--nixos/modules/services/web-apps/your_spotify.nix191
-rw-r--r--nixos/modules/services/web-apps/zitadel.nix2
-rw-r--r--nixos/modules/services/web-servers/bluemap.nix309
-rw-r--r--nixos/modules/services/web-servers/caddy/default.nix5
-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/web-servers/nginx/tailscale-auth.nix4
-rw-r--r--nixos/modules/services/web-servers/traefik.nix2
-rw-r--r--nixos/modules/services/x11/desktop-managers/mate.nix1
-rw-r--r--nixos/modules/services/x11/desktop-managers/pantheon.nix5
-rw-r--r--nixos/modules/services/x11/desktop-managers/phosh.nix2
-rw-r--r--nixos/modules/services/x11/desktop-managers/plasma5.nix2
-rw-r--r--nixos/modules/services/x11/desktop-managers/xfce.nix4
-rw-r--r--nixos/modules/services/x11/window-managers/clfswm.nix2
-rw-r--r--nixos/modules/services/x11/window-managers/qtile.nix43
-rw-r--r--nixos/modules/services/x11/xserver.nix10
-rwxr-xr-xnixos/modules/system/activation/switch-to-configuration.pl3
-rw-r--r--nixos/modules/system/activation/switchable-system.nix109
-rw-r--r--nixos/modules/system/activation/test.nix4
-rw-r--r--nixos/modules/system/activation/top-level.nix23
-rw-r--r--nixos/modules/system/boot/binfmt.nix2
-rw-r--r--nixos/modules/system/boot/initrd-ssh.nix2
-rw-r--r--nixos/modules/system/boot/loader/systemd-boot/systemd-boot-builder.py3
-rw-r--r--nixos/modules/system/boot/loader/systemd-boot/systemd-boot.nix6
-rw-r--r--nixos/modules/system/boot/networkd.nix267
-rw-r--r--nixos/modules/system/boot/resolved.nix143
-rw-r--r--nixos/modules/system/boot/stage-1-init.sh1
-rw-r--r--nixos/modules/system/boot/systemd.nix11
-rw-r--r--nixos/modules/system/boot/systemd/coredump.nix2
-rw-r--r--nixos/modules/system/boot/systemd/initrd.nix4
-rw-r--r--nixos/modules/system/boot/systemd/sysusers.nix21
-rw-r--r--nixos/modules/system/boot/systemd/user.nix12
-rw-r--r--nixos/modules/system/etc/build-composefs-dump.py35
-rw-r--r--nixos/modules/system/etc/etc.nix2
-rw-r--r--nixos/modules/tasks/filesystems/zfs.nix34
-rw-r--r--nixos/modules/tasks/network-interfaces-scripted.nix6
-rw-r--r--nixos/modules/tasks/network-interfaces-systemd.nix121
-rw-r--r--nixos/modules/testing/test-instrumentation.nix2
-rw-r--r--nixos/modules/virtualisation/containerd.nix1
-rw-r--r--nixos/modules/virtualisation/containers.nix13
-rw-r--r--nixos/modules/virtualisation/docker.nix4
-rw-r--r--nixos/modules/virtualisation/incus.nix74
-rw-r--r--nixos/modules/virtualisation/lxc-image-metadata.nix4
-rw-r--r--nixos/modules/virtualisation/lxd-agent.nix2
-rw-r--r--nixos/modules/virtualisation/oci-containers.nix11
-rw-r--r--nixos/modules/virtualisation/oci-image.nix2
-rw-r--r--nixos/modules/virtualisation/oci-options.nix6
-rw-r--r--nixos/modules/virtualisation/proxmox-image.nix83
-rw-r--r--nixos/modules/virtualisation/proxmox-lxc.nix11
-rw-r--r--nixos/modules/virtualisation/qemu-vm.nix2
-rw-r--r--nixos/modules/virtualisation/spice-usb-redirection.nix2
-rw-r--r--nixos/modules/virtualisation/vagrant-guest.nix3
-rw-r--r--nixos/modules/virtualisation/virtualbox-guest.nix11
-rw-r--r--nixos/modules/virtualisation/virtualbox-host.nix2
380 files changed, 9208 insertions, 4492 deletions
diff --git a/nixos/modules/config/fonts/ghostscript.nix b/nixos/modules/config/fonts/ghostscript.nix
index a5508b948990c..5db7c0ac71799 100644
--- a/nixos/modules/config/fonts/ghostscript.nix
+++ b/nixos/modules/config/fonts/ghostscript.nix
@@ -18,6 +18,6 @@ with lib;
   };
 
   config = mkIf config.fonts.enableGhostscriptFonts {
-    fonts.packages = [ "${pkgs.ghostscript}/share/ghostscript/fonts" ];
+    fonts.packages = [ pkgs.ghostscript.fonts ];
   };
 }
diff --git a/nixos/modules/config/no-x-libs.nix b/nixos/modules/config/no-x-libs.nix
index 1d7976cef36a2..930e57dbde5bb 100644
--- a/nixos/modules/config/no-x-libs.nix
+++ b/nixos/modules/config/no-x-libs.nix
@@ -39,25 +39,27 @@ with lib;
       # dep of graphviz, libXpm is optional for Xpm support
       gd = super.gd.override { withXorg = false; };
       ghostscript = super.ghostscript.override { cupsSupport = false; x11Support = false; };
-      gjs = super.gjs.overrideAttrs { doCheck = false; installTests = false; }; # avoid test dependency on gtk3
+      gjs = (super.gjs.override { installTests = false; }).overrideAttrs { doCheck = false; }; # avoid test dependency on gtk3
       gobject-introspection = super.gobject-introspection.override { x11Support = false; };
       gpg-tui = super.gpg-tui.override { x11Support = false; };
       gpsd = super.gpsd.override { guiSupport = false; };
       graphviz = super.graphviz-nox;
       gst_all_1 = super.gst_all_1 // {
         gst-plugins-bad = super.gst_all_1.gst-plugins-bad.override { guiSupport = false; };
-        gst-plugins-base = super.gst_all_1.gst-plugins-base.override { enableWayland = false; enableX11 = false; };
+        gst-plugins-base = super.gst_all_1.gst-plugins-base.override { enableGl = false; enableWayland = false; enableX11 = false; };
         gst-plugins-good = super.gst_all_1.gst-plugins-good.override { enableWayland = false; enableX11 = false; gtkSupport = false; qt5Support = false; qt6Support = false; };
+        gst-plugins-rs = super.gst_all_1.gst-plugins-rs.override { withGtkPlugins = false; };
       };
       imagemagick = super.imagemagick.override { libX11Support = false; libXtSupport = false; };
       imagemagickBig = super.imagemagickBig.override { libX11Support = false; libXtSupport = false; };
       intel-vaapi-driver = super.intel-vaapi-driver.override { enableGui = false; };
       libdevil = super.libdevil-nox;
       libextractor = super.libextractor.override { gtkSupport = false; };
+      libplacebo = super.libplacebo.override { vulkanSupport = false; };
       libva = super.libva-minimal;
       limesuite = super.limesuite.override { withGui = false; };
       mc = super.mc.override { x11Support = false; };
-      mpv-unwrapped = super.mpv-unwrapped.override { sdl2Support = false; x11Support = false; waylandSupport = false; };
+      mpv-unwrapped = super.mpv-unwrapped.override { drmSupport = false; screenSaverSupport = false; sdl2Support = false; vulkanSupport = false; waylandSupport = false; x11Support = false; };
       msmtp = super.msmtp.override { withKeyring = false; };
       mupdf = super.mupdf.override { enableGL = false; enableX11 = false; };
       neofetch = super.neofetch.override { x11Support = false; };
@@ -70,6 +72,7 @@ with lib;
       networkmanager-vpnc = super.networkmanager-vpnc.override { withGnome = false; };
       pango = super.pango.override { x11Support = false; };
       pinentry-curses = super.pinentry-curses.override { withLibsecret = false; };
+      pinentry-tty = super.pinentry-tty.override { withLibsecret = false; };
       pipewire = super.pipewire.override { vulkanSupport = false; x11Support = false; };
       pythonPackagesExtensions = super.pythonPackagesExtensions ++ [
         (python-final: python-prev: {
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/config/swap.nix b/nixos/modules/config/swap.nix
index a606ebd767598..53aea5d847129 100644
--- a/nixos/modules/config/swap.nix
+++ b/nixos/modules/config/swap.nix
@@ -275,7 +275,6 @@ in
                     chattr +C "$DEVICE" 2>/dev/null || true
 
                     dd if=/dev/zero of="$DEVICE" bs=1M count=${toString sw.size}
-                    chmod 0600 ${sw.device}
                     ${optionalString (!sw.randomEncryption.enable) "mkswap ${sw.realDevice}"}
                   fi
                 ''}
@@ -292,9 +291,12 @@ in
 
             unitConfig.RequiresMountsFor = [ "${dirOf sw.device}" ];
             unitConfig.DefaultDependencies = false; # needed to prevent a cycle
-            serviceConfig.Type = "oneshot";
-            serviceConfig.RemainAfterExit = sw.randomEncryption.enable;
-            serviceConfig.ExecStop = optionalString sw.randomEncryption.enable "${pkgs.cryptsetup}/bin/cryptsetup luksClose ${sw.deviceName}";
+            serviceConfig = {
+              Type = "oneshot";
+              RemainAfterExit = sw.randomEncryption.enable;
+              UMask = "0177";
+              ExecStop = optionalString sw.randomEncryption.enable "${pkgs.cryptsetup}/bin/cryptsetup luksClose ${sw.deviceName}";
+            };
             restartIfChanged = false;
           };
 
diff --git a/nixos/modules/config/terminfo.nix b/nixos/modules/config/terminfo.nix
index 4b58605aa7f1a..b538d749ffcbf 100644
--- a/nixos/modules/config/terminfo.nix
+++ b/nixos/modules/config/terminfo.nix
@@ -31,7 +31,7 @@ with lib;
     # attrNames (filterAttrs
     #  (_: drv: (builtins.tryEval (isDerivation drv && drv ? terminfo)).value)
     #  pkgs)
-    environment.systemPackages = mkIf config.environment.enableAllTerminfo (map (x: x.terminfo) (with pkgs; [
+    environment.systemPackages = mkIf config.environment.enableAllTerminfo (map (x: x.terminfo) (with pkgs.pkgsBuildBuild; [
       alacritty
       contour
       foot
diff --git a/nixos/modules/config/xdg/portal.nix b/nixos/modules/config/xdg/portal.nix
index 2c4d07c4953cb..2368ca04a49ea 100644
--- a/nixos/modules/config/xdg/portal.nix
+++ b/nixos/modules/config/xdg/portal.nix
@@ -96,7 +96,7 @@ in
         Sets which portal backend should be used to provide the implementation
         for the requested interface. For details check {manpage}`portals.conf(5)`.
 
-        Configs will be linked to `/etx/xdg/xdg-desktop-portal/` with the name `$desktop-portals.conf`
+        Configs will be linked to `/etc/xdg/xdg-desktop-portal/` with the name `$desktop-portals.conf`
         for `xdg.portal.config.$desktop` and `portals.conf` for `xdg.portal.config.common`
         as an exception.
       '';
diff --git a/nixos/modules/config/xdg/terminal-exec.nix b/nixos/modules/config/xdg/terminal-exec.nix
new file mode 100644
index 0000000000000..daf2055d2e906
--- /dev/null
+++ b/nixos/modules/config/xdg/terminal-exec.nix
@@ -0,0 +1,54 @@
+{
+  config,
+  lib,
+  pkgs,
+  ...
+}:
+
+let
+  cfg = config.xdg.terminal-exec;
+  inherit (lib) mkIf mkEnableOption mkOption mkPackageOption types;
+in
+{
+  meta.maintainers = with lib.maintainers; [ Cryolitia ];
+
+  ###### interface
+
+  options = {
+    xdg.terminal-exec = {
+      enable = mkEnableOption "xdg-terminal-exec, the [proposed](https://gitlab.freedesktop.org/xdg/xdg-specs/-/merge_requests/46) Default Terminal Execution Specification";
+      package = mkPackageOption pkgs "xdg-terminal-exec" { };
+      settings = mkOption {
+        type = with types; attrsOf (listOf str);
+        default = { };
+        description = ''
+          Configuration options for the Default Terminal Execution Specification.
+
+          The keys are the desktop environments that are matched (case-insensitively) against `$XDG_CURRENT_DESKTOP`,
+          or `default` which is used when the current desktop environment is not found in the configuration.
+          The values are a list of terminals' [desktop file IDs](https://specifications.freedesktop.org/desktop-entry-spec/latest/ar01s02.html#desktop-file-id) to try in order of decreasing priority.
+        '';
+        example = {
+          default = [ "kitty.desktop" ];
+          GNOME = [ "com.raggesilver.BlackBox.desktop" "org.gnome.Terminal.desktop" ];
+        };
+      };
+    };
+  };
+
+  ###### implementation
+
+  config = mkIf cfg.enable {
+    environment = {
+      systemPackages = [ cfg.package ];
+
+      etc = lib.mapAttrs' (
+        desktop: terminals:
+        # map desktop name such as GNOME to `xdg/gnome-xdg-terminals.list`, default to `xdg/xdg-terminals.list`
+        lib.nameValuePair (
+          "xdg/${if desktop == "default" then "" else "${lib.toLower desktop}-"}xdg-terminals.list"
+        ) { text = lib.concatLines terminals; }
+      ) cfg.settings;
+    };
+  };
+}
diff --git a/nixos/modules/hardware/graphics.nix b/nixos/modules/hardware/graphics.nix
new file mode 100644
index 0000000000000..99c122f75c2a1
--- /dev/null
+++ b/nixos/modules/hardware/graphics.nix
@@ -0,0 +1,126 @@
+{ config, lib, pkgs, ... }:
+let
+  cfg = config.hardware.graphics;
+
+  driversEnv = pkgs.buildEnv {
+    name = "graphics-drivers";
+    paths = [ cfg.package ] ++ cfg.extraPackages;
+  };
+
+  driversEnv32 = pkgs.buildEnv {
+    name = "graphics-drivers-32bit";
+    paths = [ cfg.package32 ] ++ cfg.extraPackages32;
+  };
+in
+{
+  imports = [
+    (lib.mkRenamedOptionModule [ "services" "xserver" "vaapiDrivers" ] [ "hardware" "opengl" "extraPackages" ])
+    (lib.mkRemovedOptionModule [ "hardware" "opengl" "s3tcSupport" ] "S3TC support is now always enabled in Mesa.")
+    (lib.mkRemovedOptionModule [ "hardware" "opengl" "driSupport"] "The setting can be removed.")
+
+    (lib.mkRenamedOptionModule [ "hardware" "opengl" "enable"] [ "hardware" "graphics" "enable" ])
+    (lib.mkRenamedOptionModule [ "hardware" "opengl" "driSupport32Bit"] [ "hardware" "graphics" "enable32Bit" ])
+    (lib.mkRenamedOptionModule [ "hardware" "opengl" "package"] [ "hardware" "graphics" "package" ])
+    (lib.mkRenamedOptionModule [ "hardware" "opengl" "package32"] [ "hardware" "graphics" "package32" ])
+    (lib.mkRenamedOptionModule [ "hardware" "opengl" "extraPackages"] [ "hardware" "graphics" "extraPackages" ])
+    (lib.mkRenamedOptionModule [ "hardware" "opengl" "extraPackages32"] [ "hardware" "graphics" "extraPackages32" ])
+  ];
+
+  options.hardware.graphics = {
+    enable = lib.mkOption {
+      description = ''
+        Whether to enable hardware accelerated graphics drivers.
+
+        This is required to allow most graphical applications and
+        environments to use hardware rendering, video encode/decode
+        acceleration, etc.
+
+        This option should be enabled by default by the corresponding modules,
+        so you do not usually have to set it yourself.
+      '';
+      type = lib.types.bool;
+      default = false;
+    };
+
+    enable32Bit = lib.mkOption {
+      description = ''
+        On 64-bit systems, whether to also install 32-bit drivers for
+        32-bit applications (such as Wine).
+      '';
+      type = lib.types.bool;
+      default = false;
+    };
+
+    package = lib.mkOption {
+      description = ''
+        The package that provides the default driver set.
+      '';
+      type = lib.types.package;
+      internal = true;
+    };
+
+    package32 = lib.mkOption {
+      description = ''
+        The package that provides the 32-bit driver set. Used when {option}`enable32Bit` is enabled.
+        set.
+      '';
+      type = lib.types.package;
+      internal = true;
+    };
+
+    extraPackages = lib.mkOption {
+      description = ''
+        Additional packages to add to the default graphics driver lookup path.
+        This can be used to add OpenCL drivers, VA-API/VDPAU drivers, etc.
+
+        ::: {.note}
+        intel-media-driver supports hardware Broadwell (2014) or newer. Older hardware should use the mostly unmaintained intel-vaapi-driver driver.
+        :::
+      '';
+      type = lib.types.listOf lib.types.package;
+      default = [];
+      example = lib.literalExpression "with pkgs; [ intel-media-driver intel-ocl intel-vaapi-driver ]";
+    };
+
+    extraPackages32 = lib.mkOption {
+      description = ''
+        Additional packages to add to 32-bit graphics driver lookup path on 64-bit systems.
+        Used when {option}`enable32Bit` is set. This can be used to add OpenCL drivers, VA-API/VDPAU drivers, etc.
+
+        ::: {.note}
+        intel-media-driver supports hardware Broadwell (2014) or newer. Older hardware should use the mostly unmaintained intel-vaapi-driver driver.
+        :::
+      '';
+      type = lib.types.listOf lib.types.package;
+      default = [];
+      example = lib.literalExpression "with pkgs.pkgsi686Linux; [ intel-media-driver intel-vaapi-driver ]";
+    };
+  };
+
+  config = lib.mkIf cfg.enable {
+    assertions = [
+      {
+        assertion = cfg.enable32Bit -> pkgs.stdenv.isx86_64;
+        message = "`hardware.graphics.enable32Bit` only makes sense on a 64-bit system.";
+      }
+      {
+        assertion = cfg.enable32Bit -> (config.boot.kernelPackages.kernel.features.ia32Emulation or false);
+        message = "`hardware.graphics.enable32Bit` requires a kernel that supports 32-bit emulation";
+      }
+    ];
+
+    systemd.tmpfiles.settings.graphics-driver = {
+      "/run/opengl-driver"."L+".argument = toString driversEnv;
+      "/run/opengl-driver-32" =
+        if pkgs.stdenv.isi686 then
+          { "L+".argument = "opengl-driver"; }
+        else if cfg.enable32Bit then
+          { "L+".argument = toString driversEnv32; }
+        else
+          { "r" = {}; };
+    };
+
+    hardware.graphics.package = lib.mkDefault pkgs.mesa.drivers;
+    hardware.graphics.package32 = lib.mkDefault pkgs.pkgsi686Linux.mesa.drivers;
+  };
+}
diff --git a/nixos/modules/hardware/opengl.nix b/nixos/modules/hardware/opengl.nix
deleted file mode 100644
index 25324fd8b0af9..0000000000000
--- a/nixos/modules/hardware/opengl.nix
+++ /dev/null
@@ -1,161 +0,0 @@
-{ config, lib, pkgs, ... }:
-
-with lib;
-
-let
-
-  cfg = config.hardware.opengl;
-
-  kernelPackages = config.boot.kernelPackages;
-
-  videoDrivers = config.services.xserver.videoDrivers;
-
-  package = pkgs.buildEnv {
-    name = "opengl-drivers";
-    paths = [ cfg.package ] ++ cfg.extraPackages;
-  };
-
-  package32 = pkgs.buildEnv {
-    name = "opengl-drivers-32bit";
-    paths = [ cfg.package32 ] ++ cfg.extraPackages32;
-  };
-
-in
-
-{
-
-  imports = [
-    (mkRenamedOptionModule [ "services" "xserver" "vaapiDrivers" ] [ "hardware" "opengl" "extraPackages" ])
-    (mkRemovedOptionModule [ "hardware" "opengl" "s3tcSupport" ] "S3TC support is now always enabled in Mesa.")
-  ];
-
-  options = {
-
-    hardware.opengl = {
-      enable = mkOption {
-        description = ''
-          Whether to enable OpenGL drivers. This is needed to enable
-          OpenGL support in X11 systems, as well as for Wayland compositors
-          like sway and Weston. It is enabled by default
-          by the corresponding modules, so you do not usually have to
-          set it yourself, only if there is no module for your wayland
-          compositor of choice. See services.xserver.enable and
-          programs.sway.enable.
-        '';
-        type = types.bool;
-        default = false;
-      };
-
-      driSupport = mkOption {
-        type = types.bool;
-        default = true;
-        description = ''
-          Whether to enable accelerated OpenGL rendering through the
-          Direct Rendering Interface (DRI).
-        '';
-      };
-
-      driSupport32Bit = mkOption {
-        type = types.bool;
-        default = false;
-        description = ''
-          On 64-bit systems, whether to support Direct Rendering for
-          32-bit applications (such as Wine).  This is currently only
-          supported for the `nvidia` as well as
-          `Mesa`.
-        '';
-      };
-
-      package = mkOption {
-        type = types.package;
-        internal = true;
-        description = ''
-          The package that provides the OpenGL implementation.
-        '';
-      };
-
-      package32 = mkOption {
-        type = types.package;
-        internal = true;
-        description = ''
-          The package that provides the 32-bit OpenGL implementation on
-          64-bit systems. Used when {option}`driSupport32Bit` is
-          set.
-        '';
-      };
-
-      extraPackages = mkOption {
-        type = types.listOf types.package;
-        default = [];
-        example = literalExpression "with pkgs; [ intel-media-driver intel-ocl intel-vaapi-driver ]";
-        description = ''
-          Additional packages to add to OpenGL drivers.
-          This can be used to add OpenCL drivers, VA-API/VDPAU drivers etc.
-
-          ::: {.note}
-          intel-media-driver supports hardware Broadwell (2014) or newer. Older hardware should use the mostly unmaintained intel-vaapi-driver driver.
-          :::
-        '';
-      };
-
-      extraPackages32 = mkOption {
-        type = types.listOf types.package;
-        default = [];
-        example = literalExpression "with pkgs.pkgsi686Linux; [ intel-media-driver intel-vaapi-driver ]";
-        description = ''
-          Additional packages to add to 32-bit OpenGL drivers on 64-bit systems.
-          Used when {option}`driSupport32Bit` is set. This can be used to add OpenCL drivers, VA-API/VDPAU drivers etc.
-
-          ::: {.note}
-          intel-media-driver supports hardware Broadwell (2014) or newer. Older hardware should use the mostly unmaintained intel-vaapi-driver driver.
-          :::
-        '';
-      };
-
-      setLdLibraryPath = mkOption {
-        type = types.bool;
-        internal = true;
-        default = false;
-        description = ''
-          Whether the `LD_LIBRARY_PATH` environment variable
-          should be set to the locations of driver libraries. Drivers which
-          rely on overriding libraries should set this to true. Drivers which
-          support `libglvnd` and other dispatch libraries
-          instead of overriding libraries should not set this.
-        '';
-      };
-    };
-
-  };
-
-  config = mkIf cfg.enable {
-    assertions = [
-      { assertion = cfg.driSupport32Bit -> pkgs.stdenv.isx86_64;
-        message = "Option driSupport32Bit only makes sense on a 64-bit system.";
-      }
-      { assertion = cfg.driSupport32Bit -> (config.boot.kernelPackages.kernel.features.ia32Emulation or false);
-        message = "Option driSupport32Bit requires a kernel that supports 32bit emulation";
-      }
-    ];
-
-    systemd.tmpfiles.rules = [
-      "L+ /run/opengl-driver - - - - ${package}"
-      (
-        if pkgs.stdenv.isi686 then
-          "L+ /run/opengl-driver-32 - - - - opengl-driver"
-        else if cfg.driSupport32Bit then
-          "L+ /run/opengl-driver-32 - - - - ${package32}"
-        else
-          "r /run/opengl-driver-32"
-      )
-    ];
-
-    environment.sessionVariables.LD_LIBRARY_PATH = mkIf cfg.setLdLibraryPath
-      ([ "/run/opengl-driver/lib" ] ++ optional cfg.driSupport32Bit "/run/opengl-driver-32/lib");
-
-    hardware.opengl.package = mkDefault pkgs.mesa.drivers;
-    hardware.opengl.package32 = mkDefault pkgs.pkgsi686Linux.mesa.drivers;
-
-    boot.extraModulePackages = optional (elem "virtualbox" videoDrivers) kernelPackages.virtualboxGuestAdditions;
-  };
-}
diff --git a/nixos/modules/hardware/openrazer.nix b/nixos/modules/hardware/openrazer.nix
index 5ba6abfdb3d7e..6f61254a60c1f 100644
--- a/nixos/modules/hardware/openrazer.nix
+++ b/nixos/modules/hardware/openrazer.nix
@@ -19,7 +19,7 @@ let
       [Startup]
       sync_effects_enabled = ${toPyBoolStr cfg.syncEffectsEnabled}
       devices_off_on_screensaver = ${toPyBoolStr cfg.devicesOffOnScreensaver}
-      battery_notifier = ${toPyBoolStr (cfg.mouseBatteryNotifier || cfg.batteryNotifier.enable)}
+      battery_notifier = ${toPyBoolStr cfg.batteryNotifier.enable}
       battery_notifier_freq = ${builtins.toString cfg.batteryNotifier.frequency}
       battery_notifier_percent = ${builtins.toString cfg.batteryNotifier.percentage}
 
@@ -80,14 +80,6 @@ in
         '';
       };
 
-      mouseBatteryNotifier = mkOption {
-        type = types.bool;
-        default = true;
-        description = ''
-          Mouse battery notifier.
-        '';
-      };
-
       batteryNotifier = mkOption {
         description = ''
           Settings for device battery notifications.
@@ -143,14 +135,11 @@ in
     };
   };
 
-  config = mkIf cfg.enable {
-    warnings = flatten [
-      (optional cfg.mouseBatteryNotifier ''
-        The option openrazer.mouseBatteryNotifier is deprecated.
-        Please use openrazer.batteryNotifier instead to enable and configure battery notifications.
-      '')
-    ];
+  imports = [
+    (mkRenamedOptionModule [ "hardware" "openrazer" "mouseBatteryNotifier" ] [ "hardware" "openrazer" "batteryNotifier" "enable" ])
+  ];
 
+  config = mkIf cfg.enable {
     boot.extraModulePackages = [ kernelPackages.openrazer ];
     boot.kernelModules = drivers;
 
diff --git a/nixos/modules/hardware/printers.nix b/nixos/modules/hardware/printers.nix
index de2f84d4831b8..ace900d88586d 100644
--- a/nixos/modules/hardware/printers.nix
+++ b/nixos/modules/hardware/printers.nix
@@ -13,7 +13,7 @@ let
     } // optionalAttrs (p.description != null) {
       D = p.description;
     } // optionalAttrs (p.ppdOptions != {}) {
-      o = mapAttrsToList (name: value: "'${name}'='${value}'") p.ppdOptions;
+      o = mapAttrsToList (name: value: "${name}=${value}") p.ppdOptions;
     });
   in ''
     ${pkgs.cups}/bin/lpadmin ${args} -E
diff --git a/nixos/modules/hardware/video/amdgpu-pro.nix b/nixos/modules/hardware/video/amdgpu-pro.nix
deleted file mode 100644
index 2a86280eec8cb..0000000000000
--- a/nixos/modules/hardware/video/amdgpu-pro.nix
+++ /dev/null
@@ -1,69 +0,0 @@
-# This module provides the proprietary AMDGPU-PRO drivers.
-
-{ config, lib, pkgs, ... }:
-
-with lib;
-
-let
-
-  drivers = config.services.xserver.videoDrivers;
-
-  enabled = elem "amdgpu-pro" drivers;
-
-  package = config.boot.kernelPackages.amdgpu-pro;
-  package32 = pkgs.pkgsi686Linux.linuxPackages.amdgpu-pro.override { kernel = null; };
-
-  opengl = config.hardware.opengl;
-
-in
-
-{
-
-  config = mkIf enabled {
-    services.xserver.drivers = singleton
-      { name = "amdgpu"; modules = [ package ]; display = true; };
-
-    hardware.opengl.package = package;
-    hardware.opengl.package32 = package32;
-    hardware.opengl.setLdLibraryPath = true;
-
-    boot.extraModulePackages = [ package.kmod ];
-
-    boot.kernelPackages = pkgs.linuxKernel.packagesFor
-      (pkgs.linuxKernel.kernels.linux_5_10.override {
-        structuredExtraConfig = {
-          DEVICE_PRIVATE = kernel.yes;
-          KALLSYMS_ALL = kernel.yes;
-        };
-      });
-
-    hardware.firmware = [ package.fw ];
-
-    systemd.tmpfiles.settings.amdgpu-pro = {
-      "/run/amdgpu"."L+".argument = "${package}/opt/amdgpu";
-      "/run/amdgpu-pro"."L+".argument = "${package}/opt/amdgpu-pro";
-    };
-
-    system.requiredKernelConfig = with config.lib.kernelConfig; [
-      (isYes "DEVICE_PRIVATE")
-      (isYes "KALLSYMS_ALL")
-    ];
-
-    boot.initrd.extraUdevRulesCommands = mkIf (!config.boot.initrd.systemd.enable) ''
-      cp -v ${package}/etc/udev/rules.d/*.rules $out/
-    '';
-    boot.initrd.services.udev.packages = [ package ];
-
-    environment.systemPackages =
-      [ package.vulkan ] ++
-      # this isn't really DRI, but we'll reuse this option for now
-      optional config.hardware.opengl.driSupport32Bit package32.vulkan;
-
-    environment.etc = {
-      "modprobe.d/blacklist-radeon.conf".source = package + "/etc/modprobe.d/blacklist-radeon.conf";
-      amd.source = package + "/etc/amd";
-    };
-
-  };
-
-}
diff --git a/nixos/modules/hardware/video/intel-gpu-tools.nix b/nixos/modules/hardware/video/intel-gpu-tools.nix
new file mode 100644
index 0000000000000..b69fefcae1184
--- /dev/null
+++ b/nixos/modules/hardware/video/intel-gpu-tools.nix
@@ -0,0 +1,25 @@
+{ config, lib, pkgs, ... }:
+
+let
+  cfg = config.hardware.intel-gpu-tools;
+in
+{
+  options = {
+    hardware.intel-gpu-tools = {
+      enable = lib.mkEnableOption "a setcap wrapper for intel-gpu-tools";
+    };
+  };
+
+  config = lib.mkIf cfg.enable {
+    security.wrappers.intel_gpu_top = {
+      owner = "root";
+      group = "root";
+      source = "${pkgs.intel-gpu-tools}/bin/intel_gpu_top";
+      capabilities = "cap_perfmon+ep";
+    };
+  };
+
+  meta = {
+    maintainers = with lib.maintainers; [ kira-bruneau ];
+  };
+}
diff --git a/nixos/modules/hardware/video/nvidia.nix b/nixos/modules/hardware/video/nvidia.nix
index 37d8e53a2e049..0274dfcaa70f9 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.
@@ -207,11 +206,26 @@ in {
         option is supported is used
       '';
 
+      prime.reverseSync.setupCommands.enable =
+        (lib.mkEnableOption ''
+          configure the display manager to be able to use the outputs
+          attached to the NVIDIA GPU.
+          Disable in order to configure the NVIDIA GPU outputs manually using xrandr.
+          Note that this configuration will only be successful when a display manager
+          for which the {option}`services.xserver.displayManager.setupCommands`
+          option is supported is used
+        '')
+        // {
+          default = true;
+        };
+
       nvidiaSettings =
         (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 +240,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 +257,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
+  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.";
+            }
           ];
-          extraPackages32 = [
-            nvidia_x11.lib32
+          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.mkIf 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.graphics = {
+            extraPackages = [ nvidia_x11.out ];
+            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";
+            }
           ];
-        };
-        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"
+
+          # 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"
+                '';
+            };
+
+          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 && reverseSyncCfg.setupCommands.enable))
               ''
-              + lib.optionalString cfg.forceFullCompositionPipeline ''
-                Option         "metamodes" "nvidia-auto-select +0+0 {ForceFullCompositionPipeline=On}"
-                Option         "AllowIndirectGLXProtocol" "off"
-                Option         "TripleBuffer" "on"
+                # Added by nvidia configuration module for Optimus/PRIME.
+                ${lib.getExe pkgs.xorg.xrandr} --setprovideroutputsource ${providerCmdParams}
+                ${lib.getExe pkgs.xorg.xrandr} --auto
               '';
-          };
 
-        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"
-          '';
+          environment.etc = {
+            "nvidia/nvidia-application-profiles-rc" = lib.mkIf nvidia_x11.useProfiles {
+              source = "${nvidia_x11.bin}/share/nvidia/nvidia-application-profiles-rc";
+            };
 
-        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
-          '';
+            # '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/";
+          };
 
-        environment.etc = {
-          "nvidia/nvidia-application-profiles-rc" = lib.mkIf nvidia_x11.useProfiles {source = "${nvidia_x11.bin}/share/nvidia/nvidia-application-profiles-rc";};
+          hardware.graphics = {
+            extraPackages = [ pkgs.nvidia-vaapi-driver ];
+            extraPackages32 = [ pkgs.pkgsi686Linux.nvidia-vaapi-driver ];
+          };
 
-          # '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/";
-        };
+          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 "$@"
+              ''
+            );
 
-        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"];
-          };
-        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"];
+          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 = lib.optional (cfg.open || lib.versionAtLeast nvidia_x11.version "555") 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/hardware/video/virtualbox.nix b/nixos/modules/hardware/video/virtualbox.nix
new file mode 100644
index 0000000000000..31ed92b7d148e
--- /dev/null
+++ b/nixos/modules/hardware/video/virtualbox.nix
@@ -0,0 +1,7 @@
+{ lib, config, ... }:
+let
+  inherit (config.boot) kernelPackages;
+  inherit (config.services.xserver) videoDrivers;
+in {
+  boot.extraModulePackages = lib.mkIf (lib.elem "virtualbox" videoDrivers) [ kernelPackages.virtualboxGuestAdditions ];
+}
diff --git a/nixos/modules/hardware/xone.nix b/nixos/modules/hardware/xone.nix
index 89690d8c6fb10..bb3b42399d8e1 100644
--- a/nixos/modules/hardware/xone.nix
+++ b/nixos/modules/hardware/xone.nix
@@ -6,7 +6,7 @@ let
 in
 {
   options.hardware.xone = {
-    enable = mkEnableOption "the xone driver for Xbox One and Xbobx Series X|S accessories";
+    enable = mkEnableOption "the xone driver for Xbox One and Xbox Series X|S accessories";
   };
 
   config = mkIf cfg.enable {
diff --git a/nixos/modules/image/repart-image.nix b/nixos/modules/image/repart-image.nix
index 59d5fc26efe9b..e404067299004 100644
--- a/nixos/modules/image/repart-image.nix
+++ b/nixos/modules/image/repart-image.nix
@@ -10,7 +10,6 @@
 , mypy
 , systemd
 , fakeroot
-, util-linux
 
   # filesystem tools
 , dosfstools
@@ -105,7 +104,6 @@ in
   nativeBuildInputs = [
     systemd
     fakeroot
-    util-linux
   ] ++ lib.optionals (compression.enable) [
     compressionPkg
   ] ++ fileSystemTools;
@@ -148,7 +146,7 @@ in
     runHook preBuild
 
     echo "Building image with systemd-repart..."
-    unshare --map-root-user fakeroot systemd-repart \
+    fakeroot systemd-repart \
       ''${systemdRepartFlags[@]} \
       ${imageFileBasename}.raw \
       | tee repart-output.json
diff --git a/nixos/modules/installer/cd-dvd/installation-cd-graphical-calamares-plasma5.nix b/nixos/modules/installer/cd-dvd/installation-cd-graphical-calamares-plasma5.nix
index 61e94ffed8894..d1a42fc7a713b 100644
--- a/nixos/modules/installer/cd-dvd/installation-cd-graphical-calamares-plasma5.nix
+++ b/nixos/modules/installer/cd-dvd/installation-cd-graphical-calamares-plasma5.nix
@@ -23,7 +23,7 @@
 
   environment.systemPackages = with pkgs; [
     # Graphical text editor
-    kate
+    plasma5Packages.kate
   ];
 
   system.activationScripts.installerDesktop = let
@@ -40,7 +40,7 @@
 
     ln -sfT ${manualDesktopFile} ${desktopDir + "nixos-manual.desktop"}
     ln -sfT ${pkgs.gparted}/share/applications/gparted.desktop ${desktopDir + "gparted.desktop"}
-    ln -sfT ${pkgs.konsole}/share/applications/org.kde.konsole.desktop ${desktopDir + "org.kde.konsole.desktop"}
+    ln -sfT ${pkgs.plasma5Packages.konsole}/share/applications/org.kde.konsole.desktop ${desktopDir + "org.kde.konsole.desktop"}
     ln -sfT ${pkgs.calamares-nixos}/share/applications/io.calamares.calamares.desktop ${desktopDir + "io.calamares.calamares.desktop"}
   '';
 
diff --git a/nixos/modules/installer/cd-dvd/installation-cd-graphical-plasma5.nix b/nixos/modules/installer/cd-dvd/installation-cd-graphical-plasma5.nix
index ce111bcebd5c9..770df5bb997b9 100644
--- a/nixos/modules/installer/cd-dvd/installation-cd-graphical-plasma5.nix
+++ b/nixos/modules/installer/cd-dvd/installation-cd-graphical-plasma5.nix
@@ -23,7 +23,7 @@
 
   environment.systemPackages = with pkgs; [
     # Graphical text editor
-    kate
+    plasma5Packages.kate
   ];
 
   system.activationScripts.installerDesktop = let
@@ -40,7 +40,7 @@
 
     ln -sfT ${manualDesktopFile} ${desktopDir + "nixos-manual.desktop"}
     ln -sfT ${pkgs.gparted}/share/applications/gparted.desktop ${desktopDir + "gparted.desktop"}
-    ln -sfT ${pkgs.konsole}/share/applications/org.kde.konsole.desktop ${desktopDir + "org.kde.konsole.desktop"}
+    ln -sfT ${pkgs.plasma5Packages.konsole}/share/applications/org.kde.konsole.desktop ${desktopDir + "org.kde.konsole.desktop"}
   '';
 
 }
diff --git a/nixos/modules/installer/netboot/netboot.nix b/nixos/modules/installer/netboot/netboot.nix
index c88a53393d13f..93f806b75eb11 100644
--- a/nixos/modules/installer/netboot/netboot.nix
+++ b/nixos/modules/installer/netboot/netboot.nix
@@ -37,10 +37,6 @@ with lib;
     # here and it causes a cyclic dependency.
     boot.loader.grub.enable = false;
 
-    # !!! Hack - attributes expected by other modules.
-    environment.systemPackages = [ pkgs.grub2_efi ]
-      ++ (lib.optionals (pkgs.stdenv.hostPlatform.system != "aarch64-linux") [pkgs.grub2 pkgs.syslinux]);
-
     fileSystems."/" = mkImageMediaOverride
       { fsType = "tmpfs";
         options = [ "mode=0755" ];
diff --git a/nixos/modules/installer/tools/nix-fallback-paths.nix b/nixos/modules/installer/tools/nix-fallback-paths.nix
index e4241e9654036..9669ec5e37f3c 100644
--- a/nixos/modules/installer/tools/nix-fallback-paths.nix
+++ b/nixos/modules/installer/tools/nix-fallback-paths.nix
@@ -1,7 +1,7 @@
 {
-  x86_64-linux = "/nix/store/azvn85cras6xv4z5j85fiy406f24r1q0-nix-2.18.1";
-  i686-linux = "/nix/store/9bnwy7f9h0kzdzmcnjjsjg0aak5waj40-nix-2.18.1";
-  aarch64-linux = "/nix/store/hh65xwqm9s040s3cgn9vzcmrxj0sf5ij-nix-2.18.1";
-  x86_64-darwin = "/nix/store/6zi5fqzn9n17wrk8r41rhdw4j7jqqsi3-nix-2.18.1";
-  aarch64-darwin = "/nix/store/0pbq6wzr2f1jgpn5212knyxpwmkjgjah-nix-2.18.1";
+  x86_64-linux = "/nix/store/yrsmzlw2lgbknzwic1gy1gmv3l2w1ax8-nix-2.18.3";
+  i686-linux = "/nix/store/ds9381l9mlwfaclvqnkzn3jl4qb8m3y1-nix-2.18.3";
+  aarch64-linux = "/nix/store/hw1zny3f8520zyskmp1qaybv1ir5ilxh-nix-2.18.3";
+  x86_64-darwin = "/nix/store/z08yc4sl1fr65q53wz6pw30h67qafaln-nix-2.18.3";
+  aarch64-darwin = "/nix/store/p57m7m0wrz8sqxiwinzpwzqzak82zn75-nix-2.18.3";
 }
diff --git a/nixos/modules/misc/locate.nix b/nixos/modules/misc/locate.nix
index 84c711c2b4efa..0e9adefff5e1e 100644
--- a/nixos/modules/misc/locate.nix
+++ b/nixos/modules/misc/locate.nix
@@ -1,24 +1,22 @@
 { config, lib, pkgs, ... }:
 
-with lib;
-
 let
   cfg = config.services.locate;
-  isMLocate = hasPrefix "mlocate" cfg.package.name;
-  isPLocate = hasPrefix "plocate" cfg.package.name;
+  isMLocate = lib.hasPrefix "mlocate" cfg.package.name;
+  isPLocate = lib.hasPrefix "plocate" cfg.package.name;
   isMorPLocate = isMLocate || isPLocate;
-  isFindutils = hasPrefix "findutils" cfg.package.name;
+  isFindutils = lib.hasPrefix "findutils" cfg.package.name;
 in
 {
   imports = [
-    (mkRenamedOptionModule [ "services" "locate" "period" ] [ "services" "locate" "interval" ])
-    (mkRenamedOptionModule [ "services" "locate" "locate" ] [ "services" "locate" "package" ])
-    (mkRemovedOptionModule [ "services" "locate" "includeStore" ] "Use services.locate.prunePaths")
+    (lib.mkRenamedOptionModule [ "services" "locate" "period" ] [ "services" "locate" "interval" ])
+    (lib.mkRenamedOptionModule [ "services" "locate" "locate" ] [ "services" "locate" "package" ])
+    (lib.mkRemovedOptionModule [ "services" "locate" "includeStore" ] "Use services.locate.prunePaths")
   ];
 
-  options.services.locate = with types; {
-    enable = mkOption {
-      type = bool;
+  options.services.locate = {
+    enable = lib.mkOption {
+      type = lib.types.bool;
       default = false;
       description = ''
         If enabled, NixOS will periodically update the database of
@@ -26,12 +24,12 @@ in
       '';
     };
 
-    package = mkPackageOption pkgs [ "findutils" "locate" ] {
+    package = lib.mkPackageOption pkgs [ "findutils" "locate" ] {
       example = "mlocate";
     };
 
-    interval = mkOption {
-      type = str;
+    interval = lib.mkOption {
+      type = lib.types.str;
       default = "02:15";
       example = "hourly";
       description = ''
@@ -46,24 +44,24 @@ in
       '';
     };
 
-    extraFlags = mkOption {
-      type = listOf str;
+    extraFlags = lib.mkOption {
+      type = lib.types.listOf lib.types.str;
       default = [ ];
       description = ''
         Extra flags to pass to {command}`updatedb`.
       '';
     };
 
-    output = mkOption {
-      type = path;
+    output = lib.mkOption {
+      type = lib.types.path;
       default = "/var/cache/locatedb";
       description = ''
         The database file to build.
       '';
     };
 
-    localuser = mkOption {
-      type = nullOr str;
+    localuser = lib.mkOption {
+      type = lib.types.nullOr lib.types.str;
       default = "nobody";
       description = ''
         The user to search non-network directories as, using
@@ -71,8 +69,8 @@ in
       '';
     };
 
-    pruneFS = mkOption {
-      type = listOf str;
+    pruneFS = lib.mkOption {
+      type = lib.types.listOf lib.types.str;
       default = [
         "afs"
         "anon_inodefs"
@@ -158,8 +156,8 @@ in
       '';
     };
 
-    prunePaths = mkOption {
-      type = listOf path;
+    prunePaths = lib.mkOption {
+      type = lib.types.listOf lib.types.path;
       default = [
         "/tmp"
         "/var/tmp"
@@ -175,10 +173,10 @@ in
       '';
     };
 
-    pruneNames = mkOption {
-      type = listOf str;
+    pruneNames = lib.mkOption {
+      type = lib.types.listOf lib.types.str;
       default = lib.optionals (!isFindutils) [ ".bzr" ".cache" ".git" ".hg" ".svn" ];
-      defaultText = literalMD ''
+      defaultText = lib.literalMD ''
         `[ ".bzr" ".cache" ".git" ".hg" ".svn" ]`, if
         supported by the locate implementation (i.e. mlocate or plocate).
       '';
@@ -187,8 +185,8 @@ in
       '';
     };
 
-    pruneBindMounts = mkOption {
-      type = bool;
+    pruneBindMounts = lib.mkOption {
+      type = lib.types.bool;
       default = false;
       description = ''
         Whether not to index bind mounts
@@ -197,10 +195,10 @@ in
 
   };
 
-  config = mkIf cfg.enable {
-    users.groups = mkMerge [
-      (mkIf isMLocate { mlocate = { }; })
-      (mkIf isPLocate { plocate = { }; })
+  config = lib.mkIf cfg.enable {
+    users.groups = lib.mkMerge [
+      (lib.mkIf isMLocate { mlocate = { }; })
+      (lib.mkIf isPLocate { plocate = { }; })
     ];
 
     security.wrappers =
@@ -211,46 +209,46 @@ in
           setgid = true;
           setuid = false;
         };
-        mlocate = mkIf isMLocate {
+        mlocate = lib.mkIf isMLocate {
           group = "mlocate";
           source = "${cfg.package}/bin/locate";
         };
-        plocate = mkIf isPLocate {
+        plocate = lib.mkIf isPLocate {
           group = "plocate";
           source = "${cfg.package}/bin/plocate";
         };
       in
-      mkIf isMorPLocate {
-        locate = mkMerge [ common mlocate plocate ];
-        plocate = mkIf isPLocate (mkMerge [ common plocate ]);
+      lib.mkIf isMorPLocate {
+        locate = lib.mkMerge [ common mlocate plocate ];
+        plocate = lib.mkIf isPLocate (lib.mkMerge [ common plocate ]);
       };
 
-    environment.systemPackages = [ cfg.package ];
+    environment = {
+      # write /etc/updatedb.conf for manual calls to `updatedb`
+      etc."updatedb.conf".text = ''
+        PRUNEFS="${lib.concatStringsSep " " cfg.pruneFS}"
+        PRUNENAMES="${lib.concatStringsSep " " cfg.pruneNames}"
+        PRUNEPATHS="${lib.concatStringsSep " " cfg.prunePaths}"
+        PRUNE_BIND_MOUNTS="${if cfg.pruneBindMounts then "yes" else "no"}"
+      '';
 
-    environment.variables.LOCATE_PATH = cfg.output;
+      systemPackages = [ cfg.package ];
 
-    environment.etc = {
-      # write /etc/updatedb.conf for manual calls to `updatedb`
-      "updatedb.conf" = {
-        text = ''
-          PRUNEFS="${lib.concatStringsSep " " cfg.pruneFS}"
-          PRUNENAMES="${lib.concatStringsSep " " cfg.pruneNames}"
-          PRUNEPATHS="${lib.concatStringsSep " " cfg.prunePaths}"
-          PRUNE_BIND_MOUNTS="${if cfg.pruneBindMounts then "yes" else "no"}"
-        '';
+      variables = lib.mkIf isFindutils {
+        LOCATE_PATH = cfg.output;
       };
     };
 
-    warnings = optional (isMorPLocate && cfg.localuser != null)
+    warnings = lib.optional (isMorPLocate && cfg.localuser != null)
       "mlocate and plocate do not support the services.locate.localuser option. updatedb will run as root. Silence this warning by setting services.locate.localuser = null."
-    ++ optional (isFindutils && cfg.pruneNames != [ ])
+    ++ lib.optional (isFindutils && cfg.pruneNames != [ ])
       "findutils locate does not support pruning by directory component"
-    ++ optional (isFindutils && cfg.pruneBindMounts)
+    ++ lib.optional (isFindutils && cfg.pruneBindMounts)
       "findutils locate does not support skipping bind mounts";
 
     systemd.services.update-locatedb = {
       description = "Update Locate Database";
-      path = mkIf (!isMorPLocate) [ pkgs.su ];
+      path = lib.mkIf (!isMorPLocate) [ pkgs.su ];
 
       # mlocate's updatedb takes flags via a configuration file or
       # on the command line, but not by environment variable.
@@ -258,42 +256,44 @@ in
         if isMorPLocate then
           let
             toFlags = x:
-              optional (cfg.${x} != [ ])
-                "--${lib.toLower x} '${concatStringsSep " " cfg.${x}}'";
-            args = concatLists (map toFlags [ "pruneFS" "pruneNames" "prunePaths" ]);
+              lib.optional (cfg.${x} != [ ])
+                "--${lib.toLower x} '${lib.concatStringsSep " " cfg.${x}}'";
+            args = lib.concatLists (map toFlags [ "pruneFS" "pruneNames" "prunePaths" ]);
           in
           ''
             exec ${cfg.package}/bin/updatedb \
-              --output ${toString cfg.output} ${concatStringsSep " " args} \
+              --output ${toString cfg.output} ${lib.concatStringsSep " " args} \
               --prune-bind-mounts ${if cfg.pruneBindMounts then "yes" else "no"} \
-              ${concatStringsSep " " cfg.extraFlags}
+              ${lib.concatStringsSep " " cfg.extraFlags}
           ''
         else ''
           exec ${cfg.package}/bin/updatedb \
-            ${optionalString (cfg.localuser != null && !isMorPLocate) "--localuser=${cfg.localuser}"} \
-            --output=${toString cfg.output} ${concatStringsSep " " cfg.extraFlags}
+            ${lib.optionalString (cfg.localuser != null && !isMorPLocate) "--localuser=${cfg.localuser}"} \
+            --output=${toString cfg.output} ${lib.concatStringsSep " " cfg.extraFlags}
         '';
-      environment = optionalAttrs (!isMorPLocate) {
-        PRUNEFS = concatStringsSep " " cfg.pruneFS;
-        PRUNEPATHS = concatStringsSep " " cfg.prunePaths;
-        PRUNENAMES = concatStringsSep " " cfg.pruneNames;
+      environment = lib.optionalAttrs (!isMorPLocate) {
+        PRUNEFS = lib.concatStringsSep " " cfg.pruneFS;
+        PRUNEPATHS = lib.concatStringsSep " " cfg.prunePaths;
+        PRUNENAMES = lib.concatStringsSep " " cfg.pruneNames;
         PRUNE_BIND_MOUNTS = if cfg.pruneBindMounts then "yes" else "no";
       };
-      serviceConfig.Nice = 19;
-      serviceConfig.IOSchedulingClass = "idle";
-      serviceConfig.PrivateTmp = "yes";
-      serviceConfig.PrivateNetwork = "yes";
-      serviceConfig.NoNewPrivileges = "yes";
-      serviceConfig.ReadOnlyPaths = "/";
-      # Use dirOf cfg.output because mlocate creates temporary files next to
-      # the actual database. We could specify and create them as well,
-      # but that would make this quite brittle when they change something.
-      # NOTE: If /var/cache does not exist, this leads to the misleading error message:
-      # update-locatedb.service: Failed at step NAMESPACE spawning …/update-locatedb-start: No such file or directory
-      serviceConfig.ReadWritePaths = dirOf cfg.output;
+      serviceConfig = {
+        Nice = 19;
+        IOSchedulingClass = "idle";
+        PrivateTmp = "yes";
+        PrivateNetwork = "yes";
+        NoNewPrivileges = "yes";
+        ReadOnlyPaths = "/";
+        # Use dirOf cfg.output because mlocate creates temporary files next to
+        # the actual database. We could specify and create them as well,
+        # but that would make this quite brittle when they change something.
+        # NOTE: If /var/cache does not exist, this leads to the misleading error message:
+        # update-locatedb.service: Failed at step NAMESPACE spawning …/update-locatedb-start: No such file or directory
+        ReadWritePaths = dirOf cfg.output;
+      };
     };
 
-    systemd.timers.update-locatedb = mkIf (cfg.interval != "never") {
+    systemd.timers.update-locatedb = lib.mkIf (cfg.interval != "never") {
       description = "Update timer for locate database";
       partOf = [ "update-locatedb.service" ];
       wantedBy = [ "timers.target" ];
diff --git a/nixos/modules/misc/version.nix b/nixos/modules/misc/version.nix
index d582e0c162de3..db917f73a0645 100644
--- a/nixos/modules/misc/version.nix
+++ b/nixos/modules/misc/version.nix
@@ -121,7 +121,7 @@ in
     image = {
 
       id = lib.mkOption {
-        type = types.nullOr (types.strMatching "^[a-z0-9._-]+$");
+        type = types.nullOr types.str;
         default = null;
         description = ''
           Image identifier.
@@ -135,7 +135,7 @@ in
       };
 
       version = lib.mkOption {
-        type = types.nullOr (types.strMatching "^[a-z0-9._-]+$");
+        type = types.nullOr types.str;
         default = null;
         description = ''
           Image version.
diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix
index 111b5c129cb3c..876e40983c1e5 100644
--- a/nixos/modules/module-list.nix
+++ b/nixos/modules/module-list.nix
@@ -45,6 +45,7 @@
   ./config/xdg/portals/lxqt.nix
   ./config/xdg/portals/wlr.nix
   ./config/xdg/sounds.nix
+  ./config/xdg/terminal-exec.nix
   ./config/zram.nix
   ./hardware/acpilight.nix
   ./hardware/all-firmware.nix
@@ -66,6 +67,7 @@
   ./hardware/gkraken.nix
   ./hardware/glasgow.nix
   ./hardware/gpgsmartcards.nix
+  ./hardware/graphics.nix
   ./hardware/hackrf.nix
   ./hardware/i2c.nix
   ./hardware/infiniband.nix
@@ -83,7 +85,6 @@
   ./hardware/new-lg4ff.nix
   ./hardware/nitrokey.nix
   ./hardware/onlykey/default.nix
-  ./hardware/opengl.nix
   ./hardware/openrazer.nix
   ./hardware/opentabletdriver.nix
   ./hardware/pcmcia.nix
@@ -102,13 +103,14 @@
   ./hardware/uni-sync.nix
   ./hardware/usb-modeswitch.nix
   ./hardware/usb-storage.nix
-  ./hardware/video/amdgpu-pro.nix
   ./hardware/video/bumblebee.nix
   ./hardware/video/capture/mwprocapture.nix
   ./hardware/video/displaylink.nix
+  ./hardware/video/intel-gpu-tools.nix
   ./hardware/video/nvidia.nix
   ./hardware/video/switcheroo-control.nix
   ./hardware/video/uvcvideo/default.nix
+  ./hardware/video/virtualbox.nix
   ./hardware/video/webcam/facetimehd.nix
   ./hardware/video/webcam/ipu6.nix
   ./hardware/wooting.nix
@@ -156,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
@@ -165,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
@@ -192,6 +196,7 @@
   ./programs/fzf.nix
   ./programs/gamemode.nix
   ./programs/gamescope.nix
+  ./programs/gdk-pixbuf.nix
   ./programs/geary.nix
   ./programs/git.nix
   ./programs/gnome-disks.nix
@@ -214,6 +219,7 @@
   ./programs/kbdlight.nix
   ./programs/kclock.nix
   ./programs/kdeconnect.nix
+  ./programs/ladybird.nix
   ./programs/lazygit.nix
   ./programs/kubeswitch.nix
   ./programs/less.nix
@@ -245,9 +251,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
@@ -277,6 +283,7 @@
   ./programs/systemtap.nix
   ./programs/thefuck.nix
   ./programs/thunar.nix
+  ./programs/thunderbird.nix
   ./programs/tmux.nix
   ./programs/traceroute.nix
   ./programs/trippy.nix
@@ -288,6 +295,7 @@
   ./programs/virt-manager.nix
   ./programs/wavemon.nix
   ./programs/wayland/cardboard.nix
+  ./programs/wayland/hyprlock.nix
   ./programs/wayland/hyprland.nix
   ./programs/wayland/labwc.nix
   ./programs/wayland/river.nix
@@ -306,6 +314,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
@@ -412,6 +421,7 @@
   ./services/cluster/kubernetes/scheduler.nix
   ./services/cluster/pacemaker/default.nix
   ./services/cluster/patroni/default.nix
+  ./services/cluster/rke2/default.nix
   ./services/cluster/spark/default.nix
   ./services/computing/boinc/client.nix
   ./services/computing/foldingathome/client.nix
@@ -539,6 +549,8 @@
   ./services/games/xonotic.nix
   ./services/hardware/acpid.nix
   ./services/hardware/actkbd.nix
+  ./services/hardware/amdgpu.nix
+  ./services/hardware/amdvlk.nix
   ./services/hardware/argonone.nix
   ./services/hardware/asusd.nix
   ./services/hardware/auto-cpufreq.nix
@@ -664,6 +676,7 @@
   ./services/matrix/maubot.nix
   ./services/matrix/mautrix-facebook.nix
   ./services/matrix/mautrix-meta.nix
+  ./services/matrix/mautrix-signal.nix
   ./services/matrix/mautrix-telegram.nix
   ./services/matrix/mautrix-whatsapp.nix
   ./services/matrix/mjolnir.nix
@@ -696,6 +709,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
@@ -760,12 +774,14 @@
   ./services/misc/octoprint.nix
   ./services/misc/ollama.nix
   ./services/misc/ombi.nix
+  ./services/misc/open-webui.nix
   ./services/misc/osrm.nix
   ./services/misc/owncast.nix
   ./services/misc/packagekit.nix
   ./services/misc/paperless.nix
   ./services/misc/parsoid.nix
   ./services/misc/persistent-evdev.nix
+  ./services/misc/pghero.nix
   ./services/misc/pinnwand.nix
   ./services/misc/plex.nix
   ./services/misc/plikd.nix
@@ -773,12 +789,14 @@
   ./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
   ./services/misc/radarr.nix
   ./services/misc/readarr.nix
   ./services/misc/redmine.nix
+  ./services/misc/renovate.nix
   ./services/misc/ripple-data-api.nix
   ./services/misc/rippled.nix
   ./services/misc/rmfakecloud.nix
@@ -821,6 +839,7 @@
   ./services/misc/zoneminder.nix
   ./services/misc/zookeeper.nix
   ./services/monitoring/alerta.nix
+  ./services/monitoring/alloy.nix
   ./services/monitoring/apcupsd.nix
   ./services/monitoring/arbtt.nix
   ./services/monitoring/below.nix
@@ -861,6 +880,7 @@
   ./services/monitoring/osquery.nix
   ./services/monitoring/parsedmarc.nix
   ./services/monitoring/prometheus/alertmanager-irc-relay.nix
+  ./services/monitoring/prometheus/alertmanager-webhook-logger.nix
   ./services/monitoring/prometheus/alertmanager.nix
   ./services/monitoring/prometheus/default.nix
   ./services/monitoring/prometheus/exporters.nix
@@ -1100,6 +1120,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
@@ -1234,6 +1255,7 @@
   ./services/search/meilisearch.nix
   ./services/search/opensearch.nix
   ./services/search/qdrant.nix
+  ./services/search/quickwit.nix
   ./services/search/sonic-server.nix
   ./services/search/typesense.nix
   ./services/security/aesmd.nix
@@ -1296,6 +1318,7 @@
   ./services/system/zram-generator.nix
   ./services/torrent/deluge.nix
   ./services/torrent/flexget.nix
+  ./services/torrent/flood.nix
   ./services/torrent/magnetico.nix
   ./services/torrent/opentracker.nix
   ./services/torrent/peerflix.nix
@@ -1316,9 +1339,11 @@
   ./services/video/unifi-video.nix
   ./services/video/v4l2-relayd.nix
   ./services/wayland/cage.nix
+  ./services/wayland/hypridle.nix
   ./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
@@ -1332,6 +1357,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
@@ -1342,7 +1368,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
@@ -1386,6 +1414,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
@@ -1414,6 +1443,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
@@ -1425,11 +1455,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
@@ -1473,7 +1505,6 @@
   ./services/x11/display-managers/xpra.nix
   ./services/x11/extra-layouts.nix
   ./services/x11/fractalart.nix
-  ./services/x11/gdk-pixbuf.nix
   ./services/x11/hardware/cmt.nix
   ./services/x11/hardware/digimend.nix
   ./services/x11/hardware/synaptics.nix
diff --git a/nixos/modules/profiles/perlless.nix b/nixos/modules/profiles/perlless.nix
index 90abd14f077e4..010e4f8f2a28e 100644
--- a/nixos/modules/profiles/perlless.nix
+++ b/nixos/modules/profiles/perlless.nix
@@ -26,6 +26,6 @@
 
   # Check that the system does not contain a Nix store path that contains the
   # string "perl".
-  system.forbiddenDependenciesRegex = "perl";
+  system.forbiddenDependenciesRegexes = ["perl"];
 
 }
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..f143361bc9331 100644
--- a/nixos/modules/programs/bash/bash-completion.nix
+++ b/nixos/modules/programs/bash/bash-completion.nix
@@ -1,18 +1,22 @@
 { config, lib, pkgs, ... }:
 
-with lib;
-
 let
-  enable = config.programs.bash.enableCompletion;
+  cfg = config.programs.bash;
 in
 {
-  options = {
-    programs.bash.enableCompletion = mkEnableOption "Bash completion for all interactive bash shells" // {
+  options.programs.bash.completion = {
+    enable = lib.mkEnableOption "Bash completion for all interactive bash shells" // {
       default = true;
     };
+
+    package = lib.mkPackageOption pkgs "bash-completion" { };
   };
 
-  config = mkIf enable {
+  imports = [
+    (lib.mkRenamedOptionModule [ "programs" "bash" "enableCompletion" ] [ "programs" "bash" "completion" "enable" ])
+  ];
+
+  config = lib.mkIf cfg.completion.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
@@ -21,7 +25,7 @@ in
       # $XDG_DATA_DIRS/bash-completion/completions/
       # on demand, so they do not need to be sourced here.
       if shopt -q progcomp &>/dev/null; then
-        . "${pkgs.bash-completion}/etc/profile.d/bash_completion.sh"
+        . "${cfg.completion.package}/etc/profile.d/bash_completion.sh"
         nullglobStatus=$(shopt -p nullglob)
         shopt -s nullglob
         for p in $NIX_PROFILES; do
diff --git a/nixos/modules/programs/bash/bash.nix b/nixos/modules/programs/bash/bash.nix
index 21ef8338d8dd8..4c06f0aad9f81 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.completion.enable [
       "/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/coolercontrol.nix b/nixos/modules/programs/coolercontrol.nix
index 8c9a39d2eba99..1c64d46ae2b90 100644
--- a/nixos/modules/programs/coolercontrol.nix
+++ b/nixos/modules/programs/coolercontrol.nix
@@ -48,9 +48,11 @@ in
 
     # Nvidia support
     (lib.mkIf cfg.nvidiaSupport {
-      systemd.services.coolercontrold.path = with config.boot.kernelPackages; [
-        nvidia_x11 # nvidia-smi
-        nvidia_x11.settings # nvidia-settings
+      systemd.services.coolercontrold.path = let
+        nvidiaPkg = config.hardware.nvidia.package;
+      in [
+        nvidiaPkg # nvidia-smi
+        nvidiaPkg.settings # nvidia-settings
       ];
     })
   ]);
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 2102a07cd0bca..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,16 +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;
       };
 
-      useBabelfish = mkOption {
-        type = types.bool;
+      package = lib.mkPackageOption pkgs "fish" { };
+
+      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).
@@ -64,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";
@@ -97,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";
@@ -161,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;
@@ -244,8 +244,8 @@ in
           patchedGenerator = pkgs.stdenv.mkDerivation {
             name = "fish_patched-completion-generator";
             srcs = [
-              "${pkgs.fish}/share/fish/tools/create_manpage_completions.py"
-              "${pkgs.fish}/share/fish/tools/deroff.py"
+              "${cfg.package}/share/fish/tools/create_manpage_completions.py"
+              "${cfg.package}/share/fish/tools/deroff.py"
             ];
             unpackCmd = "cp $curSrc $(basename $curSrc)";
             sourceRoot = ".";
@@ -264,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
@@ -275,24 +275,24 @@ 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 = [ pkgs.fish ]; }
+      { systemPackages = [ cfg.package ]; }
 
       {
         shells = [
           "/run/current-system/sw/bin/fish"
-          "${pkgs.fish}/bin/fish"
+          (lib.getExe 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/fzf.nix b/nixos/modules/programs/fzf.nix
index 66ad7d418de68..b9258ab1e5052 100644
--- a/nixos/modules/programs/fzf.nix
+++ b/nixos/modules/programs/fzf.nix
@@ -15,7 +15,7 @@ in
     environment.systemPackages = lib.mkIf (cfg.keybindings || cfg.fuzzyCompletion) [ pkgs.fzf ];
 
     programs = {
-      # load after programs.bash.enableCompletion
+      # load after programs.bash.completion.enable
       bash.promptPluginInit = lib.mkAfter (lib.optionalString cfg.fuzzyCompletion ''
         source ${pkgs.fzf}/share/fzf/completion.bash
       '' + lib.optionalString cfg.keybindings ''
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/services/x11/gdk-pixbuf.nix b/nixos/modules/programs/gdk-pixbuf.nix
index 9e89d9f96c4af..f96259ccd2c78 100644
--- a/nixos/modules/services/x11/gdk-pixbuf.nix
+++ b/nixos/modules/programs/gdk-pixbuf.nix
@@ -1,16 +1,20 @@
 { config, lib, pkgs, ... }:
 
 let
-  cfg = config.services.xserver.gdk-pixbuf;
+  cfg = config.programs.gdk-pixbuf;
 
   loadersCache = pkgs.gnome._gdkPixbufCacheBuilder_DO_NOT_USE {
-    extraLoaders = lib.unique (cfg.modulePackages);
+    extraLoaders = lib.unique cfg.modulePackages;
   };
 in
 
 {
+  imports = [
+    (lib.mkRenamedOptionModule [ "services" "xserver" "gdk-pixbuf" ] [ "programs" "gdk-pixbuf" ])
+  ];
+
   options = {
-    services.xserver.gdk-pixbuf.modulePackages = lib.mkOption {
+    programs.gdk-pixbuf.modulePackages = lib.mkOption {
       type = lib.types.listOf lib.types.package;
       default = [ ];
       description = "Packages providing GDK-Pixbuf modules, for cache generation.";
@@ -22,7 +26,7 @@ in
   # GDK_PIXBUF_MODULE_FILE to point to it.
   config = lib.mkIf (cfg.modulePackages != []) {
     environment.sessionVariables = {
-      GDK_PIXBUF_MODULE_FILE = "${loadersCache}";
+      GDK_PIXBUF_MODULE_FILE = loadersCache;
     };
   };
 }
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/kubeswitch.nix b/nixos/modules/programs/kubeswitch.nix
index 304df48e3c11a..9348540022f23 100644
--- a/nixos/modules/programs/kubeswitch.nix
+++ b/nixos/modules/programs/kubeswitch.nix
@@ -29,17 +29,13 @@ in
 
   config =
     let
-      shell_files = pkgs.stdenv.mkDerivation rec {
-        name = "kubeswitch-shell-files";
-        phases = [ "installPhase" ];
-        installPhase = ''
-          mkdir -p $out/share
-          for shell in bash zsh; do
-            ${cfg.package}/bin/switcher init $shell | sed 's/switch(/${cfg.commandName}(/' > $out/share/${cfg.commandName}_init.$shell
-            ${cfg.package}/bin/switcher --cmd ${cfg.commandName} completion $shell > $out/share/${cfg.commandName}_completion.$shell
-          done
-        '';
-      };
+      shell_files = pkgs.runCommand "kubeswitch-shell-files" {} ''
+        mkdir -p $out/share
+        for shell in bash zsh; do
+          ${cfg.package}/bin/switcher init $shell | sed 's/switch(/${cfg.commandName}(/' > $out/share/${cfg.commandName}_init.$shell
+          ${cfg.package}/bin/switcher --cmd ${cfg.commandName} completion $shell > $out/share/${cfg.commandName}_completion.$shell
+        done
+      '';
     in
     lib.mkIf cfg.enable {
       environment.systemPackages = [ cfg.package ];
diff --git a/nixos/modules/programs/ladybird.nix b/nixos/modules/programs/ladybird.nix
new file mode 100644
index 0000000000000..43bfe445ef58e
--- /dev/null
+++ b/nixos/modules/programs/ladybird.nix
@@ -0,0 +1,14 @@
+{ config, pkgs, lib, ... }:
+
+let
+  cfg = config.programs.ladybird;
+in {
+  options = {
+    programs.ladybird.enable = lib.mkEnableOption "the Ladybird web browser";
+  };
+
+  config = lib.mkIf cfg.enable {
+    environment.systemPackages = [ pkgs.ladybird ];
+    fonts.fontDir.enable = true;
+  };
+}
diff --git a/nixos/modules/programs/less.nix b/nixos/modules/programs/less.nix
index 2cb7620075118..50ea1586f6880 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,14 @@ 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";
+
+      package = lib.mkPackageOption pkgs "less" { };
 
-      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 +50,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 +60,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 +70,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 +79,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 +90,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 +110,26 @@ in
     };
   };
 
-  config = mkIf cfg.enable {
+  config = lib.mkIf cfg.enable {
 
-    environment.systemPackages = [ pkgs.less ];
+    environment.systemPackages = [ cfg.package ];
 
     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/miriway.nix b/nixos/modules/programs/miriway.nix
index 00c1356ab0836..418bb3dc4f2dd 100644
--- a/nixos/modules/programs/miriway.nix
+++ b/nixos/modules/programs/miriway.nix
@@ -65,7 +65,7 @@ in {
       };
     };
 
-    hardware.opengl.enable = lib.mkDefault true;
+    hardware.graphics.enable = lib.mkDefault true;
     fonts.enableDefaultPackages = lib.mkDefault true;
     programs.dconf.enable = lib.mkDefault true;
     programs.xwayland.enable = lib.mkDefault 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..ef5bad69e934e 100644
--- a/nixos/modules/programs/shadow.nix
+++ b/nixos/modules/programs/shadow.nix
@@ -1,29 +1,39 @@
 # 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 = {
+
+    security.shadow.enable = lib.mkEnableOption "" // {
+      default = true;
+      description = ''
+        Enable the shadow authentication suite, which provides critical programs such as su, login, passwd.
+
+        Note: This is currently experimental. Only disable this if you're
+        confident that you can recover your system if it breaks.
+      '';
+    };
+
     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.
         '';
-        type = nullOr str;
+        type = lib.types.nullOr lib.types.str;
         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.
           See login.defs(5) man page for available options.
         '';
-        type = submodule {
+        type = lib.types.submodule {
           freeformType = (pkgs.formats.keyValue { }).type;
           /* There are three different sources for user/group id ranges, each of which gets
              used by different programs:
@@ -35,88 +45,88 @@ 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" ];
+              type = lib.types.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"];
+              type = lib.types.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;
+              type = lib.types.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;
+              type = lib.types.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;
+              type = lib.types.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;
+              type = lib.types.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;
+              type = lib.types.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;
+              type = lib.types.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;
+              type = lib.types.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;
+              type = lib.types.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'';
               default = "tty";
-              type = str;
+              type = lib.types.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'';
               default = "0620";
-              type = str;
+              type = lib.types.str;
             };
 
             # 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;
+              type = lib.types.str;
             };
           };
         };
@@ -124,7 +134,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,108 +142,116 @@ 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";
-      type = either path shellPackage;
+      example = lib.literalExpression "pkgs.zsh";
+      type = lib.types.either lib.types.path lib.types.shellPackage;
     };
   };
 
   ###### implementation
 
-  config = {
-    assertions = [
-      {
-        assertion = cfg.settings.SYS_UID_MIN <= cfg.settings.SYS_UID_MAX;
-        message = "SYS_UID_MIN must be less than or equal to SYS_UID_MAX";
-      }
-      {
-        assertion = cfg.settings.UID_MIN <= cfg.settings.UID_MAX;
-        message = "UID_MIN must be less than or equal to UID_MAX";
-      }
-      {
-        assertion = cfg.settings.SYS_GID_MIN <= cfg.settings.SYS_GID_MAX;
-        message = "SYS_GID_MIN must be less than or equal to SYS_GID_MAX";
-      }
-      {
-        assertion = cfg.settings.GID_MIN <= cfg.settings.GID_MAX;
-        message = "GID_MIN must be less than or equal to GID_MAX";
-      }
-    ];
-
-    security.loginDefs.settings.CHFN_RESTRICT =
-      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.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 { } " ";
-        };
-      in
-      {
-        # /etc/login.defs: global configuration for pwdutils.
-        # You cannot login without it!
-        "login.defs".source = pkgs.writeText "login.defs" (toKeyValue cfg.settings);
-
-        # /etc/default/useradd: configuration for useradd.
-        "default/useradd".source = pkgs.writeText "useradd" ''
-          GROUP=100
-          HOME=/home
-          SHELL=${utils.toShellPath config.users.defaultUserShell}
-        '';
-      };
+  config = lib.mkMerge [
+    {
+      assertions = [
+        {
+          assertion = config.security.shadow.enable || config.services.greetd.enable;
+          message = "You must enable at least one VT login method, either security.shadow.enable or services.greetd.enable";
+        }
+      ];
+    }
+    (lib.mkIf config.security.shadow.enable {
+      assertions = [
+        {
+          assertion = cfg.settings.SYS_UID_MIN <= cfg.settings.SYS_UID_MAX;
+          message = "SYS_UID_MIN must be less than or equal to SYS_UID_MAX";
+        }
+        {
+          assertion = cfg.settings.UID_MIN <= cfg.settings.UID_MAX;
+          message = "UID_MIN must be less than or equal to UID_MAX";
+        }
+        {
+          assertion = cfg.settings.SYS_GID_MIN <= cfg.settings.SYS_GID_MAX;
+          message = "SYS_GID_MIN must be less than or equal to SYS_GID_MAX";
+        }
+        {
+          assertion = cfg.settings.GID_MIN <= cfg.settings.GID_MAX;
+          message = "GID_MIN must be less than or equal to GID_MAX";
+        }
+      ];
 
-    security.pam.services = {
-      chsh = { rootOK = true; };
-      chfn = { rootOK = true; };
-      su = {
-        rootOK = true;
-        forwardXAuth = true;
-        logFailures = true;
-      };
-      passwd = { };
-      # Note: useradd, groupadd etc. aren't setuid root, so it
-      # doesn't really matter what the PAM config says as long as it
-      # lets root in.
-      useradd.rootOK = true;
-      usermod.rootOK = true;
-      userdel.rootOK = true;
-      groupadd.rootOK = true;
-      groupmod.rootOK = true;
-      groupmems.rootOK = true;
-      groupdel.rootOK = true;
-      login = {
-        startSession = true;
-        allowNullPassword = true;
-        showMotd = true;
-        updateWtmp = true;
-      };
-      chpasswd = { rootOK = true; };
-    };
+      security.loginDefs.settings.CHFN_RESTRICT = lib.mkIf (cfg.chfnRestrict != null) cfg.chfnRestrict;
+
+      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 = lib.generators.toKeyValue {
+            mkKeyValue = lib.generators.mkKeyValueDefault { } " ";
+          };
+        in {
+          # /etc/login.defs: global configuration for pwdutils.
+          # You cannot login without it!
+          "login.defs".source = pkgs.writeText "login.defs" (toKeyValue cfg.settings);
+
+          # /etc/default/useradd: configuration for useradd.
+          "default/useradd".source = pkgs.writeText "useradd" ''
+            GROUP=100
+            HOME=/home
+            SHELL=${utils.toShellPath config.users.defaultUserShell}
+          '';
+        };
 
-    security.wrappers =
-      let
-        mkSetuidRoot = source: {
-          setuid = true;
-          owner = "root";
-          group = "root";
-          inherit source;
+      security.pam.services = {
+        chsh.rootOK = true;
+        chfn.rootOK = true;
+        su = {
+          rootOK = true;
+          forwardXAuth = true;
+          logFailures = true;
         };
-      in
-      {
-        su = mkSetuidRoot "${cfg.package.su}/bin/su";
-        sg = mkSetuidRoot "${cfg.package.out}/bin/sg";
-        newgrp = mkSetuidRoot "${cfg.package.out}/bin/newgrp";
-        newuidmap = mkSetuidRoot "${cfg.package.out}/bin/newuidmap";
-        newgidmap = mkSetuidRoot "${cfg.package.out}/bin/newgidmap";
-      }
-      // optionalAttrs config.users.mutableUsers {
-        chsh = mkSetuidRoot "${cfg.package.out}/bin/chsh";
-        passwd = mkSetuidRoot "${cfg.package.out}/bin/passwd";
+        passwd = { };
+        # Note: useradd, groupadd etc. aren't setuid root, so it
+        # doesn't really matter what the PAM config says as long as it
+        # lets root in.
+        useradd.rootOK = true;
+        usermod.rootOK = true;
+        userdel.rootOK = true;
+        groupadd.rootOK = true;
+        groupmod.rootOK = true;
+        groupmems.rootOK = true;
+        groupdel.rootOK = true;
+        login = {
+          startSession = true;
+          allowNullPassword = true;
+          showMotd = true;
+          updateWtmp = true;
+        };
+        chpasswd.rootOK = true;
       };
-  };
+
+      security.wrappers =
+        let
+          mkSetuidRoot = source: {
+            setuid = true;
+            owner = "root";
+            group = "root";
+            inherit source;
+          };
+        in
+          {
+            su = mkSetuidRoot "${cfg.package.su}/bin/su";
+            sg = mkSetuidRoot "${cfg.package.out}/bin/sg";
+            newgrp = mkSetuidRoot "${cfg.package.out}/bin/newgrp";
+            newuidmap = mkSetuidRoot "${cfg.package.out}/bin/newuidmap";
+            newgidmap = mkSetuidRoot "${cfg.package.out}/bin/newgidmap";
+          }
+          // 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..2ee464dc22d37 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,18 +44,19 @@ 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
           prevLibs = if prev ? extraLibraries then prev.extraLibraries pkgs else [ ];
-          additionalLibs = with config.hardware.opengl;
+          additionalLibs = with config.hardware.graphics;
             if pkgs.stdenv.hostPlatform.is64bit
             then [ package ] ++ extraPackages
             else [ package32 ] ++ extraPackages32;
         in prevLibs ++ additionalLibs;
-      } // optionalAttrs (cfg.gamescopeSession.enable && gamescopeCfg.capSysNice)
+        extraPkgs = p: (cfg.extraPackages ++ lib.optionals (prev ? extraPkgs) (prev.extraPkgs p));
+      } // lib.optionalAttrs (cfg.gamescopeSession.enable && gamescopeCfg.capSysNice)
       {
         buildFHSEnv = pkgs.buildFHSEnv.override {
           # use the setuid wrapped bubblewrap
@@ -71,10 +72,23 @@ in {
       '';
     };
 
-    extraCompatPackages = mkOption {
-      type = types.listOf types.package;
+    extraPackages = lib.mkOption {
+      type = lib.types.listOf lib.types.package;
+      default = [ ];
+      example = lib.literalExpression ''
+        with pkgs; [
+          gamescope
+        ]
+      '';
+      description = ''
+        Additional packages to add to the Steam environment.
+      '';
+    };
+
+    extraCompatPackages = lib.mkOption {
+      type = lib.types.listOf lib.types.package;
       default = [ ];
-      example = literalExpression ''
+      example = lib.literalExpression ''
         with pkgs; [
           proton-ge-bin
         ]
@@ -88,46 +102,59 @@ in {
       '';
     };
 
-    remotePlay.openFirewall = mkOption {
-      type = types.bool;
+    fontPackages = lib.mkOption {
+      type = lib.types.listOf lib.types.package;
+      # `fonts.packages` is a list of paths now, filter out which are not packages
+      default = builtins.filter lib.types.package.check config.fonts.packages;
+      defaultText = lib.literalExpression "builtins.filter lib.types.package.check config.fonts.packages";
+      example = lib.literalExpression "with pkgs; [ source-han-sans ]";
+      description = ''
+        Font packages to use in Steam.
+
+        Defaults to system fonts, but could be overridden to use other fonts — useful for users who would like to customize CJK fonts used in Steam. According to the [upstream issue](https://github.com/ValveSoftware/steam-for-linux/issues/10422#issuecomment-1944396010), Steam only follows the per-user fontconfig configuration.
+      '';
+    };
+
+    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 +164,24 @@ 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 {
-    hardware.opengl = { # this fixes the "glXChooseVisual failed" bug, context: https://github.com/NixOS/nixpkgs/issues/47932
+  config = lib.mkIf cfg.enable {
+    hardware.graphics = { # this fixes the "glXChooseVisual failed" bug, context: https://github.com/NixOS/nixpkgs/issues/47932
       enable = true;
-      driSupport = true;
-      driSupport32Bit = true;
+      enable32Bit = 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 +191,10 @@ in {
       };
     };
 
-    programs.gamescope.enable = mkDefault cfg.gamescopeSession.enable;
-    services.displayManager.sessionPackages = mkIf cfg.gamescopeSession.enable [ gamescopeSessionFile ];
+    programs.steam.extraPackages = cfg.fontPackages;
+
+    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 +204,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/thunderbird.nix b/nixos/modules/programs/thunderbird.nix
new file mode 100644
index 0000000000000..b15c1df609439
--- /dev/null
+++ b/nixos/modules/programs/thunderbird.nix
@@ -0,0 +1,89 @@
+{
+  pkgs,
+  config,
+  lib,
+  ...
+}:
+let
+  cfg = config.programs.thunderbird;
+  policyFormat = pkgs.formats.json { };
+  policyDoc = "https://github.com/thunderbird/policy-templates";
+in
+{
+  options.programs.thunderbird = {
+    enable = lib.mkEnableOption "Thunderbird mail client";
+
+    package = lib.mkPackageOption pkgs "thunderbird" { };
+
+    policies = lib.mkOption {
+      type = policyFormat.type;
+      default = { };
+      description = ''
+        Group policies to install.
+
+        See [Thunderbird's documentation](${policyDoc})
+        for a list of available options.
+
+        This can be used to install extensions declaratively! Check out the
+        documentation of the `ExtensionSettings` policy for details.
+
+      '';
+    };
+
+    preferences = lib.mkOption {
+      type =
+        with lib.types;
+        attrsOf (oneOf [
+          bool
+          int
+          str
+        ]);
+      default = { };
+      description = ''
+        Preferences to set from `about:config`.
+
+        Some of these might be able to be configured more ergonomically
+        using policies.
+      '';
+    };
+
+    preferencesStatus = lib.mkOption {
+      type = lib.types.enum [
+        "default"
+        "locked"
+        "user"
+        "clear"
+      ];
+      default = "locked";
+      description = ''
+        The status of `thunderbird.preferences`.
+
+        `status` can assume the following values:
+        - `"default"`: Preferences appear as default.
+        - `"locked"`: Preferences appear as default and can't be changed.
+        - `"user"`: Preferences appear as changed.
+        - `"clear"`: Value has no effect. Resets to factory defaults on each startup.
+      '';
+    };
+  };
+
+  config = lib.mkIf cfg.enable {
+    environment.systemPackages = [ cfg.package ];
+
+    environment.etc =
+      let
+        policiesJSON = policyFormat.generate "thunderbird-policies.json" { inherit (cfg) policies; };
+      in
+      lib.mkIf (cfg.policies != { }) { "thunderbird/policies/policies.json".source = policiesJSON; };
+
+    programs.thunderbird.policies = {
+      DisableAppUpdate = true;
+      Preferences = builtins.mapAttrs (_: value: {
+        Value = value;
+        Status = cfg.preferencesStatus;
+      }) cfg.preferences;
+    };
+  };
+
+  meta.maintainers = with lib.maintainers; [ nydragon ];
+}
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..c7ab18a2e2886 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,14 +10,14 @@ 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
           implementation works.
 
-          This will enable {option}`hardware.opengl.enable` so that OpenGL
+          This will enable {option}`hardware.graphics.enable` so that OpenGL
           programs can find Mesa's llvmpipe drivers.
 
           Setting this option to `false` does not mean that software
@@ -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).
@@ -48,7 +46,7 @@ in
     # can find the llvmpipe `swrast.so` software rendering DRI lib via `libglvnd`.
     # This comment exists to explain why `hardware.` is involved,
     # even though 100% software rendering is used.
-    hardware.opengl.enable = true;
+    hardware.graphics.enable = true;
 
   };
 }
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 e648eaa1b68e4..575adc79cf10b 100644
--- a/nixos/modules/programs/wayland/hyprland.nix
+++ b/nixos/modules/programs/wayland/hyprland.nix
@@ -1,57 +1,43 @@
-{ config
-, lib
-, pkgs
-, ...
-}:
-with lib; let
+{ config, lib, pkgs, ... }:
+
+let
   cfg = config.programs.hyprland;
 
-  finalPortalPackage = cfg.portalPackage.override {
-    hyprland = cfg.finalPackage;
-  };
+  wayland-lib = import ./lib.nix { inherit lib; };
 in
 {
   options.programs.hyprland = {
-    enable = mkEnableOption null // {
-      description = ''
-        Whether to enable Hyprland, the dynamic tiling Wayland compositor that doesn't sacrifice on its looks.
-
-        You can manually launch Hyprland by executing {command}`Hyprland` on a TTY.
-
-        A configuration file will be generated in {file}`~/.config/hypr/hyprland.conf`.
-        See <https://wiki.hyprland.org> for more information.
+    enable = lib.mkEnableOption ''
+      Hyprland, the dynamic tiling Wayland compositor that doesn't sacrifice on its looks.
+      You can manually launch Hyprland by executing {command}`Hyprland` on a TTY.
+      A configuration file will be generated in {file}`~/.config/hypr/hyprland.conf`.
+      See <https://wiki.hyprland.org> for more information'';
+
+    package = lib.mkPackageOption pkgs "hyprland" {
+      extraDescription = ''
+        If the package is not overridable with `enableXWayland`, then the module option
+        {option}`xwayland` will have no effect.
       '';
-    };
-
-    package = mkPackageOption pkgs "hyprland" { };
-
-    finalPackage = mkOption {
-      type = types.package;
-      readOnly = true;
-      default = cfg.package.override {
+    } // {
+      apply = p: wayland-lib.genFinalPackage p {
         enableXWayland = cfg.xwayland.enable;
       };
-      defaultText = literalExpression
-        "`programs.hyprland.package` with applied configuration";
-      description = ''
-        The Hyprland package after applying configuration.
-      '';
     };
 
-    portalPackage = mkPackageOption pkgs "xdg-desktop-portal-hyprland" { };
-
-    xwayland.enable = mkEnableOption ("XWayland") // { default = true; };
-
-    envVars.enable = mkEnableOption null // {
-      default = true;
-      example = false;
-      description = ''
-        Set environment variables for Hyprland to work properly.
-        Enabled by default.
+    portalPackage = lib.mkPackageOption pkgs "xdg-desktop-portal-hyprland" {
+      extraDescription = ''
+        If the package is not overridable with `hyprland`, then the Hyprland package
+        used by the portal may differ from the one set in the module option {option}`package`.
       '';
+    } // {
+      apply = p: wayland-lib.genFinalPackage p {
+        hyprland = cfg.package;
+      };
     };
 
-    systemd.setPath.enable = mkEnableOption null // {
+    xwayland.enable = lib.mkEnableOption "XWayland" // { default = true; };
+
+    systemd.setPath.enable = lib.mkEnableOption null // {
       default = true;
       example = false;
       description = ''
@@ -62,55 +48,47 @@ in
     };
   };
 
-  config = mkIf cfg.enable {
-    environment.systemPackages = [ cfg.finalPackage ];
-
-    fonts.enableDefaultPackages = mkDefault true;
-    hardware.opengl.enable = mkDefault true;
+  config = lib.mkIf cfg.enable (lib.mkMerge [
+    {
+      environment.systemPackages = [ cfg.package ];
 
-    programs = {
-      dconf.enable = mkDefault true;
-      xwayland.enable = mkDefault cfg.xwayland.enable;
-    };
-
-    security.polkit.enable = true;
+      # To make a Hyprland session available if a display manager like SDDM is enabled:
+      services.displayManager.sessionPackages = [ cfg.package ];
 
-    services.displayManager.sessionPackages = [ cfg.finalPackage ];
-
-    xdg.portal = {
-      enable = mkDefault true;
-      extraPortals = [ finalPortalPackage ];
-      configPackages = mkDefault [ cfg.finalPackage ];
-    };
+      xdg.portal = {
+        enable = true;
+        extraPortals = [ cfg.portalPackage ];
+        configPackages = lib.mkDefault [ cfg.package ];
+      };
 
-    environment.sessionVariables = mkIf cfg.envVars.enable {
-      XDG_CURRENT_DESKTOP = "Hyprland";
-      XDG_SESSION_DESKTOP = "Hyprland";
-      XDG_SESSION_TYPE = "wayland";
-      GDK_BACKEND = "wayland,x11";
-      QT_QPA_PLATFORM = "wayland;xcb";
-      _JAVA_AWT_WM_NONREPARENTING = "1"; # Fix for Java applications on tiling window managers
-    };
+      systemd = lib.mkIf cfg.systemd.setPath.enable {
+        user.extraConfig = ''
+          DefaultEnvironment="PATH=/run/wrappers/bin:/etc/profiles/per-user/%u/bin:/nix/var/nix/profiles/default/bin:/run/current-system/sw/bin:$PATH"
+        '';
+      };
+    }
 
-    systemd = mkIf cfg.systemd.setPath.enable {
-      user.extraConfig = ''
-        DefaultEnvironment="PATH=$PATH:/run/current-system/sw/bin:/etc/profiles/per-user/%u/bin:/run/wrappers/bin"
-      '';
-    };
-  };
+    (import ./wayland-session.nix {
+      inherit lib pkgs;
+      enableXWayland = cfg.xwayland.enable;
+      enableWlrPortal = lib.mkDefault false; # Hyprland has its own portal, wlr is not needed
+    })
+  ]);
 
-  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"
     )
   ];
+
+  meta.maintainers = with lib.maintainers; [ fufexan ];
 }
diff --git a/nixos/modules/programs/wayland/hyprlock.nix b/nixos/modules/programs/wayland/hyprlock.nix
new file mode 100644
index 0000000000000..6c60765e80cc7
--- /dev/null
+++ b/nixos/modules/programs/wayland/hyprlock.nix
@@ -0,0 +1,25 @@
+{ lib, pkgs, config, ... }:
+
+let
+  cfg = config.programs.hyprlock;
+in
+{
+  options.programs.hyprlock = {
+    enable = lib.mkEnableOption "hyprlock, Hyprland's GPU-accelerated screen locking utility";
+    package = lib.mkPackageOption pkgs "hyprlock" { };
+  };
+
+  config = lib.mkIf cfg.enable {
+    environment.systemPackages = [
+      cfg.package
+    ];
+
+    # Hyprlock needs Hypridle systemd service to be running to detect idle time
+    services.hypridle.enable = true;
+
+    # Hyprlock needs PAM access to authenticate, else it fallbacks to su
+    security.pam.services.hyprlock = {};
+  };
+
+  meta.maintainers = with lib.maintainers; [ johnrtitor ];
+}
diff --git a/nixos/modules/programs/wayland/lib.nix b/nixos/modules/programs/wayland/lib.nix
new file mode 100644
index 0000000000000..0f275d3f18c56
--- /dev/null
+++ b/nixos/modules/programs/wayland/lib.nix
@@ -0,0 +1,12 @@
+{ lib }:
+
+{
+  genFinalPackage = pkg: args:
+    let
+      expectedArgs = with lib;
+        lib.naturalSort (lib.attrNames args);
+      existingArgs = with lib;
+        naturalSort (intersectLists expectedArgs (attrNames (functionArgs pkg.override)));
+    in
+      if existingArgs != expectedArgs then pkg else pkg.override args;
+}
diff --git a/nixos/modules/programs/wayland/river.nix b/nixos/modules/programs/wayland/river.nix
index d0e309646b0ef..6391f00e2f626 100644
--- a/nixos/modules/programs/wayland/river.nix
+++ b/nixos/modules/programs/wayland/river.nix
@@ -1,37 +1,40 @@
-{
-  config,
-  pkgs,
-  lib,
-  ...
-}:
-with lib; let
+{ config, lib, pkgs, ... }:
+
+let
   cfg = config.programs.river;
-in {
+
+  wayland-lib = import ./lib.nix { inherit lib; };
+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 = ''
+        If the package is not overridable with `xwaylandSupport`, then the module option
+        {option}`xwayland` will have no effect.
+
         Set to `null` to not add any River package to your path.
         This should be done if you want to use the Home Manager River module to install River.
       '';
+    } // {
+      apply = p: if p == null then null else
+        wayland-lib.genFinalPackage p {
+          xwaylandSupport = cfg.xwayland.enable;
+        };
     };
 
-    extraPackages = mkOption {
-      type = with types; listOf package;
-      default = with pkgs; [
-        swaylock
-        foot
-        dmenu
-      ];
-      defaultText = literalExpression ''
+    xwayland.enable = lib.mkEnableOption "XWayland" // { default = true; };
+
+    extraPackages = lib.mkOption {
+      type = with lib.types; listOf package;
+      default = with pkgs; [ swaylock foot dmenu ];
+      defaultText = lib.literalExpression ''
         with pkgs; [ swaylock foot dmenu ];
       '';
-      example = literalExpression ''
-        with pkgs; [
-          termite rofi light
-        ]
+      example = lib.literalExpression ''
+        with pkgs; [ termite rofi light ]
       '';
       description = ''
         Extra packages to be installed system wide. See
@@ -41,19 +44,22 @@ in {
     };
   };
 
-  config =
-    mkIf cfg.enable (mkMerge [
-      {
-        environment.systemPackages = optional (cfg.package != null) cfg.package ++ cfg.extraPackages;
+  config = lib.mkIf cfg.enable (lib.mkMerge [
+    {
+      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 = lib.optional (cfg.package != null) cfg.package;
 
-        # To make a river session available if a display manager like SDDM is enabled:
-        services.displayManager.sessionPackages = optionals (cfg.package != null) [ cfg.package ];
+      # https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1050913
+      xdg.portal.config.river.default = lib.mkDefault [ "wlr" "gtk" ];
+    }
 
-        # https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1050913
-        xdg.portal.config.river.default = mkDefault [ "wlr" "gtk" ];
-      }
-      (import ./wayland-session.nix { inherit lib pkgs; })
-    ]);
+    (import ./wayland-session.nix {
+      inherit lib pkgs;
+      enableXWayland = cfg.xwayland.enable;
+    })
+  ]);
 
   meta.maintainers = with lib.maintainers; [ GaetanLepage ];
 }
diff --git a/nixos/modules/programs/wayland/sway.nix b/nixos/modules/programs/wayland/sway.nix
index 348e1db7cdc1c..e3e32aa7a56ab 100644
--- a/nixos/modules/programs/wayland/sway.nix
+++ b/nixos/modules/programs/wayland/sway.nix
@@ -1,88 +1,53 @@
-{ config, pkgs, lib, ... }:
-
-with lib;
+{ config, lib, pkgs, ... }:
 
 let
   cfg = config.programs.sway;
 
-  wrapperOptions = types.submodule {
-    options =
-      let
-        mkWrapperFeature  = default: description: mkOption {
-          type = types.bool;
-          inherit default;
-          example = !default;
-          description = "Whether to make use of the ${description}";
-        };
-      in {
-        base = mkWrapperFeature true ''
-          base wrapper to execute extra session commands and prepend a
-          dbus-run-session to the sway command.
-        '';
-        gtk = mkWrapperFeature false ''
-          wrapGAppsHook wrapper to execute sway with required environment
-          variables for GTK applications.
-        '';
-    };
-  };
-
-  genFinalPackage = pkg:
-    let
-      expectedArgs = lib.naturalSort [
-        "extraSessionCommands"
-        "extraOptions"
-        "withBaseWrapper"
-        "withGtkWrapper"
-        "isNixOS"
-      ];
-      existedArgs = with lib;
-        naturalSort
-        (intersectLists expectedArgs (attrNames (functionArgs pkg.override)));
-    in if existedArgs != expectedArgs then
-      pkg
-    else
-      pkg.override {
-        extraSessionCommands = cfg.extraSessionCommands;
-        extraOptions = cfg.extraOptions;
-        withBaseWrapper = cfg.wrapperFeatures.base;
-        withGtkWrapper = cfg.wrapperFeatures.gtk;
-        isNixOS = true;
-      };
-in {
+  wayland-lib = import ./lib.nix { inherit lib; };
+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;
-      default = pkgs.sway;
-      apply = p: if p == null then null else genFinalPackage p;
-      defaultText = literalExpression "pkgs.sway";
-      description = ''
-        Sway package to use. If the package does not contain the override arguments
-        `extraSessionCommands`, `extraOptions`, `withBaseWrapper`, `withGtkWrapper`,
-        `isNixOS`, then the module options {option}`wrapperFeatures`,
-        {option}`wrapperFeatures` and {option}`wrapperFeatures` will have no effect.
-        Set to `null` to not add any Sway package to your path. This should be done if
-        you want to use the Home Manager Sway module to install Sway.
+    package = lib.mkPackageOption pkgs "sway" {
+      nullable = true;
+      extraDescription = ''
+        If the package is not overridable with `extraSessionCommands`, `extraOptions`,
+        `withBaseWrapper`, `withGtkWrapper`, `enableXWayland` and `isNixOS`,
+        then the module options {option}`wrapperFeatures`, {option}`extraSessionCommands`,
+        {option}`extraOptions` and {option}`xwayland` will have no effect.
+
+        Set to `null` to not add any Sway package to your path.
+        This should be done if you want to use the Home Manager Sway module to install Sway.
       '';
+    } // {
+      apply = p: if p == null then null else
+        wayland-lib.genFinalPackage p {
+          extraSessionCommands = cfg.extraSessionCommands;
+          extraOptions = cfg.extraOptions;
+          withBaseWrapper = cfg.wrapperFeatures.base;
+          withGtkWrapper = cfg.wrapperFeatures.gtk;
+          enableXWayland = cfg.xwayland.enable;
+          isNixOS = true;
+        };
     };
 
-    wrapperFeatures = mkOption {
-      type = wrapperOptions;
-      default = { };
-      example = { gtk = true; };
-      description = ''
-        Attribute set of features to enable in the wrapper.
-      '';
+    wrapperFeatures = {
+      base = lib.mkEnableOption ''
+        the base wrapper to execute extra session commands and prepend a
+        dbus-run-session to the sway command'' // { default = true; };
+      gtk = lib.mkEnableOption ''
+        the wrapGAppsHook wrapper to execute sway with required environment
+        variables for GTK applications'';
     };
 
-    extraSessionCommands = mkOption {
-      type = types.lines;
+    extraSessionCommands = lib.mkOption {
+      type = lib.types.lines;
       default = "";
       example = ''
         # SDL:
@@ -102,8 +67,8 @@ in {
       '';
     };
 
-    extraOptions = mkOption {
-      type = types.listOf types.str;
+    extraOptions = lib.mkOption {
+      type = lib.types.listOf lib.types.str;
       default = [];
       example = [
         "--verbose"
@@ -116,19 +81,16 @@ in {
       '';
     };
 
-    extraPackages = mkOption {
-      type = with types; listOf package;
-      default = with pkgs; [
-        swaylock swayidle foot dmenu wmenu
-      ];
-      defaultText = literalExpression ''
+    xwayland.enable = lib.mkEnableOption "XWayland" // { default = true; };
+
+    extraPackages = lib.mkOption {
+      type = with lib.types; listOf package;
+      default = with pkgs; [ swaylock swayidle foot dmenu wmenu ];
+      defaultText = lib.literalExpression ''
         with pkgs; [ swaylock swayidle foot dmenu wmenu ];
       '';
-      example = literalExpression ''
-        with pkgs; [
-          i3status i3status-rust
-          termite rofi light
-        ]
+      example = lib.literalExpression ''
+        with pkgs; [ i3status i3status-rust termite rofi light ]
       '';
       description = ''
         Extra packages to be installed system wide. See
@@ -137,46 +99,50 @@ in {
         for a list of useful software.
       '';
     };
-
   };
 
-  config = mkIf cfg.enable
-    (mkMerge [
-      {
-        assertions = [
-          {
-            assertion = cfg.extraSessionCommands != "" -> cfg.wrapperFeatures.base;
-            message = ''
-              The extraSessionCommands for Sway will not be run if
-              wrapperFeatures.base is disabled.
-            '';
-          }
-        ];
-
-        environment = {
-          systemPackages = optional (cfg.package != null) cfg.package ++ cfg.extraPackages;
-          # Needed for the default wallpaper:
-          pathsToLink = 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";
-          };
+  config = lib.mkIf cfg.enable (lib.mkMerge [
+    {
+      assertions = [
+        {
+          assertion = cfg.extraSessionCommands != "" -> cfg.wrapperFeatures.base;
+          message = ''
+            The extraSessionCommands for Sway will not be run if wrapperFeatures.base is disabled.
+          '';
+        }
+      ];
+
+      environment = {
+        systemPackages = lib.optional (cfg.package != null) cfg.package ++ cfg.extraPackages;
+
+        # Needed for the default wallpaper:
+        pathsToLink = lib.optional (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
+          '';
+        } // lib.optionalAttrs (cfg.package != null) {
+          "sway/config".source = lib.mkOptionDefault "${cfg.package}/etc/sway/config";
         };
+      };
+
+      programs.gnupg.agent.pinentryPackage = lib.mkDefault pkgs.pinentry-gnome3;
 
-        programs.gnupg.agent.pinentryPackage = lib.mkDefault pkgs.pinentry-gnome3;
+      # To make a Sway session available if a display manager like SDDM is enabled:
+      services.displayManager.sessionPackages = lib.optional (cfg.package != null) cfg.package;
 
-        # https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1050913
-        xdg.portal.config.sway.default = mkDefault [ "wlr" "gtk" ];
+      # https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1050913
+      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 ]; }
-      (import ./wayland-session.nix { inherit lib pkgs; })
-    ]);
+    (import ./wayland-session.nix {
+      inherit lib pkgs;
+      enableXWayland = cfg.xwayland.enable;
+    })
+  ]);
 
   meta.maintainers = with lib.maintainers; [ primeos colemickens ];
 }
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..09fb2a5f14b2e 100644
--- a/nixos/modules/programs/wayland/wayland-session.nix
+++ b/nixos/modules/programs/wayland/wayland-session.nix
@@ -1,23 +1,27 @@
-{ lib, pkgs, ... }: with lib; {
-    security = {
-      polkit.enable = true;
-      pam.services.swaylock = {};
-    };
+{
+  lib,
+  pkgs,
+  enableXWayland ? true,
+  enableWlrPortal ? true,
+}:
 
-    hardware.opengl.enable = mkDefault true;
-    fonts.enableDefaultPackages = mkDefault true;
+{
+  security = {
+    polkit.enable = true;
+    pam.services.swaylock = {};
+  };
 
-    programs = {
-      dconf.enable = mkDefault true;
-      xwayland.enable = mkDefault true;
-    };
+  hardware.graphics.enable = lib.mkDefault true;
+  fonts.enableDefaultPackages = lib.mkDefault true;
 
-    xdg.portal = {
-      enable = mkDefault true;
+  programs = {
+    dconf.enable = lib.mkDefault true;
+    xwayland.enable = lib.mkDefault enableXWayland;
+  };
 
-      extraPortals = [
-        # For screen sharing
-        pkgs.xdg-desktop-portal-wlr
-      ];
-    };
+  xdg.portal.wlr.enable = enableWlrPortal;
+
+  # Window manager only sessions (unlike DEs) don't handle XDG
+  # autostart files, so force them to run the service
+  services.xserver.desktopManager.runXdgAutostartIfNone = lib.mkDefault true;
 }
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..6bf18d4ebd89c 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" {
-        example = "xonsh.override { extraPackages = ps: [ ps.requests ]; }";
+      package = lib.mkPackageOption pkgs "xonsh" {
+        example = "xonsh.wrapper.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.
@@ -63,17 +61,14 @@ in
               aliases['ls'] = _ls_alias
           del _ls_alias
 
-
       ${cfg.config}
     '';
 
     environment.systemPackages = [ cfg.package ];
 
-    environment.shells =
-      [ "/run/current-system/sw/bin/xonsh"
-        "${cfg.package}/bin/xonsh"
-      ];
-
+    environment.shells = [
+      "/run/current-system/sw/bin/xonsh"
+      "${lib.getExe cfg.package}"
+    ];
   };
-
 }
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..643a5d369f3fc
--- /dev/null
+++ b/nixos/modules/programs/ydotool.nix
@@ -0,0 +1,92 @@
+{
+  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 {command}`ydotool` for members of
+      {option}`programs.ydotool.group`.
+    '';
+    group = lib.mkOption {
+      type = lib.types.str;
+      default = "ydotool";
+      description = ''
+        Group which users must be in to use {command}`ydotool`.
+      '';
+    };
+  };
+
+  config = let
+    runtimeDirectory = "ydotoold";
+  in lib.mkIf cfg.enable {
+    users.groups."${config.programs.ydotool.group}" = { };
+
+    systemd.services.ydotoold = {
+      description = "ydotoold - backend for ydotool";
+      wantedBy = [ "multi-user.target" ];
+      partOf = [ "multi-user.target" ];
+      serviceConfig = {
+        Group = config.programs.ydotool.group;
+        RuntimeDirectory = runtimeDirectory;
+        RuntimeDirectoryMode = "0750";
+        ExecStart = "${lib.getExe' pkgs.ydotool "ydotoold"} --socket-path=${config.environment.variables.YDOTOOL_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/${runtimeDirectory}/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/acme/default.nix b/nixos/modules/security/acme/default.nix
index 5ffafdc37fefb..83581d02840ed 100644
--- a/nixos/modules/security/acme/default.nix
+++ b/nixos/modules/security/acme/default.nix
@@ -545,7 +545,7 @@ let
       };
 
       server = mkOption {
-        type = types.str;
+        type = types.nullOr types.str;
         inherit (defaultAndText "server" "https://acme-v02.api.letsencrypt.org/directory") default defaultText;
         example = "https://acme-staging-v02.api.letsencrypt.org/directory";
         description = ''
diff --git a/nixos/modules/security/ipa.nix b/nixos/modules/security/ipa.nix
index 543b1abfa672c..e746ca75724a1 100644
--- a/nixos/modules/security/ipa.nix
+++ b/nixos/modules/security/ipa.nix
@@ -85,6 +85,18 @@ in {
         description = "Whether to cache credentials.";
       };
 
+      ipaHostname = mkOption {
+        type = types.str;
+        example = "myworkstation.example.com";
+        default = if config.networking.domain != null then config.networking.fqdn
+                  else "${config.networking.hostName}.${cfg.domain}";
+        defaultText = literalExpression ''
+          if config.networking.domain != null then config.networking.fqdn
+          else "''${networking.hostName}.''${security.ipa.domain}"
+        '';
+        description = "Fully-qualified hostname used to identify this host in the IPA domain.";
+      };
+
       ifpAllowedUids = mkOption {
         type = types.listOf types.str;
         default = ["root"];
@@ -218,7 +230,7 @@ in {
 
       ipa_domain = ${cfg.domain}
       ipa_server = _srv_, ${cfg.server}
-      ipa_hostname = ${config.networking.hostName}.${cfg.domain}
+      ipa_hostname = ${cfg.ipaHostname}
 
       cache_credentials = ${pyBool cfg.cacheCredentials}
       krb5_store_password_if_offline = ${pyBool cfg.offlinePasswords}
@@ -232,7 +244,6 @@ in {
       ldap_user_extra_attrs = mail:mail, sn:sn, givenname:givenname, telephoneNumber:telephoneNumber, lock:nsaccountlock
 
       [sssd]
-      debug_level = 65510
       services = nss, sudo, pam, ssh, ifp
       domains = ${cfg.domain}
 
@@ -244,7 +255,6 @@ in {
       pam_verbosity = 3
 
       [sudo]
-      debug_level = 65510
 
       [autofs]
 
diff --git a/nixos/modules/security/krb5/default.nix b/nixos/modules/security/krb5/default.nix
index 78426c07cbc98..6714c41d8a07c 100644
--- a/nixos/modules/security/krb5/default.nix
+++ b/nixos/modules/security/krb5/default.nix
@@ -77,8 +77,22 @@ in {
     };
   };
 
-  config = mkIf cfg.enable {
-    environment = {
+  config = {
+    assertions = mkIf (cfg.enable || config.services.kerberos_server.enable) [(let
+      implementation = cfg.package.passthru.implementation or "<NOT SET>";
+    in {
+      assertion = lib.elem implementation [ "krb5" "heimdal" ];
+      message = ''
+        `security.krb5.package` must be one of:
+
+          - krb5
+          - heimdal
+
+        Currently chosen implementation: ${implementation}
+      '';
+    })];
+
+    environment = mkIf cfg.enable {
       systemPackages = [ cfg.package ];
       etc."krb5.conf".source = format.generate "krb5.conf" cfg.settings;
     };
diff --git a/nixos/modules/security/krb5/krb5-conf-format.nix b/nixos/modules/security/krb5/krb5-conf-format.nix
index 5a6bbed9fd188..3e5e64ae0cb04 100644
--- a/nixos/modules/security/krb5/krb5-conf-format.nix
+++ b/nixos/modules/security/krb5/krb5-conf-format.nix
@@ -7,17 +7,61 @@
 let
   inherit (lib) boolToString concatMapStringsSep concatStringsSep filter
     isAttrs isBool isList mapAttrsToList mkOption singleton splitString;
-  inherit (lib.types) attrsOf bool coercedTo either int listOf oneOf path
-    str submodule;
+  inherit (lib.types) attrsOf bool coercedTo either enum int listOf oneOf
+    path str submodule;
 in
-{ }: {
-  type = let
-    section = attrsOf relation;
-    relation = either (attrsOf value) value;
+{
+  enableKdcACLEntries ? false
+}: rec {
+  sectionType = let
+    relation = oneOf [
+      (listOf (attrsOf value))
+      (attrsOf value)
+      value
+    ];
     value = either (listOf atom) atom;
     atom = oneOf [int str bool];
+  in attrsOf relation;
+
+  type = let
+    aclEntry = submodule {
+      options = {
+        principal = mkOption {
+          type = str;
+          description = "Which principal the rule applies to";
+        };
+        access = mkOption {
+          type = either
+            (listOf (enum ["add" "cpw" "delete" "get" "list" "modify"]))
+            (enum ["all"]);
+          default = "all";
+          description = "The changes the principal is allowed to make.";
+        };
+        target = mkOption {
+          type = str;
+          default = "*";
+          description = "The principals that 'access' applies to.";
+        };
+      };
+    };
+
+    realm = submodule ({ name, ... }: {
+      freeformType = sectionType;
+      options = {
+        acl = mkOption {
+          type = listOf aclEntry;
+          default = [
+            { principal = "*/admin"; access = "all"; }
+            { principal = "admin"; access = "all"; }
+          ];
+          description = ''
+            The privileges granted to a user.
+          '';
+        };
+      };
+    });
   in submodule {
-    freeformType = attrsOf section;
+    freeformType = attrsOf sectionType;
     options = {
       include = mkOption {
         default = [ ];
@@ -40,7 +84,17 @@ in
         '';
         type = coercedTo path singleton (listOf path);
       };
-    };
+
+    }
+    //
+    (lib.optionalAttrs enableKdcACLEntries {
+      realms = mkOption {
+        type = attrsOf realm;
+        description = ''
+          The realm(s) to serve keys for.
+        '';
+      };
+    });
   };
 
   generate = let
@@ -71,6 +125,9 @@ in
         ${name} = {
         ${indent (concatStringsSep "\n" (mapAttrsToList formatValue relation))}
         }''
+      else if isList relation
+      then
+        concatMapStringsSep "\n" (formatRelation name) relation
       else formatValue name relation;
 
     formatValue = name: value:
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/docuum.nix b/nixos/modules/services/admin/docuum.nix
index 6f6cd4e027337..51a21740b276a 100644
--- a/nixos/modules/services/admin/docuum.nix
+++ b/nixos/modules/services/admin/docuum.nix
@@ -2,7 +2,7 @@
 
 let
   cfg = config.services.docuum;
-  inherit (lib) mkIf mkEnableOption mkOption getExe types;
+  inherit (lib) mkIf mkEnableOption mkOption getExe types optionals concatMap;
 in
 {
   options.services.docuum = {
@@ -14,6 +14,27 @@ in
       default = "10 GB";
       example = "50%";
     };
+
+    minAge = mkOption {
+      description = "Sets the minimum age of images to be considered for deletion.";
+      type = types.nullOr types.str;
+      default = null;
+      example = "1d";
+    };
+
+    keep = mkOption {
+      description = "Prevents deletion of images for which repository:tag matches the specified regex.";
+      type = types.listOf types.str;
+      default = [];
+      example = [ "^my-image" ];
+    };
+
+    deletionChunkSize = mkOption {
+      description = "Removes specified quantity of images at a time.";
+      type = types.int;
+      default = 1;
+      example = 10;
+    };
   };
 
   config = mkIf cfg.enable {
@@ -35,10 +56,13 @@ in
         DynamicUser = true;
         StateDirectory = "docuum";
         SupplementaryGroups = [ "docker" ];
-        ExecStart = utils.escapeSystemdExecArgs [
+        ExecStart = utils.escapeSystemdExecArgs ([
           (getExe pkgs.docuum)
           "--threshold" cfg.threshold
-        ];
+          "--deletion-chunk-size" cfg.deletionChunkSize
+        ] ++ (concatMap (keep: [ "--keep" keep ]) cfg.keep)
+          ++ (optionals (cfg.minAge != null) [ "--min-age" cfg.minAge ])
+        );
       };
     };
   };
diff --git a/nixos/modules/services/admin/meshcentral.nix b/nixos/modules/services/admin/meshcentral.nix
index 25779e01123ec..6e0801e1c0894 100644
--- a/nixos/modules/services/admin/meshcentral.nix
+++ b/nixos/modules/services/admin/meshcentral.nix
@@ -42,5 +42,5 @@ in with lib; {
       };
     };
   };
-  meta.maintainers = [ maintainers.lheckemann ];
+  meta.maintainers = [ ];
 }
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/alsa.nix b/nixos/modules/services/audio/alsa.nix
index e53da4b64e7bc..b002cb1274ac3 100644
--- a/nixos/modules/services/audio/alsa.nix
+++ b/nixos/modules/services/audio/alsa.nix
@@ -106,7 +106,8 @@ in
         serviceConfig = {
           Type = "oneshot";
           RemainAfterExit = true;
-          ExecStart = "${pkgs.coreutils}/bin/mkdir -p /var/lib/alsa";
+          ExecStartPre = "${pkgs.coreutils}/bin/mkdir -p /var/lib/alsa";
+          ExecStart = "${alsa-utils}/sbin/alsactl restore --ignore";
           ExecStop = "${alsa-utils}/sbin/alsactl store --ignore";
         };
       };
diff --git a/nixos/modules/services/audio/mopidy.nix b/nixos/modules/services/audio/mopidy.nix
index 1d6c45b64a16c..198ca74359dc1 100644
--- a/nixos/modules/services/audio/mopidy.nix
+++ b/nixos/modules/services/audio/mopidy.nix
@@ -78,6 +78,7 @@ in {
     systemd.services.mopidy = {
       wantedBy = [ "multi-user.target" ];
       after = [ "network-online.target" "sound.target" ];
+      wants = [ "network-online.target" ];
       description = "mopidy music player daemon";
       serviceConfig = {
         ExecStart = "${mopidyEnv}/bin/mopidy --config ${concatStringsSep ":" ([mopidyConf] ++ cfg.extraConfigFiles)}";
diff --git a/nixos/modules/services/audio/navidrome.nix b/nixos/modules/services/audio/navidrome.nix
index a5a7e805e3d61..06d2d174a4df3 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; [ fsnkty ];
 }
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/backup/restic.nix b/nixos/modules/services/backup/restic.nix
index 8b56636c79695..8be2649189b95 100644
--- a/nixos/modules/services/backup/restic.nix
+++ b/nixos/modules/services/backup/restic.nix
@@ -11,7 +11,7 @@ in
     description = ''
       Periodic backups to create with Restic.
     '';
-    type = types.attrsOf (types.submodule ({ config, name, ... }: {
+    type = types.attrsOf (types.submodule ({ name, ... }: {
       options = {
         passwordFile = mkOption {
           type = types.str;
@@ -206,12 +206,19 @@ in
           ];
         };
 
+        runCheck = mkOption {
+          type = types.bool;
+          default = (builtins.length config.services.restic.backups.${name}.checkOpts > 0);
+          defaultText = literalExpression ''builtins.length config.services.backups.${name}.checkOpts > 0'';
+          description = "Whether to run the `check` command with the provided `checkOpts` options.";
+          example = true;
+        };
+
         checkOpts = mkOption {
           type = types.listOf types.str;
           default = [ ];
           description = ''
-            A list of options for 'restic check', which is run after
-            pruning.
+            A list of options for 'restic check'.
           '';
           example = [
             "--with-cache"
@@ -298,7 +305,9 @@ in
             doBackup = (backup.dynamicFilesFrom != null) || (backup.paths != null && backup.paths != []);
             pruneCmd = optionals (builtins.length backup.pruneOpts > 0) [
               (resticCmd + " forget --prune " + (concatStringsSep " " backup.pruneOpts))
-              (resticCmd + " check " + (concatStringsSep " " backup.checkOpts))
+            ];
+            checkCmd = optionals backup.runCheck [
+                (resticCmd + " check " + (concatStringsSep " " backup.checkOpts))
             ];
             # Helper functions for rclone remotes
             rcloneRemoteName = builtins.elemAt (splitString ":" backup.repository) 1;
@@ -331,7 +340,7 @@ in
             serviceConfig = {
               Type = "oneshot";
               ExecStart = (optionals doBackup [ "${resticCmd} backup ${concatStringsSep " " (backup.extraBackupArgs ++ excludeFlags)} --files-from=${filesFromTmpFile}" ])
-                ++ pruneCmd;
+                ++ pruneCmd ++ checkCmd;
               User = backup.user;
               RuntimeDirectory = "restic-backups-${name}";
               CacheDirectory = "restic-backups-${name}";
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/cluster/kubernetes/default.nix b/nixos/modules/services/cluster/kubernetes/default.nix
index 89bbedf4d0401..01760ffbc72da 100644
--- a/nixos/modules/services/cluster/kubernetes/default.nix
+++ b/nixos/modules/services/cluster/kubernetes/default.nix
@@ -261,7 +261,7 @@ in {
           name = "service-account";
           CN = "system:service-account-signer";
           action = ''
-            systemctl reload \
+            systemctl restart \
               kube-apiserver.service \
               kube-controller-manager.service
           '';
diff --git a/nixos/modules/services/cluster/rke2/default.nix b/nixos/modules/services/cluster/rke2/default.nix
new file mode 100644
index 0000000000000..9ddbd299fdf8d
--- /dev/null
+++ b/nixos/modules/services/cluster/rke2/default.nix
@@ -0,0 +1,311 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+let
+  cfg = config.services.rke2;
+in
+{
+  imports = [ ];
+
+  options.services.rke2 = {
+    enable = mkEnableOption "rke2";
+
+    package = mkPackageOption pkgs "rke2" { };
+
+    role = mkOption {
+      type = types.enum [ "server" "agent" ];
+      description = ''
+        Whether rke2 should run as a server or agent.
+
+        If it's a server:
+
+        - By default it also runs workloads as an agent.
+        - any optionals is allowed.
+
+        If it's an agent:
+
+        - `serverAddr` is required.
+        - `token` or `tokenFile` is required.
+        - `agentToken` or `agentTokenFile` or `disable` or `cni` are not allowed.
+      '';
+      default = "server";
+    };
+
+    configPath = mkOption {
+      type = types.path;
+      description = "Load configuration from FILE.";
+      default = "/etc/rancher/rke2/config.yaml";
+    };
+
+    debug = mkOption {
+      type = types.bool;
+      description = "Turn on debug logs.";
+      default = false;
+    };
+
+    dataDir = mkOption {
+      type = types.path;
+      description = "The folder to hold state in.";
+      default = "/var/lib/rancher/rke2";
+    };
+
+    token = mkOption {
+      type = types.str;
+      description = ''
+        Shared secret used to join a server or agent to a cluster.
+
+        > WARNING: This option will expose store your token unencrypted world-readable in the nix store.
+        If this is undesired use the `tokenFile` option instead.
+      '';
+      default = "";
+    };
+
+    tokenFile = mkOption {
+      type = types.nullOr types.path;
+      description = "File path containing rke2 token to use when connecting to the server.";
+      default = null;
+    };
+
+    disable = mkOption {
+      type = types.listOf types.str;
+      description = "Do not deploy packaged components and delete any deployed components.";
+      default = [ ];
+    };
+
+    nodeName = mkOption {
+      type = types.nullOr types.str;
+      description = "Node name.";
+      default = null;
+    };
+
+    nodeLabel = mkOption {
+      type = types.listOf types.str;
+      description = "Registering and starting kubelet with set of labels.";
+      default = [ ];
+    };
+
+    nodeTaint = mkOption {
+      type = types.listOf types.str;
+      description = "Registering kubelet with set of taints.";
+      default = [ ];
+    };
+
+    nodeIP = mkOption {
+      type = types.nullOr types.str;
+      description = "IPv4/IPv6 addresses to advertise for node.";
+      default = null;
+    };
+
+    agentToken = mkOption {
+      type = types.str;
+      description = ''
+        Shared secret used to join agents to the cluster, but not servers.
+
+        > **WARNING**: This option will expose store your token unencrypted world-readable in the nix store.
+        If this is undesired use the `agentTokenFile` option instead.
+      '';
+      default = "";
+    };
+
+    agentTokenFile = mkOption {
+      type = types.nullOr types.path;
+      description = "File path containing rke2 agent token to use when connecting to the server.";
+      default = null;
+    };
+
+    serverAddr = mkOption {
+      type = types.str;
+      description = "The rke2 server to connect to, used to join a cluster.";
+      example = "https://10.0.0.10:6443";
+      default = "";
+    };
+
+    selinux = mkOption {
+      type = types.bool;
+      description = "Enable SELinux in containerd.";
+      default = false;
+    };
+
+    cni = mkOption {
+      type = types.enum [ "none" "canal" "cilium" "calico" "flannel" ];
+      description = ''
+        CNI Plugins to deploy, one of `none`, `calico`, `canal`, `cilium` or `flannel`.
+
+        All CNI plugins get installed via a helm chart after the main components are up and running
+        and can be [customized by modifying the helm chart options](https://docs.rke2.io/helm).
+
+        [Learn more about RKE2 and CNI plugins](https://docs.rke2.io/networking/basic_network_options)
+
+        > **WARNING**: Flannel support in RKE2 is currently experimental.
+      '';
+      default = "canal";
+    };
+
+    cisHardening = mkOption {
+      type = types.bool;
+      description = ''
+        Enable CIS Hardening for RKE2.
+
+        It will set the configurations and controls required to address Kubernetes benchmark controls
+        from the Center for Internet Security (CIS).
+
+        Learn more about [CIS Hardening for RKE2](https://docs.rke2.io/security/hardening_guide).
+
+        > **NOTICE**:
+        >
+        > You may need restart the `systemd-sysctl` muaually by:
+        >
+        > ```shell
+        > sudo systemctl restart systemd-sysctl
+        > ```
+      '';
+      default = false;
+    };
+
+    extraFlags = mkOption {
+      type = types.listOf types.str;
+      description = ''
+        Extra flags to pass to the rke2 service/agent.
+
+        Here you can find all the available flags:
+
+        - [Server Configuration Reference](https://docs.rke2.io/reference/server_config)
+        - [Agent Configuration Reference](https://docs.rke2.io/reference/linux_agent_config)
+      '';
+      example = [ "--disable-kube-proxy" "--cluster-cidr=10.24.0.0/16" ];
+      default = [ ];
+    };
+
+    environmentVars = mkOption {
+      type = types.attrsOf types.str;
+      description = ''
+        Environment variables for configuring the rke2 service/agent.
+
+        Here you can find all the available environment variables:
+
+        - [Server Configuration Reference](https://docs.rke2.io/reference/server_config)
+        - [Agent Configuration Reference](https://docs.rke2.io/reference/linux_agent_config)
+
+        Besides the options above, you can also active environment variables by edit/create those files:
+
+        - `/etc/default/rke2`
+        - `/etc/sysconfig/rke2`
+        - `/usr/local/lib/systemd/system/rke2.env`
+      '';
+      # See: https://github.com/rancher/rke2/blob/master/bundle/lib/systemd/system/rke2-server.env#L1
+      default = {
+        HOME = "/root";
+      };
+    };
+  };
+
+  config = mkIf cfg.enable {
+    assertions = [
+      {
+        assertion = cfg.role == "agent" -> (builtins.pathExists cfg.configPath || cfg.serverAddr != "");
+        message = "serverAddr or configPath (with 'server' key) should be set if role is 'agent'";
+      }
+      {
+        assertion = cfg.role == "agent" -> (builtins.pathExists cfg.configPath || cfg.tokenFile != null || cfg.token != "");
+        message = "token or tokenFile or configPath (with 'token' or 'token-file' keys) should be set if role is 'agent'";
+      }
+      {
+        assertion = cfg.role == "agent" -> ! (cfg.agentTokenFile != null || cfg.agentToken != "");
+        message = "agentToken or agentTokenFile should be set if role is 'agent'";
+      }
+      {
+        assertion = cfg.role == "agent" -> ! (cfg.disable != [ ]);
+        message = "disable should not be set if role is 'agent'";
+      }
+      {
+        assertion = cfg.role == "agent" -> ! (cfg.cni != "canal");
+        message = "cni should not be set if role is 'agent'";
+      }
+    ];
+
+    environment.systemPackages = [ config.services.rke2.package ];
+    # To configure NetworkManager to ignore calico/flannel related network interfaces.
+    # See: https://docs.rke2.io/known_issues#networkmanager
+    environment.etc."NetworkManager/conf.d/rke2-canal.conf" = {
+      enable = config.networking.networkmanager.enable;
+      text = ''
+        [keyfile]
+        unmanaged-devices=interface-name:cali*;interface-name:flannel*
+      '';
+    };
+    # See: https://docs.rke2.io/security/hardening_guide#set-kernel-parameters
+    boot.kernel.sysctl = mkIf cfg.cisHardening {
+      "vm.panic_on_oom" = 0;
+      "vm.overcommit_memory" = 1;
+      "kernel.panic" = 10;
+      "kernel.panic_on_oops" = 1;
+    };
+
+    systemd.services.rke2 = {
+      description = "Rancher Kubernetes Engine v2";
+      documentation = [ "https://github.com/rancher/rke2#readme" ];
+      after = [ "network-online.target" ];
+      wants = [ "network-online.target" ];
+      wantedBy = [ "multi-user.target" ];
+      serviceConfig = {
+        Type = if cfg.role == "agent" then "exec" else "notify";
+        EnvironmentFile = [
+          "-/etc/default/%N"
+          "-/etc/sysconfig/%N"
+          "-/usr/local/lib/systemd/system/%N.env"
+        ];
+        Environment = mapAttrsToList (k: v: "${k}=${v}") cfg.environmentVars;
+        KillMode = "process";
+        Delegate = "yes";
+        LimitNOFILE = 1048576;
+        LimitNPROC = "infinity";
+        LimitCORE = "infinity";
+        TasksMax = "infinity";
+        TimeoutStartSec = 0;
+        Restart = "always";
+        RestartSec = "5s";
+        ExecStartPre = [
+          # There is a conflict between RKE2 and `nm-cloud-setup.service`. This service add a routing table that
+          # interfere with the CNI plugin's configuration. This script checks if the service is enabled and if so,
+          # failed the RKE2 start.
+          # See: https://github.com/rancher/rke2/issues/1053
+          (pkgs.writeScript "check-nm-cloud-setup.sh" ''
+            #! ${pkgs.runtimeShell}
+            set -x
+            ! /run/current-system/systemd/bin/systemctl is-enabled --quiet nm-cloud-setup.service
+          '')
+          "-${pkgs.kmod}/bin/modprobe br_netfilter"
+          "-${pkgs.kmod}/bin/modprobe overlay"
+        ];
+        ExecStart = "${cfg.package}/bin/rke2 '${cfg.role}' ${escapeShellArgs (
+             (optional (cfg.configPath != "/etc/rancher/rke2/config.yaml") "--config=${cfg.configPath}")
+          ++ (optional cfg.debug "--debug")
+          ++ (optional (cfg.dataDir != "/var/lib/rancher/rke2") "--data-dir=${cfg.dataDir}")
+          ++ (optional (cfg.token != "") "--token=${cfg.token}")
+          ++ (optional (cfg.tokenFile != null) "--token-file=${cfg.tokenFile}")
+          ++ (optionals (cfg.role == "server" && cfg.disable != [ ]) (map (d: "--disable=${d}") cfg.disable))
+          ++ (optional (cfg.nodeName != null) "--node-name=${cfg.nodeName}")
+          ++ (optionals (cfg.nodeLabel != [ ]) (map (l: "--node-label=${l}") cfg.nodeLabel))
+          ++ (optionals (cfg.nodeTaint != [ ]) (map (t: "--node-taint=${t}") cfg.nodeTaint))
+          ++ (optional (cfg.nodeIP != null) "--node-ip=${cfg.nodeIP}")
+          ++ (optional (cfg.role == "server" && cfg.agentToken != "") "--agent-token=${cfg.agentToken}")
+          ++ (optional (cfg.role == "server" && cfg.agentTokenFile != null) "--agent-token-file=${cfg.agentTokenFile}")
+          ++ (optional (cfg.serverAddr != "") "--server=${cfg.serverAddr}")
+          ++ (optional cfg.selinux "--selinux")
+          ++ (optional (cfg.role == "server" && cfg.cni != "canal") "--cni=${cfg.cni}")
+          ++ (optional cfg.cisHardening "--profile=${if cfg.package.version >= "1.25" then "cis-1.23" else "cis-1.6"}")
+          ++ cfg.extraFlags
+        )}";
+        ExecStopPost = let
+          killProcess = pkgs.writeScript "kill-process.sh" ''
+            #! ${pkgs.runtimeShell}
+            /run/current-system/systemd/bin/systemd-cgls /system.slice/$1 | \
+            ${pkgs.gnugrep}/bin/grep -Eo '[0-9]+ (containerd|kubelet)' | \
+            ${pkgs.gawk}/bin/awk '{print $1}' | \
+            ${pkgs.findutils}/bin/xargs -r ${pkgs.util-linux}/bin/kill
+          '';
+        in "-${killProcess} %n";
+      };
+    };
+  };
+}
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/continuous-integration/jenkins/default.nix b/nixos/modules/services/continuous-integration/jenkins/default.nix
index 7b671ba9ed9de..a23120739b7fa 100644
--- a/nixos/modules/services/continuous-integration/jenkins/default.nix
+++ b/nixos/modules/services/continuous-integration/jenkins/default.nix
@@ -237,6 +237,8 @@ in {
       serviceConfig = {
         User = cfg.user;
         StateDirectory = mkIf (hasPrefix "/var/lib/jenkins" cfg.home) "jenkins";
+        # For (possible) socket use
+        RuntimeDirectory = "jenkins";
       };
     };
   };
diff --git a/nixos/modules/services/databases/postgresql.md b/nixos/modules/services/databases/postgresql.md
index 8a587832cd8c0..e76f127335c7b 100644
--- a/nixos/modules/services/databases/postgresql.md
+++ b/nixos/modules/services/databases/postgresql.md
@@ -244,6 +244,27 @@ The upgrade process is:
      $ ./delete_old_cluster.sh
      ```
 
+## Versioning and End-of-Life {#module-services-postgres-versioning}
+
+PostgreSQL's versioning policy is described [here](https://www.postgresql.org/support/versioning/). TLDR:
+
+- Each major version is supported for 5 years.
+- Every three months there will be a new minor release, containing bug and security fixes.
+- For criticial/security fixes there could be more minor releases inbetween. This happens *very* infrequently.
+- After five years, a final minor version is released. This usually happens in early November.
+- After that a version is considered end-of-life (EOL).
+- Around February each year is the first time an EOL-release will not have received regular updates anymore.
+
+Technically, we'd not want to have EOL'ed packages in a stable NixOS release, which is to be supported until one month after the previous release. Thus, with NixOS' release schedule in May and November, the oldest PostgreSQL version in nixpkgs would have to be supported until December. It could be argued that a soon-to-be-EOL-ed version should thus be removed in May for the .05 release already. But since new security vulnerabilities are first disclosed in Februrary of the following year, we agreed on keeping the oldest PostgreSQL major version around one more cycle in [#310580](https://github.com/NixOS/nixpkgs/pull/310580#discussion_r1597284693).
+
+Thus:
+- In September/October the new major version will be released and added to nixos-unstable.
+- In November the last minor version for the oldest major will be released.
+- Both the current stable .05 release and nixos-unstable should be updated to the latest minor.
+- In November, before branch-off for the .11 release, the EOL-ed major will be removed from nixos-unstable.
+
+This leaves a small gap of a couple of weeks after the latest minor release and the end of our support window for the .05 release, in which there could be an emergency release to other major versions of PostgreSQL - but not the oldest major we have in that branch. In that case: If we can't trivially patch the issue, we will mark the package/version as insecure **immediately**.
+
 ## Options {#module-services-postgres-options}
 
 A complete list of options for the PostgreSQL module may be found [here](#opt-services.postgresql.enable).
diff --git a/nixos/modules/services/desktop-managers/lomiri.nix b/nixos/modules/services/desktop-managers/lomiri.nix
index e11867b691071..0b871aa38183e 100644
--- a/nixos/modules/services/desktop-managers/lomiri.nix
+++ b/nixos/modules/services/desktop-managers/lomiri.nix
@@ -22,6 +22,7 @@ in {
         libusermetrics
         lomiri
         lomiri-download-manager
+        lomiri-filemanager-app
         lomiri-schemas # exposes some required dbus interfaces
         lomiri-session # wrappers to properly launch the session
         lomiri-sounds
@@ -34,10 +35,15 @@ in {
         morph-browser
         qtmir # not having its desktop file for Xwayland available causes any X11 application to crash the session
         suru-icon-theme
-        telephony-service
+        # telephony-service # currently broken: https://github.com/NixOS/nixpkgs/pull/314043
       ]);
+      variables = {
+        # To override the keyboard layouts in Lomiri
+        NIXOS_XKB_LAYOUTS = config.services.xserver.xkb.layout;
+      };
     };
 
+    hardware.pulseaudio.enable = lib.mkDefault true;
     networking.networkmanager.enable = lib.mkDefault true;
 
     systemd.packages = with pkgs.lomiri; [
@@ -57,7 +63,7 @@ in {
     ];
 
     # Copy-pasted basic stuff
-    hardware.opengl.enable = lib.mkDefault true;
+    hardware.graphics.enable = lib.mkDefault true;
     fonts.enableDefaultPackages = lib.mkDefault true;
     programs.dconf.enable = lib.mkDefault true;
 
@@ -71,10 +77,14 @@ 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
+        # telephony-service # currently broken: https://github.com/NixOS/nixpkgs/pull/314043
       ] ++ lib.optionals config.networking.networkmanager.enable [
         lomiri-indicator-network
       ]);
diff --git a/nixos/modules/services/desktop-managers/plasma6.nix b/nixos/modules/services/desktop-managers/plasma6.nix
index 08507b4d370a7..796e24286f9e4 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,44 +121,32 @@ 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
         okular
         kate
         khelpcenter
-        print-manager
+        dolphin
+        dolphin-plugins
+        spectacle
+        ffmpegthumbs
+        krdp
       ];
     in
       requiredPackages
@@ -183,12 +168,13 @@ in {
         )
         kio-extras-kf5
       ]
-      # Optional hardware support features
+      # Optional and hardware support features
       ++ lib.optionals config.hardware.bluetooth.enable [bluedevil bluez-qt pkgs.openobex pkgs.obexftp]
       ++ lib.optional config.networking.networkmanager.enable plasma-nm
       ++ lib.optional config.hardware.pulseaudio.enable plasma-pa
       ++ lib.optional config.services.pipewire.pulse.enable plasma-pa
       ++ lib.optional config.powerManagement.enable powerdevil
+      ++ lib.optional config.services.printing.enable print-manager
       ++ lib.optional config.services.colord.enable colord-kde
       ++ lib.optional config.services.hardware.bolt.enable plasma-thunderbolt
       ++ lib.optional config.services.samba.enable kdenetwork-filesharing
@@ -217,7 +203,7 @@ in {
     environment.sessionVariables.KPACKAGE_DEP_RESOLVERS_PATH = "${kdePackages.frameworkintegration.out}/libexec/kf6/kpackagehandlers";
 
     # Enable GTK applications to load SVG icons
-    services.xserver.gdk-pixbuf.modulePackages = [pkgs.librsvg];
+    programs.gdk-pixbuf.modulePackages = [pkgs.librsvg];
 
     fonts.packages = [cfg.notoPackage pkgs.hack-font];
     fonts.fontconfig.defaultFonts = {
@@ -278,14 +264,26 @@ in {
         enable = true;
         package = kdePackages.kwallet-pam;
       };
-      kde.kwallet = {
-        enable = true;
-        package = kdePackages.kwallet-pam;
+      kde = {
+        allowNullPassword = true;
+        kwallet = {
+          enable = true;
+          package = kdePackages.kwallet-pam;
+        };
       };
       kde-fingerprint = lib.mkIf config.services.fprintd.enable { fprintAuth = true; };
       kde-smartcard = lib.mkIf config.security.pam.p11.enable { p11Auth = true; };
     };
 
+    security.wrappers = {
+      kwin_wayland = {
+        owner = "root";
+        group = "root";
+        capabilities = "cap_sys_nice+ep";
+        source = "${lib.getBin pkgs.kdePackages.kwin}/bin/kwin_wayland";
+      };
+    };
+
     programs.dconf.enable = true;
 
     programs.firefox.nativeMessagingHosts.packages = [kdePackages.plasma-browser-integration];
diff --git a/nixos/modules/services/desktops/espanso.nix b/nixos/modules/services/desktops/espanso.nix
index 4ef6724dda0a0..a6b8a078247b1 100644
--- a/nixos/modules/services/desktops/espanso.nix
+++ b/nixos/modules/services/desktops/espanso.nix
@@ -6,19 +6,24 @@ 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 {
     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/desktops/gnome/gnome-keyring.nix b/nixos/modules/services/desktops/gnome/gnome-keyring.nix
index 79bce0ade2fc5..02b198fd81cb9 100644
--- a/nixos/modules/services/desktops/gnome/gnome-keyring.nix
+++ b/nixos/modules/services/desktops/gnome/gnome-keyring.nix
@@ -1,45 +1,52 @@
 # GNOME Keyring daemon.
 
-{ config, pkgs, lib, ... }:
-
+{
+  config,
+  pkgs,
+  lib,
+  ...
+}:
+let
+  cfg = config.services.gnome.gnome-keyring;
+in
 {
 
   meta = {
     maintainers = lib.teams.gnome.members;
   };
 
-  ###### interface
-
   options = {
-
     services.gnome.gnome-keyring = {
-
-      enable = lib.mkOption {
-        type = lib.types.bool;
-        default = false;
-        description = ''
-          Whether to enable GNOME Keyring daemon, a service designed to
-          take care of the user's security credentials,
-          such as user names and passwords.
-        '';
-      };
-
+      enable = lib.mkEnableOption ''
+        GNOME Keyring daemon, a service designed to
+        take care of the user's security credentials,
+        such as user names and passwords
+      '';
     };
-
   };
 
-
-  ###### implementation
-
-  config = lib.mkIf config.services.gnome.gnome-keyring.enable {
-
+  config = lib.mkIf cfg.enable {
     environment.systemPackages = [ pkgs.gnome.gnome-keyring ];
 
-    services.dbus.packages = [ pkgs.gnome.gnome-keyring pkgs.gcr ];
+    services.dbus.packages = [
+      pkgs.gnome.gnome-keyring
+      pkgs.gcr
+    ];
 
     xdg.portal.extraPortals = [ pkgs.gnome.gnome-keyring ];
 
-    security.pam.services.login.enableGnomeKeyring = true;
+    security.pam.services = lib.mkMerge [
+      {
+        login.enableGnomeKeyring = true;
+      }
+      (lib.mkIf config.services.xserver.displayManager.gdm.enable {
+        gdm-password.enableGnomeKeyring = true;
+        gdm-autologin.enableGnomeKeyring = true;
+      })
+      (lib.mkIf (config.services.xserver.displayManager.gdm.enable && config.services.fprintd.enable) {
+        gdm-fingerprint.enableGnomeKeyring = true;
+      })
+    ];
 
     security.wrappers.gnome-keyring-daemon = {
       owner = "root";
@@ -47,7 +54,5 @@
       capabilities = "cap_ipc_lock=ep";
       source = "${pkgs.gnome.gnome-keyring}/bin/gnome-keyring-daemon";
     };
-
   };
-
 }
diff --git a/nixos/modules/services/display-managers/default.nix b/nixos/modules/services/display-managers/default.nix
index 005ae8f1c8a58..9a7bd6c84b15b 100644
--- a/nixos/modules/services/display-managers/default.nix
+++ b/nixos/modules/services/display-managers/default.nix
@@ -113,10 +113,10 @@ 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.displayManager.sessionData.sessionNames}
+                  ${lib.concatStringsSep "\n  " cfg.sessionData.sessionNames}
               '';
         };
         default = null;
@@ -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
@@ -212,9 +212,7 @@ in
       after = [ "acpid.service" "systemd-logind.service" "systemd-user-sessions.service" ];
       restartIfChanged = false;
 
-      environment = lib.optionalAttrs config.hardware.opengl.setLdLibraryPath {
-        LD_LIBRARY_PATH = lib.makeLibraryPath [ pkgs.addOpenGLRunpath.driverLink ];
-      } // cfg.environment;
+      environment = cfg.environment;
 
       preStart = cfg.preStart;
       script = lib.mkIf (config.systemd.services.display-manager.enable == true) cfg.execCmd;
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/editors/emacs.nix b/nixos/modules/services/editors/emacs.nix
index 35f257cee1e3a..98d8506e67278 100644
--- a/nixos/modules/services/editors/emacs.nix
+++ b/nixos/modules/services/editors/emacs.nix
@@ -6,8 +6,7 @@ let
 
   cfg = config.services.emacs;
 
-  editorScript = pkgs.writeScriptBin "emacseditor" ''
-    #!${pkgs.runtimeShell}
+  editorScript = pkgs.writeShellScriptBin "emacseditor" ''
     if [ -z "$1" ]; then
       exec ${cfg.package}/bin/emacsclient --create-frame --alternate-editor ${cfg.package}/bin/emacs
     else
@@ -70,8 +69,8 @@ in
       description = "Emacs: the extensible, self-documenting text editor";
 
       serviceConfig = {
-        Type = "forking";
-        ExecStart = "${pkgs.bash}/bin/bash -c 'source ${config.system.build.setEnvironment}; exec ${cfg.package}/bin/emacs --daemon'";
+        Type = "notify";
+        ExecStart = "${pkgs.runtimeShell} -c 'source ${config.system.build.setEnvironment}; exec ${cfg.package}/bin/emacs --fg-daemon'";
         ExecStop = "${cfg.package}/bin/emacsclient --eval (kill-emacs)";
         Restart = "always";
       };
diff --git a/nixos/modules/services/games/archisteamfarm.nix b/nixos/modules/services/games/archisteamfarm.nix
index 33898f8387e99..7062332db34ab 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 = {
@@ -193,7 +196,7 @@ in
             Group = "archisteamfarm";
             WorkingDirectory = cfg.dataDir;
             Type = "simple";
-            ExecStart = "${lib.getExe cfg.package} --no-restart --process-required --service --system-required --path ${cfg.dataDir}";
+            ExecStart = "${lib.getExe cfg.package} --no-restart --service --system-required --path ${cfg.dataDir}";
             Restart = "always";
 
             # copied from the default systemd service at
diff --git a/nixos/modules/services/hardware/amdgpu.nix b/nixos/modules/services/hardware/amdgpu.nix
new file mode 100644
index 0000000000000..1952be08a17cf
--- /dev/null
+++ b/nixos/modules/services/hardware/amdgpu.nix
@@ -0,0 +1,43 @@
+{ config, lib, pkgs, ... }:
+
+let
+  cfg = config.hardware.amdgpu;
+in {
+  options.hardware.amdgpu = {
+    legacySupport.enable = lib.mkEnableOption ''
+      using `amdgpu` kernel driver instead of `radeon` for Southern Islands
+      (Radeon HD 7000) series and Sea Islands (Radeon HD 8000)
+      series cards. Note: this removes support for analog video outputs,
+      which is only available in the `radeon` driver
+    '';
+    initrd.enable = lib.mkEnableOption ''
+      loading `amdgpu` kernelModule in stage 1.
+      Can fix lower resolution in boot screen during initramfs phase
+    '';
+    opencl.enable = lib.mkEnableOption ''OpenCL support using ROCM runtime library'';
+    # cfg.amdvlk option is defined in ./amdvlk.nix module
+  };
+
+  config = {
+    boot.kernelParams = lib.optionals cfg.legacySupport.enable [
+      "amdgpu.si_support=1"
+      "amdgpu.cik_support=1"
+      "radeon.si_support=0"
+      "radeon.cik_support=0"
+    ];
+
+    boot.initrd.kernelModules = lib.optionals cfg.initrd.enable [ "amdgpu" ];
+
+    hardware.graphics = lib.mkIf cfg.opencl.enable {
+      enable = lib.mkDefault true;
+      extraPackages = [
+        pkgs.rocmPackages.clr
+        pkgs.rocmPackages.clr.icd
+      ];
+    };
+  };
+
+  meta = {
+    maintainers = with lib.maintainers; [ johnrtitor ];
+  };
+}
diff --git a/nixos/modules/services/hardware/amdvlk.nix b/nixos/modules/services/hardware/amdvlk.nix
new file mode 100644
index 0000000000000..32d6fb3be21dc
--- /dev/null
+++ b/nixos/modules/services/hardware/amdvlk.nix
@@ -0,0 +1,59 @@
+{ config, lib, pkgs, ... }:
+
+let
+  cfg = config.hardware.amdgpu.amdvlk;
+in {
+  options.hardware.amdgpu.amdvlk = {
+    enable = lib.mkEnableOption "AMDVLK Vulkan driver";
+
+    package = lib.mkPackageOption pkgs "amdvlk" { };
+
+    supportExperimental.enable = lib.mkEnableOption "Experimental features support";
+
+    support32Bit.enable = lib.mkEnableOption "32-bit driver support";
+    support32Bit.package = lib.mkPackageOption pkgs [ "driversi686Linux" "amdvlk" ] { };
+
+    settings = lib.mkOption {
+      type = with lib.types; attrsOf (either str int);
+      default = { };
+      example = {
+        AllowVkPipelineCachingToDisk = 1;
+        ShaderCacheMode = 1;
+        IFH = 0;
+        EnableVmAlwaysValid = 1;
+        IdleAfterSubmitGpuMask = 1;
+      };
+      description = ''
+        Runtime settings for AMDVLK to be configured {file}`/etc/amd/amdVulkanSettings.cfg`.
+        See [AMDVLK GitHub page](https://github.com/GPUOpen-Drivers/AMDVLK?tab=readme-ov-file#runtime-settings).
+      '';
+    };
+  };
+
+  config = lib.mkIf cfg.enable {
+    hardware.graphics = {
+      enable = true;
+      extraPackages = [ cfg.package ];
+      extraPackages32 = [ cfg.support32Bit.package ];
+    };
+
+    services.xserver.videoDrivers = [ "amdgpu" ];
+
+    environment.sessionVariables = lib.mkIf cfg.supportExperimental.enable {
+      AMDVLK_ENABLE_DEVELOPING_EXT = "all";
+    };
+
+    environment.etc = lib.mkIf (cfg.settings != { }) {
+      "amd/amdVulkanSettings.cfg".text = lib.concatStrings
+        (lib.mapAttrsToList
+          (n: v: ''
+            ${n},${builtins.toString v}
+          '')
+          cfg.settings);
+    };
+  };
+
+  meta = {
+    maintainers = with lib.maintainers; [ johnrtitor ];
+  };
+}
diff --git a/nixos/modules/services/hardware/handheld-daemon.nix b/nixos/modules/services/hardware/handheld-daemon.nix
index 6c9d5aa3e22c8..a5ba1856d015b 100644
--- a/nixos/modules/services/hardware/handheld-daemon.nix
+++ b/nixos/modules/services/hardware/handheld-daemon.nix
@@ -8,7 +8,7 @@ with lib; let
 in
 {
   options.services.handheld-daemon = {
-    enable = mkEnableOption "Enable Handheld Daemon";
+    enable = mkEnableOption "Handheld Daemon";
     package = mkPackageOption pkgs "handheld-daemon" { };
 
     user = mkOption {
diff --git a/nixos/modules/services/hardware/kanata.nix b/nixos/modules/services/hardware/kanata.nix
index 333b2d2a88a55..60fb33881f256 100644
--- a/nixos/modules/services/hardware/kanata.nix
+++ b/nixos/modules/services/hardware/kanata.nix
@@ -5,7 +5,9 @@ with lib;
 let
   cfg = config.services.kanata;
 
-  keyboard = {
+  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 = { name, config, ... }: {
     options = {
       devices = mkOption {
         type = types.listOf types.str;
@@ -22,28 +24,16 @@ let
         type = types.lines;
         example = ''
           (defsrc
-            grv  1    2    3    4    5    6    7    8    9    0    -    =    bspc
-            tab  q    w    e    r    t    y    u    i    o    p    [    ]    \
-            caps a    s    d    f    g    h    j    k    l    ;    '    ret
-            lsft z    x    c    v    b    n    m    ,    .    /    rsft
-            lctl lmet lalt           spc            ralt rmet rctl)
-
-          (deflayer qwerty
-            grv  1    2    3    4    5    6    7    8    9    0    -    =    bspc
-            tab  q    w    e    r    t    y    u    i    o    p    [    ]    \
-            @cap a    s    d    f    g    h    j    k    l    ;    '    ret
-            lsft z    x    c    v    b    n    m    ,    .    /    rsft
-            lctl lmet lalt           spc            ralt rmet rctl)
-
-          (defalias
-            ;; tap within 100ms for capslk, hold more than 100ms for lctl
-            cap (tap-hold 100 100 caps lctl))
+            caps)
+
+          (deflayermap (default-layer)
+            ;; tap caps lock as caps lock, hold caps lock as left control
+            caps (tap-hold 100 100 caps lctl))
         '';
         description = ''
           Configuration other than `defcfg`.
 
-          See [example config files](https://github.com/jtroo/kanata)
-          for more information.
+          ${upstreamDoc}
         '';
       };
       extraDefCfg = mkOption {
@@ -55,8 +45,22 @@ let
           from the devices option) and
           `linux-continue-if-no-devs-found` (hardcoded to be yes).
 
-          See [example config files](https://github.com/jtroo/kanata)
-          for more information.
+          ${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 {
@@ -86,14 +90,24 @@ let
     in
     optionalString ((length devices) > 0) "linux-dev (${devicesString})";
 
-  mkConfig = name: keyboard: pkgs.writeText "${mkName name}-config.kdb" ''
-    (defcfg
-      ${keyboard.extraDefCfg}
-      ${mkDevices keyboard.devices}
-      linux-continue-if-no-devs-found yes)
-
-    ${keyboard.config}
-  '';
+  mkConfig = name: keyboard: pkgs.writeTextFile {
+    name = "${mkName name}-config.kdb";
+    text = ''
+      (defcfg
+        ${keyboard.extraDefCfg}
+        ${mkDevices keyboard.devices}
+        linux-continue-if-no-devs-found yes)
+
+      ${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
+    '';
+  };
 
   mkService = name: keyboard: nameValuePair (mkName name) {
     wantedBy = [ "multi-user.target" ];
@@ -101,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}
@@ -153,7 +167,7 @@ in
   options.services.kanata = {
     enable = mkEnableOption "kanata, a tool to improve keyboard comfort and usability with advanced customization";
     package = mkPackageOption pkgs "kanata" {
-      example = "kanata-with-cmd";
+      example = [ "kanata-with-cmd" ];
       extraDescription = ''
         ::: {.note}
         If {option}`danger-enable-cmd` is enabled in any of the keyboards, the
diff --git a/nixos/modules/services/hardware/nvidia-container-toolkit/default.nix b/nixos/modules/services/hardware/nvidia-container-toolkit/default.nix
index 6c6bc667e6498..bd12667a56474 100644
--- a/nixos/modules/services/hardware/nvidia-container-toolkit/default.nix
+++ b/nixos/modules/services/hardware/nvidia-container-toolkit/default.nix
@@ -69,14 +69,18 @@
     virtualisation.docker.daemon.settings = lib.mkIf
       (config.hardware.nvidia-container-toolkit.enable &&
        (lib.versionAtLeast config.virtualisation.docker.package.version "25")) {
-      features.cdi = true;
-    };
+         features.cdi = true;
+       };
 
     hardware.nvidia-container-toolkit.mounts = let
       nvidia-driver = config.hardware.nvidia.package;
     in (lib.mkMerge [
       [{ hostPath = pkgs.addDriverRunpath.driverLink;
          containerPath = pkgs.addDriverRunpath.driverLink; }
+       { hostPath = "${lib.getLib nvidia-driver}/etc";
+         containerPath = "${lib.getLib nvidia-driver}/etc"; }
+       { hostPath = "${lib.getLib nvidia-driver}/share";
+         containerPath = "${lib.getLib nvidia-driver}/share"; }
        { hostPath = "${lib.getLib pkgs.glibc}/lib";
          containerPath = "${lib.getLib pkgs.glibc}/lib"; }
        { hostPath = "${lib.getLib pkgs.glibc}/lib64";
diff --git a/nixos/modules/services/hardware/nvidia-optimus.nix b/nixos/modules/services/hardware/nvidia-optimus.nix
index d53175052c74a..307bc78098d14 100644
--- a/nixos/modules/services/hardware/nvidia-optimus.nix
+++ b/nixos/modules/services/hardware/nvidia-optimus.nix
@@ -23,7 +23,7 @@ let kernel = config.boot.kernelPackages; in
   ###### implementation
 
   config = lib.mkIf config.hardware.nvidiaOptimus.disable {
-    boot.blacklistedKernelModules = ["nouveau" "nvidia" "nvidiafb" "nvidia-drm"];
+    boot.blacklistedKernelModules = ["nouveau" "nvidia" "nvidiafb" "nvidia-drm" "nvidia-modeset"];
     boot.kernelModules = [ "bbswitch" ];
     boot.extraModulePackages = [ kernel.bbswitch ];
 
diff --git a/nixos/modules/services/hardware/power-profiles-daemon.nix b/nixos/modules/services/hardware/power-profiles-daemon.nix
index 05e5b7a00b420..7651c65b9f181 100644
--- a/nixos/modules/services/hardware/power-profiles-daemon.nix
+++ b/nixos/modules/services/hardware/power-profiles-daemon.nix
@@ -39,6 +39,12 @@ in
           which conflicts with services.tlp.enable = true;
         '';
       }
+      { assertion = !config.services.auto-cpufreq.enable;
+        message = ''
+          You have set services.power-profiles-daemon.enable = true;
+          which conflicts with services.auto-cpufreq.enable = true;
+        '';
+      }
     ];
 
     environment.systemPackages = [ cfg.package ];
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/hardware/udev.nix b/nixos/modules/services/hardware/udev.nix
index 3db6616442816..62603d20e2d30 100644
--- a/nixos/modules/services/hardware/udev.nix
+++ b/nixos/modules/services/hardware/udev.nix
@@ -167,10 +167,16 @@ let
       mv etc/udev/hwdb.bin $out
     '';
 
-  compressFirmware = firmware: if (config.boot.kernelPackages.kernelAtLeast "5.3" && (firmware.compressFirmware or true)) then
-    pkgs.compressFirmwareXz firmware
-  else
-    id firmware;
+  compressFirmware = firmware:
+    let
+      inherit (config.boot.kernelPackages) kernelAtLeast;
+    in
+      if ! (firmware.compressFirmware or true) then
+        firmware
+      else
+        if kernelAtLeast "5.19" then pkgs.compressFirmwareZstd firmware
+        else if kernelAtLeast "5.3" then pkgs.compressFirmwareXz firmware
+        else firmware;
 
   # Udev has a 512-character limit for ENV{PATH}, so create a symlink
   # tree to work around this.
diff --git a/nixos/modules/services/home-automation/ebusd.nix b/nixos/modules/services/home-automation/ebusd.nix
index ac9ec06639c13..f5c5479e8eaff 100644
--- a/nixos/modules/services/home-automation/ebusd.nix
+++ b/nixos/modules/services/home-automation/ebusd.nix
@@ -138,7 +138,7 @@ in
       after = [ "network.target" ];
       serviceConfig = {
         ExecStart = let
-          args = cli.toGNUCommandLineShell { } (foldr (a: b: a // b) { } [
+          args = cli.toGNUCommandLineShell { optionValueSeparator = "="; } (foldr (a: b: a // b) { } [
             {
               inherit (cfg) device port configpath scanconfig readonly;
               foreground = true;
diff --git a/nixos/modules/services/home-automation/home-assistant.nix b/nixos/modules/services/home-automation/home-assistant.nix
index d94adfb4aa1c7..c58a31539ed81 100644
--- a/nixos/modules/services/home-automation/home-assistant.nix
+++ b/nixos/modules/services/home-automation/home-assistant.nix
@@ -518,8 +518,9 @@ in {
           # recreate symlinks for desired components
           declare -a components=(${escapeShellArgs cfg.customComponents})
           for component in "''${components[@]}"; do
-            path="$(dirname $(find "$component" -name "manifest.json"))"
-            ln -fns "$path" "${cfg.configDir}/custom_components/"
+            readarray -t manifests < <(find "$component" -name manifest.json)
+            readarray -t paths < <(dirname "''${manifests[@]}")
+            ln -fns "''${paths[@]}" "${cfg.configDir}/custom_components/"
           done
         '';
       in
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/logging/journalwatch.nix b/nixos/modules/services/logging/journalwatch.nix
index 71b29d57b7eb7..48fd992ffb65a 100644
--- a/nixos/modules/services/logging/journalwatch.nix
+++ b/nixos/modules/services/logging/journalwatch.nix
@@ -56,6 +56,8 @@ in {
         '';
       };
 
+      package = mkPackageOption pkgs "journalwatch" { };
+
       priority = mkOption {
         type = types.int;
         default = 6;
@@ -240,7 +242,7 @@ in {
         # requires a relative directory name to create beneath /var/lib
         StateDirectory = user;
         StateDirectoryMode = "0750";
-        ExecStart = "${pkgs.python3Packages.journalwatch}/bin/journalwatch mail";
+        ExecStart = "${getExe cfg.package} mail";
         # lowest CPU and IO priority, but both still in best-effort class to prevent starvation
         Nice=19;
         IOSchedulingPriority=7;
diff --git a/nixos/modules/services/mail/mailman.nix b/nixos/modules/services/mail/mailman.nix
index 180c9800d7345..ab10206fea42e 100644
--- a/nixos/modules/services/mail/mailman.nix
+++ b/nixos/modules/services/mail/mailman.nix
@@ -646,7 +646,7 @@ in {
   };
 
   meta = {
-    maintainers = with lib.maintainers; [ lheckemann qyliss ];
+    maintainers = with lib.maintainers; [ qyliss ];
     doc = ./mailman.md;
   };
 
diff --git a/nixos/modules/services/mail/postsrsd.nix b/nixos/modules/services/mail/postsrsd.nix
index 2ebc675ab10af..92f01dd4101e8 100644
--- a/nixos/modules/services/mail/postsrsd.nix
+++ b/nixos/modules/services/mail/postsrsd.nix
@@ -120,14 +120,9 @@ in {
         if [ ! -e "${cfg.secretsFile}" ]; then
           echo "WARNING: secrets file not found, autogenerating!"
           DIR="$(dirname "${cfg.secretsFile}")"
-          if [ ! -d "$DIR" ]; then
-            mkdir -p -m750 "$DIR"
-            chown "${cfg.user}:${cfg.group}" "$DIR"
-          fi
-          dd if=/dev/random bs=18 count=1 | base64 > "${cfg.secretsFile}"
-          chmod 600 "${cfg.secretsFile}"
+          install -m 750 -o ${cfg.user} -g ${cfg.group} -d "$DIR"
+          install -m 600 -o ${cfg.user} -g ${cfg.group} <(dd if=/dev/random bs=18 count=1 | base64) "${cfg.secretsFile}"
         fi
-        chown "${cfg.user}:${cfg.group}" "${cfg.secretsFile}"
       '';
     };
 
diff --git a/nixos/modules/services/mail/public-inbox.nix b/nixos/modules/services/mail/public-inbox.nix
index 14a2ab48fa250..98063e0331bd8 100644
--- a/nixos/modules/services/mail/public-inbox.nix
+++ b/nixos/modules/services/mail/public-inbox.nix
@@ -455,7 +455,7 @@ in
           after = [ "public-inbox-init.service" "public-inbox-watch.service" ];
           requires = [ "public-inbox-init.service" ];
           serviceConfig = {
-            BindPathsReadOnly =
+            BindReadOnlyPaths =
               map (c: c.dir) (lib.attrValues cfg.settings.coderepo);
             ExecStart = escapeShellArgs (
               [ "${cfg.package}/bin/public-inbox-httpd" ] ++
diff --git a/nixos/modules/services/mail/stalwart-mail.nix b/nixos/modules/services/mail/stalwart-mail.nix
index 9cc919fd117d6..776243a68af53 100644
--- a/nixos/modules/services/mail/stalwart-mail.nix
+++ b/nixos/modules/services/mail/stalwart-mail.nix
@@ -7,10 +7,12 @@ let
   configFormat = pkgs.formats.toml { };
   configFile = configFormat.generate "stalwart-mail.toml" cfg.settings;
   dataDir = "/var/lib/stalwart-mail";
+  useLegacyStorage = versionOlder config.system.stateVersion "24.11";
 
 in {
   options.services.stalwart-mail = {
     enable = mkEnableOption "the Stalwart all-in-one email server";
+
     package = mkPackageOption pkgs "stalwart-mail" { };
 
     settings = mkOption {
@@ -26,78 +28,111 @@ in {
   };
 
   config = mkIf cfg.enable {
+
     # Default config: all local
     services.stalwart-mail.settings = {
-      global.tracing.method = mkDefault "stdout";
-      global.tracing.level = mkDefault "info";
-      queue.path = mkDefault "${dataDir}/queue";
-      report.path = mkDefault "${dataDir}/reports";
-      store.db.type = mkDefault "sqlite";
-      store.db.path = mkDefault "${dataDir}/data/index.sqlite3";
-      store.blob.type = mkDefault "fs";
-      store.blob.path = mkDefault "${dataDir}/data/blobs";
+      tracer.stdout = {
+        type = mkDefault "stdout";
+        level = mkDefault "info";
+        ansi = mkDefault false;  # no colour markers to journald
+        enable = mkDefault true;
+      };
+      store = if useLegacyStorage then {
+        # structured data in SQLite, blobs on filesystem
+        db.type = mkDefault "sqlite";
+        db.path = mkDefault "${dataDir}/data/index.sqlite3";
+        fs.type = mkDefault "fs";
+        fs.path = mkDefault "${dataDir}/data/blobs";
+      } else {
+        # everything in RocksDB
+        db.type = mkDefault "rocksdb";
+        db.path = mkDefault "${dataDir}/db";
+        db.compression = mkDefault "lz4";
+      };
       storage.data = mkDefault "db";
       storage.fts = mkDefault "db";
-      storage.blob = mkDefault "blob";
+      storage.lookup = mkDefault "db";
+      storage.blob = mkDefault (if useLegacyStorage then "fs" else "db");
+      directory.internal.type = mkDefault "internal";
+      directory.internal.store = mkDefault "db";
+      storage.directory = mkDefault "internal";
       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"
+      ];
+      config.resource = {
+        spam-filter = lib.mkDefault "file://${cfg.package}/etc/stalwart/spamfilter.toml";
+      };
     };
 
-    systemd.services.stalwart-mail = {
-      wantedBy = [ "multi-user.target" ];
-      after = [ "local-fs.target" "network.target" ];
+    # This service stores a potentially large amount of data.
+    # Running it as a dynamic user would force chown to be run everytime the
+    # service is restarted on a potentially large number of files.
+    # That would cause unnecessary and unwanted delays.
+    users = {
+      groups.stalwart-mail = { };
+      users.stalwart-mail = {
+        isSystemUser = true;
+        group = "stalwart-mail";
+      };
+    };
 
-      preStart = ''
-        mkdir -p ${dataDir}/{queue,reports,data/blobs}
-      '';
+    systemd = {
+      packages = [ cfg.package ];
+      services.stalwart-mail = {
+        wantedBy = [ "multi-user.target" ];
+        after = [ "local-fs.target" "network.target" ];
+
+        preStart = if useLegacyStorage then ''
+          mkdir -p ${dataDir}/data/blobs
+        '' else ''
+          mkdir -p ${dataDir}/db
+        '';
+
+        serviceConfig = {
+          ExecStart = [
+            ""
+            "${cfg.package}/bin/stalwart-mail --config=${configFile}"
+          ];
+
+          StandardOutput = "journal";
+          StandardError = "journal";
+
+          StateDirectory = "stalwart-mail";
+
+          # Bind standard privileged ports
+          AmbientCapabilities = [ "CAP_NET_BIND_SERVICE" ];
+          CapabilityBoundingSet = [ "CAP_NET_BIND_SERVICE" ];
 
-      serviceConfig = {
-        ExecStart =
-          "${cfg.package}/bin/stalwart-mail --config=${configFile}";
-
-        # Base from template resources/systemd/stalwart-mail.service
-        Type = "simple";
-        LimitNOFILE = 65536;
-        KillMode = "process";
-        KillSignal = "SIGINT";
-        Restart = "on-failure";
-        RestartSec = 5;
-        StandardOutput = "journal";
-        StandardError = "journal";
-        SyslogIdentifier = "stalwart-mail";
-
-        DynamicUser = true;
-        User = "stalwart-mail";
-        StateDirectory = "stalwart-mail";
-
-        # Bind standard privileged ports
-        AmbientCapabilities = [ "CAP_NET_BIND_SERVICE" ];
-        CapabilityBoundingSet = [ "CAP_NET_BIND_SERVICE" ];
-
-        # Hardening
-        DeviceAllow = [ "" ];
-        LockPersonality = true;
-        MemoryDenyWriteExecute = true;
-        PrivateDevices = true;
-        PrivateUsers = false;  # incompatible with CAP_NET_BIND_SERVICE
-        ProcSubset = "pid";
-        PrivateTmp = true;
-        ProtectClock = true;
-        ProtectControlGroups = true;
-        ProtectHome = true;
-        ProtectHostname = true;
-        ProtectKernelLogs = true;
-        ProtectKernelModules = true;
-        ProtectKernelTunables = true;
-        ProtectProc = "invisible";
-        ProtectSystem = "strict";
-        RestrictAddressFamilies = [ "AF_INET" "AF_INET6" ];
-        RestrictNamespaces = true;
-        RestrictRealtime = true;
-        RestrictSUIDSGID = true;
-        SystemCallArchitectures = "native";
-        SystemCallFilter = [ "@system-service" "~@privileged" ];
-        UMask = "0077";
+          # Hardening
+          DeviceAllow = [ "" ];
+          LockPersonality = true;
+          MemoryDenyWriteExecute = true;
+          PrivateDevices = true;
+          PrivateUsers = false;  # incompatible with CAP_NET_BIND_SERVICE
+          ProcSubset = "pid";
+          PrivateTmp = true;
+          ProtectClock = true;
+          ProtectControlGroups = true;
+          ProtectHome = true;
+          ProtectHostname = true;
+          ProtectKernelLogs = true;
+          ProtectKernelModules = true;
+          ProtectKernelTunables = true;
+          ProtectProc = "invisible";
+          ProtectSystem = "strict";
+          RestrictAddressFamilies = [ "AF_INET" "AF_INET6" ];
+          RestrictNamespaces = true;
+          RestrictRealtime = true;
+          RestrictSUIDSGID = true;
+          SystemCallArchitectures = "native";
+          SystemCallFilter = [ "@system-service" "~@privileged" ];
+          UMask = "0077";
+        };
+        unitConfig.ConditionPathExists = [
+          ""
+          "${configFile}"
+        ];
       };
     };
 
@@ -106,6 +141,6 @@ in {
   };
 
   meta = {
-    maintainers = with maintainers; [ happysalada pacien ];
+    maintainers = with maintainers; [ happysalada pacien onny ];
   };
 }
diff --git a/nixos/modules/services/matrix/mautrix-signal.nix b/nixos/modules/services/matrix/mautrix-signal.nix
new file mode 100644
index 0000000000000..faca10551abb6
--- /dev/null
+++ b/nixos/modules/services/matrix/mautrix-signal.nix
@@ -0,0 +1,249 @@
+{ lib
+, config
+, pkgs
+, ...
+}:
+let
+  cfg = config.services.mautrix-signal;
+  dataDir = "/var/lib/mautrix-signal";
+  registrationFile = "${dataDir}/signal-registration.yaml";
+  settingsFile = "${dataDir}/config.yaml";
+  settingsFileUnsubstituted = settingsFormat.generate "mautrix-signal-config-unsubstituted.json" cfg.settings;
+  settingsFormat = pkgs.formats.json { };
+  appservicePort = 29328;
+
+  # to be used with a list of lib.mkIf values
+  optOneOf = lib.lists.findFirst (value: value.condition) (lib.mkIf false null);
+  mkDefaults = lib.mapAttrsRecursive (n: v: lib.mkDefault v);
+  defaultConfig = {
+    homeserver.address = "http://localhost:8448";
+    appservice = {
+      hostname = "[::]";
+      port = appservicePort;
+      database.type = "sqlite3";
+      database.uri = "file:${dataDir}/mautrix-signal.db?_txlock=immediate";
+      id = "signal";
+      bot = {
+        username = "signalbot";
+        displayname = "Signal Bridge Bot";
+      };
+      as_token = "";
+      hs_token = "";
+    };
+    bridge = {
+      username_template = "signal_{{.}}";
+      displayname_template = "{{or .ProfileName .PhoneNumber \"Unknown user\"}}";
+      double_puppet_server_map = { };
+      login_shared_secret_map = { };
+      command_prefix = "!signal";
+      permissions."*" = "relay";
+      relay.enabled = true;
+    };
+    logging = {
+      min_level = "info";
+      writers = lib.singleton {
+        type = "stdout";
+        format = "pretty-colored";
+        time_format = " ";
+      };
+    };
+  };
+
+in
+{
+  options.services.mautrix-signal = {
+    enable = lib.mkEnableOption "mautrix-signal, a Matrix-Signal puppeting bridge.";
+
+    settings = lib.mkOption {
+      apply = lib.recursiveUpdate defaultConfig;
+      type = settingsFormat.type;
+      default = defaultConfig;
+      description = ''
+        {file}`config.yaml` configuration as a Nix attribute set.
+        Configuration options should match those described in
+        [example-config.yaml](https://github.com/mautrix/signal/blob/master/example-config.yaml).
+        Secret tokens should be specified using {option}`environmentFile`
+        instead of this world-readable attribute set.
+      '';
+      example = {
+        appservice = {
+          database = {
+            type = "postgres";
+            uri = "postgresql:///mautrix_signal?host=/run/postgresql";
+          };
+          id = "signal";
+          ephemeral_events = false;
+        };
+        bridge = {
+          history_sync = {
+            request_full_sync = true;
+          };
+          private_chat_portal_meta = true;
+          mute_bridging = true;
+          encryption = {
+            allow = true;
+            default = true;
+            require = true;
+          };
+          provisioning = {
+            shared_secret = "disable";
+          };
+          permissions = {
+            "example.com" = "user";
+          };
+        };
+      };
+    };
+
+    environmentFile = lib.mkOption {
+      type = lib.types.nullOr lib.types.path;
+      default = null;
+      description = ''
+        File containing environment variables to be passed to the mautrix-signal service.
+        If an environment variable `MAUTRIX_SIGNAL_BRIDGE_LOGIN_SHARED_SECRET` is set,
+        then its value will be used in the configuration file for the option
+        `login_shared_secret_map` without leaking it to the store, using the configured
+        `homeserver.domain` as key.
+        See [here](https://github.com/mautrix/signal/blob/main/example-config.yaml)
+        for the documentation of `login_shared_secret_map`.
+      '';
+    };
+
+    serviceDependencies = lib.mkOption {
+      type = with lib.types; listOf str;
+      default = (lib.optional config.services.matrix-synapse.enable config.services.matrix-synapse.serviceUnit)
+        ++ (lib.optional config.services.matrix-conduit.enable "conduit.service");
+      defaultText = lib.literalExpression ''
+        (optional config.services.matrix-synapse.enable config.services.matrix-synapse.serviceUnit)
+        ++ (optional config.services.matrix-conduit.enable "conduit.service")
+      '';
+      description = ''
+        List of systemd units to require and wait for when starting the application service.
+      '';
+    };
+
+    registerToSynapse = lib.mkOption {
+      type = lib.types.bool;
+      default = config.services.matrix-synapse.enable;
+      defaultText = lib.literalExpression ''
+        config.services.matrix-synapse.enable
+      '';
+      description = ''
+        Whether to add the bridge's app service registration file to
+        `services.matrix-synapse.settings.app_service_config_files`.
+      '';
+    };
+  };
+
+  config = lib.mkIf cfg.enable {
+
+    users.users.mautrix-signal = {
+      isSystemUser = true;
+      group = "mautrix-signal";
+      home = dataDir;
+      description = "Mautrix-Signal bridge user";
+    };
+
+    users.groups.mautrix-signal = { };
+
+    services.matrix-synapse = lib.mkIf cfg.registerToSynapse {
+      settings.app_service_config_files = [ registrationFile ];
+    };
+    systemd.services.matrix-synapse = lib.mkIf cfg.registerToSynapse {
+      serviceConfig.SupplementaryGroups = [ "mautrix-signal" ];
+    };
+
+    # Note: this is defined here to avoid the docs depending on `config`
+    services.mautrix-signal.settings.homeserver = optOneOf (with config.services; [
+      (lib.mkIf matrix-synapse.enable (mkDefaults {
+        domain = matrix-synapse.settings.server_name;
+      }))
+      (lib.mkIf matrix-conduit.enable (mkDefaults {
+        domain = matrix-conduit.settings.global.server_name;
+        address = "http://localhost:${toString matrix-conduit.settings.global.port}";
+      }))
+    ]);
+
+    systemd.services.mautrix-signal = {
+      description = "mautrix-signal, a Matrix-Signal puppeting bridge.";
+
+      wantedBy = [ "multi-user.target" ];
+      wants = [ "network-online.target" ] ++ cfg.serviceDependencies;
+      after = [ "network-online.target" ] ++ cfg.serviceDependencies;
+      # ffmpeg is required for conversion of voice messages
+      path = [ pkgs.ffmpeg-headless ];
+
+      preStart = ''
+        # substitute the settings file by environment variables
+        # in this case read from EnvironmentFile
+        test -f '${settingsFile}' && rm -f '${settingsFile}'
+        old_umask=$(umask)
+        umask 0177
+        ${pkgs.envsubst}/bin/envsubst \
+          -o '${settingsFile}' \
+          -i '${settingsFileUnsubstituted}'
+        umask $old_umask
+
+        # generate the appservice's registration file if absent
+        if [ ! -f '${registrationFile}' ]; then
+          ${pkgs.mautrix-signal}/bin/mautrix-signal \
+            --generate-registration \
+            --config='${settingsFile}' \
+            --registration='${registrationFile}'
+        fi
+        chmod 640 ${registrationFile}
+
+        umask 0177
+        # 1. Overwrite registration tokens in config
+        # 2. If environment variable MAUTRIX_SIGNAL_BRIDGE_LOGIN_SHARED_SECRET
+        #    is set, set it as the login shared secret value for the configured
+        #    homeserver domain.
+        ${pkgs.yq}/bin/yq -s '.[0].appservice.as_token = .[1].as_token
+          | .[0].appservice.hs_token = .[1].hs_token
+          | .[0]
+          | if env.MAUTRIX_SIGNAL_BRIDGE_LOGIN_SHARED_SECRET then .bridge.login_shared_secret_map.[.homeserver.domain] = env.MAUTRIX_SIGNAL_BRIDGE_LOGIN_SHARED_SECRET else . end' \
+          '${settingsFile}' '${registrationFile}' > '${settingsFile}.tmp'
+        mv '${settingsFile}.tmp' '${settingsFile}'
+        umask $old_umask
+      '';
+
+      serviceConfig = {
+        User = "mautrix-signal";
+        Group = "mautrix-signal";
+        EnvironmentFile = cfg.environmentFile;
+        StateDirectory = baseNameOf dataDir;
+        WorkingDirectory = dataDir;
+        ExecStart = ''
+          ${pkgs.mautrix-signal}/bin/mautrix-signal \
+          --config='${settingsFile}' \
+          --registration='${registrationFile}'
+        '';
+        LockPersonality = true;
+        MemoryDenyWriteExecute = true;
+        NoNewPrivileges = true;
+        PrivateDevices = true;
+        PrivateTmp = true;
+        PrivateUsers = true;
+        ProtectClock = true;
+        ProtectControlGroups = true;
+        ProtectHome = true;
+        ProtectHostname = true;
+        ProtectKernelLogs = true;
+        ProtectKernelModules = true;
+        ProtectKernelTunables = true;
+        ProtectSystem = "strict";
+        Restart = "on-failure";
+        RestartSec = "30s";
+        RestrictRealtime = true;
+        RestrictSUIDSGID = true;
+        SystemCallArchitectures = "native";
+        SystemCallErrorNumber = "EPERM";
+        SystemCallFilter = [ "@system-service" ];
+        Type = "simple";
+        UMask = 0027;
+      };
+      restartTriggers = [ settingsFileUnsubstituted ];
+    };
+  };
+  meta.maintainers = with lib.maintainers; [ niklaskorz ];
+}
diff --git a/nixos/modules/services/matrix/synapse.nix b/nixos/modules/services/matrix/synapse.nix
index bc88fb53012b7..6d2e6201d66d3 100644
--- a/nixos/modules/services/matrix/synapse.nix
+++ b/nixos/modules/services/matrix/synapse.nix
@@ -1121,7 +1121,7 @@ in {
           The client listener on matrix-synapse is configured to use UNIX domain sockets.
           This configuration is incompatible with the `register_new_matrix_user` script.
 
-          Disable  `services.mastrix-synapse.enableRegistrationScript` to continue.
+          Disable  `services.matrix-synapse.enableRegistrationScript` to continue.
         '';
       }
     ]
diff --git a/nixos/modules/services/misc/amazon-ssm-agent.nix b/nixos/modules/services/misc/amazon-ssm-agent.nix
index 9ab4a7f96d087..0da10621d0a09 100644
--- a/nixos/modules/services/misc/amazon-ssm-agent.nix
+++ b/nixos/modules/services/misc/amazon-ssm-agent.nix
@@ -28,13 +28,7 @@ in {
 
   options.services.amazon-ssm-agent = {
     enable = mkEnableOption "Amazon SSM agent";
-
-    package = mkOption {
-      type = types.path;
-      description = "The Amazon SSM agent package to use";
-      default = pkgs.amazon-ssm-agent.override { overrideEtc = false; };
-      defaultText = literalExpression "pkgs.amazon-ssm-agent.override { overrideEtc = false; }";
-    };
+    package = mkPackageOption pkgs "amazon-ssm-agent" {};
   };
 
   config = mkIf cfg.enable {
diff --git a/nixos/modules/services/misc/anki-sync-server.md b/nixos/modules/services/misc/anki-sync-server.md
index f58d3d8ad0dab..5482a4aa0e5ff 100644
--- a/nixos/modules/services/misc/anki-sync-server.md
+++ b/nixos/modules/services/misc/anki-sync-server.md
@@ -52,7 +52,7 @@ following options:
 
 ```nix
 {
-  services.anki-sync-server.host = "0.0.0.0";
+  services.anki-sync-server.address = "0.0.0.0";
   services.anki-sync-server.openFirewall = true;
 }
 ```
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..92c0c6206c8b3
--- /dev/null
+++ b/nixos/modules/services/misc/devpi-server.nix
@@ -0,0 +1,132 @@
+{
+  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 =
+        ''
+          ${optionalString (!isNull cfg.secretFile)
+            "install -Dm 0600 \${CREDENTIALS_DIRECTORY}/devpi-secret ${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 = {
+        LoadCredential = lib.mkIf (! isNull cfg.secretFile) [
+          "devpi-secret:${cfg.secretFile}"
+        ];
+        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/forgejo.nix b/nixos/modules/services/misc/forgejo.nix
index babed2d5acd48..9a102918f35e3 100644
--- a/nixos/modules/services/misc/forgejo.nix
+++ b/nixos/modules/services/misc/forgejo.nix
@@ -12,6 +12,15 @@ let
   usePostgresql = cfg.database.type == "postgres";
   useSqlite = cfg.database.type == "sqlite3";
 
+  secrets = let
+    mkSecret = section: values: lib.mapAttrsToList (key: value: {
+      env = envEscape "FORGEJO__${section}__${key}__FILE";
+      path = value;
+    }) values;
+    # https://codeberg.org/forgejo/forgejo/src/tag/v7.0.2/contrib/environment-to-ini/environment-to-ini.go
+    envEscape = string: lib.replaceStrings [ "." "-" ] [ "_0X2E_" "_0X2D_" ] (lib.strings.toUpper string);
+  in lib.flatten (lib.mapAttrsToList mkSecret cfg.secrets);
+
   inherit (lib)
     literalExpression
     mkChangedOptionModule
@@ -34,6 +43,7 @@ in
     (mkRenamedOptionModule [ "services" "forgejo" "appName" ] [ "services" "forgejo" "settings" "DEFAULT" "APP_NAME" ])
     (mkRemovedOptionModule [ "services" "forgejo" "extraConfig" ] "services.forgejo.extraConfig has been removed. Please use the freeform services.forgejo.settings option instead")
     (mkRemovedOptionModule [ "services" "forgejo" "database" "password" ] "services.forgejo.database.password has been removed. Please use services.forgejo.database.passwordFile instead")
+    (mkRenamedOptionModule [ "services" "forgejo" "mailerPasswordFile" ] [ "services" "forgejo" "secrets" "mailer" "PASSWD" ])
 
     # copied from services.gitea; remove at some point
     (mkRenamedOptionModule [ "services" "forgejo" "cookieSecure" ] [ "services" "forgejo" "settings" "session" "COOKIE_SECURE" ])
@@ -224,13 +234,6 @@ in
         description = "Path to the git repositories.";
       };
 
-      mailerPasswordFile = mkOption {
-        type = types.nullOr types.str;
-        default = null;
-        example = "/run/keys/forgejo-mailpw";
-        description = "Path to a file containing the SMTP password.";
-      };
-
       settings = mkOption {
         default = { };
         description = ''
@@ -347,6 +350,44 @@ in
           };
         };
       };
+
+      secrets = mkOption {
+        default = { };
+        description = ''
+          This is a small wrapper over systemd's `LoadCredential`.
+
+          It takes the same sections and keys as {option}`services.forgejo.settings`,
+          but the value of each key is a path instead of a string or bool.
+
+          The path is then loaded as credential, exported as environment variable
+          and then feed through
+          <https://codeberg.org/forgejo/forgejo/src/branch/forgejo/contrib/environment-to-ini/environment-to-ini.go>.
+
+          It does the required environment variable escaping for you.
+
+          ::: {.note}
+          Keys specified here take priority over the ones in {option}`services.forgejo.settings`!
+          :::
+        '';
+        example = literalExpression ''
+        {
+          metrics = {
+            TOKEN = "/run/keys/forgejo-metrics-token";
+          };
+          camo = {
+            HMAC_KEY = "/run/keys/forgejo-camo-hmac";
+          };
+          service = {
+            HCAPTCHA_SECRET = "/run/keys/forgejo-hcaptcha-secret";
+            HCAPTCHA_SITEKEY = "/run/keys/forgejo-hcaptcha-sitekey";
+          };
+        }
+        '';
+        type = types.submodule {
+          freeformType = with types; attrsOf (attrsOf path);
+          options = { };
+        };
+      };
     };
   };
 
@@ -381,7 +422,6 @@ in
           HOST = if cfg.database.socket != null then cfg.database.socket else cfg.database.host + ":" + toString cfg.database.port;
           NAME = cfg.database.name;
           USER = cfg.database.user;
-          PASSWD = "#dbpass#";
         })
         (mkIf useSqlite {
           PATH = cfg.database.path;
@@ -397,7 +437,6 @@ in
 
       server = mkIf cfg.lfs.enable {
         LFS_START_SERVER = true;
-        LFS_JWT_SECRET = "#lfsjwtsecret#";
       };
 
       session = {
@@ -405,21 +444,30 @@ in
       };
 
       security = {
-        SECRET_KEY = "#secretkey#";
-        INTERNAL_TOKEN = "#internaltoken#";
         INSTALL_LOCK = true;
       };
 
-      mailer = mkIf (cfg.mailerPasswordFile != null) {
-        PASSWD = "#mailerpass#";
+      lfs = mkIf cfg.lfs.enable {
+        PATH = cfg.lfs.contentDir;
+      };
+    };
+
+    services.forgejo.secrets = {
+      security = {
+        SECRET_KEY = "${cfg.customDir}/conf/secret_key";
+        INTERNAL_TOKEN = "${cfg.customDir}/conf/internal_token";
       };
 
       oauth2 = {
-        JWT_SECRET = "#oauth2jwtsecret#";
+        JWT_SECRET = "${cfg.customDir}/conf/oauth2_jwt_secret";
       };
 
-      lfs = mkIf cfg.lfs.enable {
-        PATH = cfg.lfs.contentDir;
+      database = mkIf (cfg.database.passwordFile != null) {
+        PASSWD = cfg.database.passwordFile;
+      };
+
+      server = mkIf cfg.lfs.enable {
+        LFS_JWT_SECRET = "${cfg.customDir}/conf/lfs_jwt_secret";
       };
     };
 
@@ -476,6 +524,37 @@ in
       "z '${cfg.lfs.contentDir}' 0750 ${cfg.user} ${cfg.group} - -"
     ];
 
+    systemd.services.forgejo-secrets = mkIf (!cfg.useWizard) {
+      description = "Forgejo secret bootstrap helper";
+      script = ''
+        if [ ! -s '${cfg.secrets.security.SECRET_KEY}' ]; then
+            ${exe} generate secret SECRET_KEY > '${cfg.secrets.security.SECRET_KEY}'
+        fi
+
+        if [ ! -s '${cfg.secrets.oauth2.JWT_SECRET}' ]; then
+            ${exe} generate secret JWT_SECRET > '${cfg.secrets.oauth2.JWT_SECRET}'
+        fi
+
+        ${optionalString cfg.lfs.enable ''
+        if [ ! -s '${cfg.secrets.server.LFS_JWT_SECRET}' ]; then
+            ${exe} generate secret LFS_JWT_SECRET > '${cfg.secrets.server.LFS_JWT_SECRET}'
+        fi
+        ''}
+
+        if [ ! -s '${cfg.secrets.security.INTERNAL_TOKEN}' ]; then
+            ${exe} generate secret INTERNAL_TOKEN > '${cfg.secrets.security.INTERNAL_TOKEN}'
+        fi
+      '';
+      serviceConfig = {
+        Type = "oneshot";
+        RemainAfterExit = true;
+        User = cfg.user;
+        Group = cfg.group;
+        ReadWritePaths = [ cfg.customDir ];
+        UMask = "0077";
+      };
+    };
+
     systemd.services.forgejo = {
       description = "Forgejo (Beyond coding. We forge.)";
       after = [
@@ -484,11 +563,15 @@ in
         "postgresql.service"
       ] ++ optionals useMysql [
         "mysql.service"
+      ] ++ optionals (!cfg.useWizard) [
+        "forgejo-secrets.service"
       ];
       requires = optionals (cfg.database.createDatabase && usePostgresql) [
         "postgresql.service"
       ] ++ optionals (cfg.database.createDatabase && useMysql) [
         "mysql.service"
+      ] ++ optionals (!cfg.useWizard) [
+        "forgejo-secrets.service"
       ];
       wantedBy = [ "multi-user.target" ];
       path = [ cfg.package pkgs.git pkgs.gnupg ];
@@ -501,61 +584,15 @@ in
       # lfs_jwt_secret.
       # We have to consider this to stay compatible with older installations.
       preStart =
-        let
-          runConfig = "${cfg.customDir}/conf/app.ini";
-          secretKey = "${cfg.customDir}/conf/secret_key";
-          oauth2JwtSecret = "${cfg.customDir}/conf/oauth2_jwt_secret";
-          oldLfsJwtSecret = "${cfg.customDir}/conf/jwt_secret"; # old file for LFS_JWT_SECRET
-          lfsJwtSecret = "${cfg.customDir}/conf/lfs_jwt_secret"; # new file for LFS_JWT_SECRET
-          internalToken = "${cfg.customDir}/conf/internal_token";
-          replaceSecretBin = "${pkgs.replace-secret}/bin/replace-secret";
-        in
         ''
-          # copy custom configuration and generate random secrets if needed
-          ${lib.optionalString (!cfg.useWizard) ''
+          ${optionalString (!cfg.useWizard) ''
             function forgejo_setup {
-              cp -f '${format.generate "app.ini" cfg.settings}' '${runConfig}'
-
-              if [ ! -s '${secretKey}' ]; then
-                  ${exe} generate secret SECRET_KEY > '${secretKey}'
-              fi
-
-              # Migrate LFS_JWT_SECRET filename
-              if [[ -s '${oldLfsJwtSecret}' && ! -s '${lfsJwtSecret}' ]]; then
-                  mv '${oldLfsJwtSecret}' '${lfsJwtSecret}'
-              fi
-
-              if [ ! -s '${oauth2JwtSecret}' ]; then
-                  ${exe} generate secret JWT_SECRET > '${oauth2JwtSecret}'
-              fi
-
-              ${optionalString cfg.lfs.enable ''
-              if [ ! -s '${lfsJwtSecret}' ]; then
-                  ${exe} generate secret LFS_JWT_SECRET > '${lfsJwtSecret}'
-              fi
-              ''}
-
-              if [ ! -s '${internalToken}' ]; then
-                  ${exe} generate secret INTERNAL_TOKEN > '${internalToken}'
-              fi
-
-              chmod u+w '${runConfig}'
-              ${replaceSecretBin} '#secretkey#' '${secretKey}' '${runConfig}'
-              ${replaceSecretBin} '#oauth2jwtsecret#' '${oauth2JwtSecret}' '${runConfig}'
-              ${replaceSecretBin} '#internaltoken#' '${internalToken}' '${runConfig}'
-
-              ${optionalString cfg.lfs.enable ''
-                ${replaceSecretBin} '#lfsjwtsecret#' '${lfsJwtSecret}' '${runConfig}'
-              ''}
-
-              ${optionalString (cfg.database.passwordFile != null) ''
-                ${replaceSecretBin} '#dbpass#' '${cfg.database.passwordFile}' '${runConfig}'
-              ''}
-
-              ${optionalString (cfg.mailerPasswordFile != null) ''
-                ${replaceSecretBin} '#mailerpass#' '${cfg.mailerPasswordFile}' '${runConfig}'
-              ''}
-              chmod u-w '${runConfig}'
+              config='${cfg.customDir}/conf/app.ini'
+              cp -f '${format.generate "app.ini" cfg.settings}' "$config"
+
+              chmod u+w "$config"
+              ${lib.getExe' cfg.package "environment-to-ini"} --config "$config"
+              chmod u-w "$config"
             }
             (umask 027; forgejo_setup)
           ''}
@@ -616,6 +653,8 @@ in
         # System Call Filtering
         SystemCallArchitectures = "native";
         SystemCallFilter = [ "~@cpu-emulation @debug @keyring @mount @obsolete @privileged @setuid" "setrlimit" ];
+        # cfg.secrets
+        LoadCredential = map (e: "${e.env}:${e.path}") secrets;
       };
 
       environment = {
@@ -625,7 +664,7 @@ in
         # is resolved.
         GITEA_WORK_DIR = cfg.stateDir;
         GITEA_CUSTOM = cfg.customDir;
-      };
+      } // lib.listToAttrs (map (e: lib.nameValuePair e.env "%d/${e.env}") secrets);
     };
 
     services.openssh.settings.AcceptEnv = mkIf (!cfg.settings.START_SSH_SERVER or false) "GIT_PROTOCOL";
diff --git a/nixos/modules/services/misc/gitea.nix b/nixos/modules/services/misc/gitea.nix
index a8526688b074f..d43250c882683 100644
--- a/nixos/modules/services/misc/gitea.nix
+++ b/nixos/modules/services/misc/gitea.nix
@@ -722,5 +722,5 @@ in
       timerConfig.OnCalendar = cfg.dump.interval;
     };
   };
-  meta.maintainers = with lib.maintainers; [ srhb ma27 pyrox0 ];
+  meta.maintainers = with lib.maintainers; [ ma27 techknowlogick SuperSandro2000 ];
 }
diff --git a/nixos/modules/services/misc/gollum.nix b/nixos/modules/services/misc/gollum.nix
index 3966ef036bec4..f320e78a91060 100644
--- a/nixos/modules/services/misc/gollum.nix
+++ b/nixos/modules/services/misc/gollum.nix
@@ -110,7 +110,7 @@ in
     users.groups."${cfg.group}" = { };
 
     systemd.tmpfiles.rules = [
-      "d '${cfg.stateDir}' - ${config.users.users.gollum.name} ${config.users.groups.gollum.name} - -"
+      "d '${cfg.stateDir}' - ${cfg.user} ${cfg.group} - -"
     ];
 
     systemd.services.gollum = {
diff --git a/nixos/modules/services/misc/graphical-desktop.nix b/nixos/modules/services/misc/graphical-desktop.nix
index a88c02e610bf4..c8fe0d921c6ad 100644
--- a/nixos/modules/services/misc/graphical-desktop.nix
+++ b/nixos/modules/services/misc/graphical-desktop.nix
@@ -38,7 +38,7 @@ in
 
     fonts.enableDefaultPackages = lib.mkDefault true;
 
-    hardware.opengl.enable = lib.mkDefault true;
+    hardware.graphics.enable = lib.mkDefault true;
 
     programs.gnupg.agent.pinentryPackage = lib.mkOverride 1100 pkgs.pinentry-gnome3;
 
diff --git a/nixos/modules/services/misc/invidious-router.nix b/nixos/modules/services/misc/invidious-router.nix
index 33da7e96b5235..7a90c6ab9ddc0 100644
--- a/nixos/modules/services/misc/invidious-router.nix
+++ b/nixos/modules/services/misc/invidious-router.nix
@@ -8,10 +8,10 @@
   settingsFormat = pkgs.formats.yaml {};
   configFile = settingsFormat.generate "config.yaml" cfg.settings;
 in {
-  meta.maintainers = [lib.maintainers.s1ls];
+  meta.maintainers = [lib.maintainers.sils];
 
   options.services.invidious-router = {
-    enable = lib.mkEnableOption "Enables the invidious-router service";
+    enable = lib.mkEnableOption "the invidious-router service";
     port = lib.mkOption {
       type = lib.types.port;
       default = 8050;
diff --git a/nixos/modules/services/misc/jellyfin.nix b/nixos/modules/services/misc/jellyfin.nix
index a1d3910bd93b0..a006090878422 100644
--- a/nixos/modules/services/misc/jellyfin.nix
+++ b/nixos/modules/services/misc/jellyfin.nix
@@ -160,5 +160,5 @@ in
 
   };
 
-  meta.maintainers = with maintainers; [ minijackson nu-nu-ko ];
+  meta.maintainers = with maintainers; [ minijackson fsnkty ];
 }
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/mqtt2influxdb.nix b/nixos/modules/services/misc/mqtt2influxdb.nix
index a2d6a2b34a239..925139b449b8e 100644
--- a/nixos/modules/services/misc/mqtt2influxdb.nix
+++ b/nixos/modules/services/misc/mqtt2influxdb.nix
@@ -125,6 +125,7 @@ in {
   options = {
     services.mqtt2influxdb = {
       enable = mkEnableOption "BigClown MQTT to InfluxDB bridge.";
+      package = mkPackageOption pkgs ["python3Packages" "mqtt2influxdb"] {};
       environmentFiles = mkOption {
         type = types.listOf types.path;
         default = [];
@@ -245,7 +246,7 @@ in {
       '';
       serviceConfig = {
         EnvironmentFile = cfg.environmentFiles;
-        ExecStart = "${cfg.package}/bin/mqtt2influxdb -dc ${finalConfig}";
+        ExecStart = "${lib.getExe cfg.package} -dc ${finalConfig}";
         RuntimeDirectory = "mqtt2influxdb";
       };
     };
diff --git a/nixos/modules/services/misc/ollama.nix b/nixos/modules/services/misc/ollama.nix
index c0341984aa351..1467c3f93bc85 100644
--- a/nixos/modules/services/misc/ollama.nix
+++ b/nixos/modules/services/misc/ollama.nix
@@ -11,6 +11,11 @@ let
   };
 in
 {
+  imports = [
+    (lib.mkRemovedOptionModule [ "services" "ollama" "listenAddress" ]
+      "Use `services.ollama.host` and `services.ollama.port` instead.")
+  ];
+
   options = {
     services.ollama = {
       enable = lib.mkEnableOption "ollama server for local large language models";
@@ -64,12 +69,20 @@ in
           See also `services.ollama.sandbox`.
         '';
       };
-      listenAddress = lib.mkOption {
+      host = lib.mkOption {
         type = types.str;
-        default = "127.0.0.1:11434";
-        example = "0.0.0.0:11111";
+        default = "127.0.0.1";
+        example = "0.0.0.0";
+        description = ''
+          The host address which the ollama server HTTP interface listens to.
+        '';
+      };
+      port = lib.mkOption {
+        type = types.port;
+        default = 11434;
+        example = 11111;
         description = ''
-          The address which the ollama server HTTP interface binds and listens to.
+          Which port the ollama server listens to.
         '';
       };
       acceleration = lib.mkOption {
@@ -80,14 +93,30 @@ in
           What interface to use for hardware acceleration.
 
           - `null`: default behavior
-            if `nixpkgs.config.rocmSupport` is enabled, uses `"rocm"`
-            if `nixpkgs.config.cudaSupport` is enabled, uses `"cuda"`
-            otherwise defaults to `false`
+            - if `nixpkgs.config.rocmSupport` is enabled, uses `"rocm"`
+            - if `nixpkgs.config.cudaSupport` is enabled, uses `"cuda"`
+            - otherwise defaults to `false`
           - `false`: disable GPU, only use CPU
           - `"rocm"`: supported by most modern AMD GPUs
+            - may require overriding gpu type with `services.ollama.rocmOverrideGfx`
+              if rocm doesn't detect your AMD gpu
           - `"cuda"`: supported by most modern NVIDIA GPUs
         '';
       };
+      rocmOverrideGfx = lib.mkOption {
+        type = types.nullOr types.str;
+        default = null;
+        example = "10.3.0";
+        description = ''
+          Override what rocm will detect your gpu model as.
+          For example, make rocm treat your RX 5700 XT (or any other model)
+          as an RX 6900 XT using a value of `"10.3.0"` (gfx 1030).
+
+          This sets the value of `HSA_OVERRIDE_GFX_VERSION`. See [ollama's docs](
+          https://github.com/ollama/ollama/blob/main/docs/gpu.md#amd-radeon
+          ) for details.
+        '';
+      };
       environmentVariables = lib.mkOption {
         type = types.attrsOf types.str;
         default = { };
@@ -103,6 +132,14 @@ in
           Since `ollama run` is mostly a shell around the ollama server, this is usually sufficient.
         '';
       };
+      openFirewall = lib.mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Whether to open the firewall for ollama.
+          This adds `services.ollama.port` to `networking.firewall.allowedTCPPorts`.
+        '';
+      };
     };
   };
 
@@ -114,7 +151,8 @@ in
       environment = cfg.environmentVariables // {
         HOME = cfg.home;
         OLLAMA_MODELS = cfg.models;
-        OLLAMA_HOST = cfg.listenAddress;
+        OLLAMA_HOST = "${cfg.host}:${toString cfg.port}";
+        HSA_OVERRIDE_GFX_VERSION = lib.mkIf (cfg.rocmOverrideGfx != null) cfg.rocmOverrideGfx;
       };
       serviceConfig = {
         ExecStart = "${lib.getExe ollamaPackage} serve";
@@ -125,6 +163,8 @@ in
       };
     };
 
+    networking.firewall = lib.mkIf cfg.openFirewall { allowedTCPPorts = [ cfg.port ]; };
+
     environment.systemPackages = [ ollamaPackage ];
   };
 
diff --git a/nixos/modules/services/misc/open-webui.nix b/nixos/modules/services/misc/open-webui.nix
new file mode 100644
index 0000000000000..b4016d03f675f
--- /dev/null
+++ b/nixos/modules/services/misc/open-webui.nix
@@ -0,0 +1,114 @@
+{
+  config,
+  lib,
+  pkgs,
+  ...
+}:
+let
+  inherit (lib) types;
+
+  cfg = config.services.open-webui;
+in
+{
+  options = {
+    services.open-webui = {
+      enable = lib.mkEnableOption "Open-WebUI server";
+      package = lib.mkPackageOption pkgs "open-webui" { };
+
+      stateDir = lib.mkOption {
+        type = types.path;
+        default = "/var/lib/open-webui";
+        example = "/home/foo";
+        description = "State directory of Open-WebUI.";
+      };
+
+      host = lib.mkOption {
+        type = types.str;
+        default = "127.0.0.1";
+        example = "0.0.0.0";
+        description = ''
+          The host address which the Open-WebUI server HTTP interface listens to.
+        '';
+      };
+
+      port = lib.mkOption {
+        type = types.port;
+        default = 8080;
+        example = 11111;
+        description = ''
+          Which port the Open-WebUI server listens to.
+        '';
+      };
+
+      environment = lib.mkOption {
+        type = types.attrsOf types.str;
+        default = {
+          SCARF_NO_ANALYTICS = "True";
+          DO_NOT_TRACK = "True";
+          ANONYMIZED_TELEMETRY = "False";
+        };
+        example = ''
+          {
+            OLLAMA_API_BASE_URL = "http://127.0.0.1:11434";
+            # Disable authentication
+            WEBUI_AUTH = "False";
+          }
+        '';
+        description = "Extra environment variables for Open-WebUI";
+      };
+
+      openFirewall = lib.mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Whether to open the firewall for Open-WebUI.
+          This adds `services.open-webui.port` to `networking.firewall.allowedTCPPorts`.
+        '';
+      };
+    };
+  };
+
+  config = lib.mkIf cfg.enable {
+    systemd.services.open-webui = {
+      description = "User-friendly WebUI for LLMs";
+      wantedBy = [ "multi-user.target" ];
+      after = [ "network.target" ];
+
+      environment = {
+        STATIC_DIR = ".";
+        DATA_DIR = ".";
+        HF_HOME = ".";
+        SENTENCE_TRANSFORMERS_HOME = ".";
+      } // cfg.environment;
+
+      serviceConfig = {
+        ExecStart = "${lib.getExe cfg.package} serve --host ${cfg.host} --port ${toString cfg.port}";
+        WorkingDirectory = cfg.stateDir;
+        StateDirectory = "open-webui";
+        RuntimeDirectory = "open-webui";
+        RuntimeDirectoryMode = "0755";
+        PrivateTmp = true;
+        DynamicUser = true;
+        DevicePolicy = "closed";
+        LockPersonality = true;
+        MemoryDenyWriteExecute = false; # onnxruntime/capi/onnxruntime_pybind11_state.so: cannot enable executable stack as shared object requires: Permission Denied
+        PrivateUsers = true;
+        ProtectHome = true;
+        ProtectHostname = true;
+        ProtectKernelLogs = true;
+        ProtectKernelModules = true;
+        ProtectKernelTunables = true;
+        ProtectControlGroups = true;
+        ProcSubset = "all"; # Error in cpuinfo: failed to parse processor information from /proc/cpuinfo
+        RestrictNamespaces = true;
+        RestrictRealtime = true;
+        SystemCallArchitectures = "native";
+        UMask = "0077";
+      };
+    };
+
+    networking.firewall = lib.mkIf cfg.openFirewall { allowedTCPPorts = [ cfg.port ]; };
+  };
+
+  meta.maintainers = with lib.maintainers; [ shivaraj-bh ];
+}
diff --git a/nixos/modules/services/misc/pghero.nix b/nixos/modules/services/misc/pghero.nix
new file mode 100644
index 0000000000000..39515f10c8e1d
--- /dev/null
+++ b/nixos/modules/services/misc/pghero.nix
@@ -0,0 +1,142 @@
+{ config, pkgs, lib, utils, ... }:
+let
+  cfg = config.services.pghero;
+  settingsFormat = pkgs.formats.yaml { };
+  settingsFile = settingsFormat.generate "pghero.yaml" cfg.settings;
+in
+{
+  options.services.pghero = {
+    enable = lib.mkEnableOption "PgHero service";
+    package = lib.mkPackageOption pkgs "pghero" { };
+
+    listenAddress = lib.mkOption {
+      type = lib.types.str;
+      example = "[::1]:3000";
+      description = ''
+        `hostname:port` to listen for HTTP traffic.
+
+        This is bound using the systemd socket activation.
+      '';
+    };
+
+    extraArgs = lib.mkOption {
+      type = lib.types.listOf lib.types.str;
+      default = [ ];
+      description = ''
+        Additional command-line arguments for the systemd service.
+
+        Refer to the [Puma web server documentation] for available arguments.
+
+        [Puma web server documentation]: https://puma.io/puma#configuration
+      '';
+    };
+
+    settings = lib.mkOption {
+      type = settingsFormat.type;
+      default = { };
+      example = {
+        databases = {
+          primary = {
+            url = "<%= ENV['PRIMARY_DATABASE_URL'] %>";
+          };
+        };
+      };
+      description = ''
+        PgHero configuration. Refer to the [PgHero documentation] for more
+        details.
+
+        [PgHero documentation]: https://github.com/ankane/pghero/blob/master/guides/Linux.md#multiple-databases
+      '';
+    };
+
+    environment = lib.mkOption {
+      type = lib.types.attrsOf lib.types.str;
+      default = { };
+      description = ''
+        Environment variables to set for the service. Secrets should be
+        specified using {option}`environmentFile`.
+      '';
+    };
+
+    environmentFiles = lib.mkOption {
+      type = lib.types.listOf lib.types.path;
+      default = [ ];
+      description = ''
+        File to load environment variables from. Loaded variables override
+        values set in {option}`environment`.
+      '';
+    };
+
+    extraGroups = lib.mkOption {
+      type = lib.types.listOf lib.types.str;
+      default = [ ];
+      example = [ "tlskeys" ];
+      description = ''
+        Additional groups for the systemd service.
+      '';
+    };
+  };
+
+  config = lib.mkIf cfg.enable {
+    systemd.sockets.pghero = {
+      unitConfig.Description = "PgHero HTTP socket";
+      wantedBy = [ "sockets.target" ];
+      listenStreams = [ cfg.listenAddress ];
+    };
+
+    systemd.services.pghero = {
+      description = "PgHero performance dashboard for PostgreSQL";
+      wantedBy = [ "multi-user.target" ];
+      requires = [ "pghero.socket" ];
+      after = [ "pghero.socket" "network.target" ];
+
+      environment = {
+        RAILS_ENV = "production";
+        PGHERO_CONFIG_PATH = settingsFile;
+      } // cfg.environment;
+
+      serviceConfig = {
+        Type = "notify";
+        WatchdogSec = "10";
+
+        ExecStart = utils.escapeSystemdExecArgs ([
+          (lib.getExe cfg.package)
+          "--bind-to-activated-sockets"
+          "only"
+        ] ++ cfg.extraArgs);
+        Restart = "always";
+
+        WorkingDirectory = "${cfg.package}/share/pghero";
+
+        EnvironmentFile = cfg.environmentFiles;
+        SupplementaryGroups = cfg.extraGroups;
+
+        DynamicUser = true;
+        UMask = "0077";
+
+        ProtectHome = true;
+        ProtectProc = "invisible";
+        ProcSubset = "pid";
+        ProtectClock = true;
+        ProtectHostname = true;
+        ProtectControlGroups = true;
+        ProtectKernelLogs = true;
+        ProtectKernelModules = true;
+        ProtectKernelTunables = true;
+        PrivateUsers = true;
+        PrivateDevices = true;
+        RestrictRealtime = true;
+        RestrictNamespaces = true;
+        RestrictAddressFamilies = [ "AF_INET" "AF_INET6" "AF_UNIX" ];
+        DeviceAllow = [ "" ];
+        DevicePolicy = "closed";
+        CapabilityBoundingSet = [ "" ];
+        MemoryDenyWriteExecute = true;
+        LockPersonality = true;
+        SystemCallArchitectures = "native";
+        SystemCallErrorNumber = "EPERM";
+        SystemCallFilter = [ "@system-service" ];
+      };
+    };
+  };
+}
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 ab78479c96cd3..c7abb2cfa2a3e 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 -.
+          :::
         '';
       };
 
@@ -111,10 +115,7 @@ in
     ldap = {
       package = mkOption {
         type = types.package;
-        # needs openldap built with a libxcrypt that support crypt sha256 until users have had time to migrate to newer hashes
-        # Ref: <https://github.com/majewsky/portunus/issues/2>
-        # TODO: remove in NixOS 24.11 (cf. same note on pkgs/servers/portunus/default.nix)
-        default = pkgs.openldap.override { libxcrypt = pkgs.libxcrypt-legacy; };
+        default = pkgs.openldap;
         defaultText = lib.literalExpression "pkgs.openldap.override { libxcrypt = pkgs.libxcrypt-legacy; }";
         description = "The OpenLDAP package to use.";
       };
@@ -231,12 +232,14 @@ in
     };
 
     systemd.services = {
-      dex.serviceConfig = mkIf cfg.dex.enable {
-        # `dex.service` is super locked down out of the box, but we need some
-        # place to write the SQLite database. This creates $STATE_DIRECTORY below
-        # /var/lib/private because DynamicUser=true, but it gets symlinked into
-        # /var/lib/dex inside the unit
-        StateDirectory = "dex";
+      dex = mkIf cfg.dex.enable {
+        serviceConfig = {
+          # `dex.service` is super locked down out of the box, but we need some
+          # place to write the SQLite database. This creates $STATE_DIRECTORY below
+          # /var/lib/private because DynamicUser=true, but it gets symlinked into
+          # /var/lib/dex inside the unit
+          StateDirectory = "dex";
+        };
       };
 
       portunus = {
diff --git a/nixos/modules/services/misc/private-gpt.nix b/nixos/modules/services/misc/private-gpt.nix
new file mode 100644
index 0000000000000..ad9b6f5ffa80f
--- /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; [ ];
+}
diff --git a/nixos/modules/services/misc/renovate.nix b/nixos/modules/services/misc/renovate.nix
new file mode 100644
index 0000000000000..25a719c91cbd8
--- /dev/null
+++ b/nixos/modules/services/misc/renovate.nix
@@ -0,0 +1,153 @@
+{
+  config,
+  lib,
+  pkgs,
+  ...
+}:
+let
+  inherit (lib)
+    mkEnableOption
+    mkPackageOption
+    mkOption
+    types
+    mkIf
+    ;
+  json = pkgs.formats.json { };
+  cfg = config.services.renovate;
+  generateValidatedConfig =
+    name: value:
+    pkgs.callPackage (
+      { runCommand, jq }:
+      runCommand name
+        {
+          nativeBuildInputs = [
+            jq
+            cfg.package
+          ];
+          value = builtins.toJSON value;
+          passAsFile = [ "value" ];
+          preferLocalBuild = true;
+        }
+        ''
+          jq . "$valuePath"> $out
+          renovate-config-validator $out
+        ''
+    ) { };
+  generateConfig = if cfg.validateSettings then generateValidatedConfig else json.generate;
+in
+{
+  meta.maintainers = with lib.maintainers; [ marie natsukium ];
+
+  options.services.renovate = {
+    enable = mkEnableOption "renovate";
+    package = mkPackageOption pkgs "renovate" { };
+    schedule = mkOption {
+      type = with types; nullOr str;
+      description = "How often to run renovate. See {manpage}`systemd.time(7)` for the format.";
+      example = "*:0/10";
+      default = null;
+    };
+    credentials = mkOption {
+      type = with types; attrsOf path;
+      description = ''
+        Allows configuring environment variable credentials for renovate, read from files.
+        This should always be used for passing confidential data to renovate.
+      '';
+      example = {
+        RENOVATE_TOKEN = "/etc/renovate/token";
+      };
+      default = { };
+    };
+    runtimePackages = mkOption {
+      type = with types; listOf package;
+      description = "Packages available to renovate.";
+      default = [ ];
+    };
+    validateSettings = mkOption {
+      type = types.bool;
+      default = true;
+      description = "Weither to run renovate's config validator on the built configuration.";
+    };
+    settings = mkOption {
+      type = json.type;
+      default = { };
+      example = {
+        platform = "gitea";
+        endpoint = "https://git.example.com";
+        gitAuthor = "Renovate <renovate@example.com>";
+      };
+      description = ''
+        Renovate's global configuration.
+        If you want to pass secrets to renovate, please use {option}`services.renovate.credentials` for that.
+      '';
+    };
+  };
+
+  config = mkIf cfg.enable {
+    services.renovate.settings = {
+      cacheDir = "/var/cache/renovate";
+      baseDir = "/var/lib/renovate";
+    };
+
+    systemd.services.renovate = {
+      description = "Renovate dependency updater";
+      documentation = [ "https://docs.renovatebot.com/" ];
+      after = [ "network.target" ];
+      startAt = lib.optional (cfg.schedule != null) cfg.schedule;
+      path = [
+        config.systemd.package
+        pkgs.git
+      ] ++ cfg.runtimePackages;
+
+      serviceConfig = {
+        Type = "oneshot";
+        User = "renovate";
+        Group = "renovate";
+        DynamicUser = true;
+        LoadCredential = lib.mapAttrsToList (name: value: "SECRET-${name}:${value}") cfg.credentials;
+        RemainAfterExit = false;
+        Restart = "on-failure";
+        CacheDirectory = "renovate";
+        StateDirectory = "renovate";
+
+        # Hardening
+        CapabilityBoundingSet = [ "" ];
+        DeviceAllow = [ "" ];
+        LockPersonality = true;
+        PrivateDevices = true;
+        PrivateUsers = true;
+        ProcSubset = "pid";
+        ProtectClock = true;
+        ProtectControlGroups = true;
+        ProtectHome = true;
+        ProtectHostname = true;
+        ProtectKernelLogs = true;
+        ProtectKernelModules = true;
+        ProtectKernelTunables = true;
+        ProtectProc = "invisible";
+        RestrictAddressFamilies = [
+          "AF_INET"
+          "AF_INET6"
+        ];
+        RestrictNamespaces = true;
+        RestrictRealtime = true;
+        SystemCallArchitectures = "native";
+        UMask = "0077";
+      };
+
+      script = ''
+        ${lib.concatStringsSep "\n" (
+          builtins.map (name: "export ${name}=$(systemd-creds cat 'SECRET-${name}')") (
+            lib.attrNames cfg.credentials
+          )
+        )}
+        exec ${lib.escapeShellArg (lib.getExe cfg.package)}
+      '';
+
+      environment = {
+        RENOVATE_CONFIG_FILE = generateConfig "renovate-config.json" cfg.settings;
+        HOME = "/var/lib/renovate";
+      };
+    };
+  };
+}
diff --git a/nixos/modules/services/misc/snapper.nix b/nixos/modules/services/misc/snapper.nix
index 3a3ed1b5c0f56..1b16ef7958ad2 100644
--- a/nixos/modules/services/misc/snapper.nix
+++ b/nixos/modules/services/misc/snapper.nix
@@ -1,16 +1,32 @@
-{ config, pkgs, lib, ... }:
+{
+  config,
+  pkgs,
+  lib,
+  ...
+}:
 
 with lib;
 
 let
   cfg = config.services.snapper;
 
-  mkValue = v:
-    if isList v then "\"${concatMapStringsSep " " (escape [ "\\" " " ]) v}\""
-    else if v == true then "yes"
-    else if v == false then "no"
-    else if isString v then "\"${v}\""
-    else builtins.toJSON v;
+  mkValue =
+    v:
+    if isList v then
+      "\"${
+        concatMapStringsSep " " (escape [
+          "\\"
+          " "
+        ]) v
+      }\""
+    else if v == true then
+      "yes"
+    else if v == false then
+      "no"
+    else if isString v then
+      "\"${v}\""
+    else
+      builtins.toJSON v;
 
   mkKeyValue = k: v: "${k}=${mkValue v}";
 
@@ -43,7 +59,7 @@ let
 
     ALLOW_GROUPS = mkOption {
       type = types.listOf safeStr;
-      default = [];
+      default = [ ];
       description = ''
         List of groups allowed to operate with the config.
 
@@ -53,7 +69,7 @@ let
 
     ALLOW_USERS = mkOption {
       type = types.listOf safeStr;
-      default = [];
+      default = [ ];
       example = [ "alice" ];
       description = ''
         List of users allowed to operate with the config. "root" is always
@@ -78,6 +94,54 @@ let
         Defines whether hourly snapshots should be created.
       '';
     };
+
+    TIMELINE_LIMIT_HOURLY = mkOption {
+      type = types.str;
+      default = "10";
+      description = ''
+        Limits for timeline cleanup.
+      '';
+    };
+
+    TIMELINE_LIMIT_DAILY = mkOption {
+      type = types.str;
+      default = "10";
+      description = ''
+        Limits for timeline cleanup.
+      '';
+    };
+
+    TIMELINE_LIMIT_WEEKLY = mkOption {
+      type = types.str;
+      default = "0";
+      description = ''
+        Limits for timeline cleanup.
+      '';
+    };
+
+    TIMELINE_LIMIT_MONTHLY = mkOption {
+      type = types.str;
+      default = "10";
+      description = ''
+        Limits for timeline cleanup.
+      '';
+    };
+
+    TIMELINE_LIMIT_QUARTERLY = mkOption {
+      type = types.str;
+      default = "0";
+      description = ''
+        Limits for timeline cleanup.
+      '';
+    };
+
+    TIMELINE_LIMIT_YEARLY = mkOption {
+      type = types.str;
+      default = "10";
+      description = ''
+        Limits for timeline cleanup.
+      '';
+    };
   };
 in
 
@@ -103,6 +167,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";
@@ -140,105 +216,129 @@ in
         is valid here, even if NixOS doesn't document it.
       '';
 
-      type = types.attrsOf (types.submodule {
-        freeformType = types.attrsOf (types.oneOf [ (types.listOf safeStr) types.bool safeStr types.number ]);
-
-        options = configOptions;
-      });
+      type = types.attrsOf (
+        types.submodule {
+          freeformType = types.attrsOf (
+            types.oneOf [
+              (types.listOf safeStr)
+              types.bool
+              safeStr
+              types.number
+            ]
+          );
+
+          options = configOptions;
+        }
+      );
     };
   };
 
-  config = mkIf (cfg.configs != {}) (let
-    documentation = [ "man:snapper(8)" "man:snapper-configs(5)" ];
-  in {
-
-    environment = {
-
-      systemPackages = [ pkgs.snapper ];
-
-      # Note: snapper/config-templates/default is only needed for create-config
-      #       which is not the NixOS way to configure.
-      etc = {
-
-        "sysconfig/snapper".text = ''
-          SNAPPER_CONFIGS="${lib.concatStringsSep " " (builtins.attrNames cfg.configs)}"
-        '';
-
-      }
-      // (mapAttrs' (name: subvolume: nameValuePair "snapper/configs/${name}" ({
-        text = lib.generators.toKeyValue { inherit mkKeyValue; } (filterAttrs (k: v: v != defaultOf k) subvolume);
-      })) cfg.configs)
-      // (lib.optionalAttrs (cfg.filters != null) {
-        "snapper/filters/default.txt".text = cfg.filters;
-      });
-
-    };
+  config = mkIf (cfg.configs != { }) (
+    let
+      documentation = [
+        "man:snapper(8)"
+        "man:snapper-configs(5)"
+      ];
+    in
+    {
+      environment = {
+
+        systemPackages = [ pkgs.snapper ];
+
+        # Note: snapper/config-templates/default is only needed for create-config
+        #       which is not the NixOS way to configure.
+        etc =
+          {
+
+            "sysconfig/snapper".text = ''
+              SNAPPER_CONFIGS="${lib.concatStringsSep " " (builtins.attrNames cfg.configs)}"
+            '';
+          }
+          // (mapAttrs' (
+            name: subvolume:
+            nameValuePair "snapper/configs/${name}" ({
+              text = lib.generators.toKeyValue { inherit mkKeyValue; } (
+                filterAttrs (k: v: v != defaultOf k) subvolume
+              );
+            })
+          ) cfg.configs)
+          // (lib.optionalAttrs (cfg.filters != null) { "snapper/filters/default.txt".text = cfg.filters; });
+      };
 
-    services.dbus.packages = [ pkgs.snapper ];
+      services.dbus.packages = [ pkgs.snapper ];
+
+      systemd.services.snapperd = {
+        description = "DBus interface for snapper";
+        inherit documentation;
+        serviceConfig = {
+          Type = "dbus";
+          BusName = "org.opensuse.Snapper";
+          ExecStart = "${pkgs.snapper}/bin/snapperd";
+          CapabilityBoundingSet = "CAP_DAC_OVERRIDE CAP_FOWNER CAP_CHOWN CAP_FSETID CAP_SETFCAP CAP_SYS_ADMIN CAP_SYS_MODULE CAP_IPC_LOCK CAP_SYS_NICE";
+          LockPersonality = true;
+          NoNewPrivileges = false;
+          PrivateNetwork = true;
+          ProtectHostname = true;
+          RestrictAddressFamilies = "AF_UNIX";
+          RestrictRealtime = true;
+        };
+      };
 
-    systemd.services.snapperd = {
-      description = "DBus interface for snapper";
-      inherit documentation;
-      serviceConfig = {
-        Type = "dbus";
-        BusName = "org.opensuse.Snapper";
-        ExecStart = "${pkgs.snapper}/bin/snapperd";
-        CapabilityBoundingSet = "CAP_DAC_OVERRIDE CAP_FOWNER CAP_CHOWN CAP_FSETID CAP_SETFCAP CAP_SYS_ADMIN CAP_SYS_MODULE CAP_IPC_LOCK CAP_SYS_NICE";
-        LockPersonality = true;
-        NoNewPrivileges = false;
-        PrivateNetwork = true;
-        ProtectHostname = true;
-        RestrictAddressFamilies = "AF_UNIX";
-        RestrictRealtime = true;
+      systemd.services.snapper-timeline = {
+        description = "Timeline of Snapper Snapshots";
+        inherit documentation;
+        requires = [ "local-fs.target" ];
+        serviceConfig.ExecStart = "${pkgs.snapper}/lib/snapper/systemd-helper --timeline";
       };
-    };
 
-    systemd.services.snapper-timeline = {
-      description = "Timeline of Snapper Snapshots";
-      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 = {
-      description = "Cleanup of Snapper Snapshots";
-      inherit documentation;
-      serviceConfig.ExecStart = "${pkgs.snapper}/lib/snapper/systemd-helper --cleanup";
-    };
+      systemd.services.snapper-cleanup = {
+        description = "Cleanup of Snapper Snapshots";
+        inherit documentation;
+        serviceConfig.ExecStart = "${pkgs.snapper}/lib/snapper/systemd-helper --cleanup";
+      };
 
-    systemd.timers.snapper-cleanup = {
-      description = "Cleanup of Snapper Snapshots";
-      inherit documentation;
-      wantedBy = [ "timers.target" ];
-      requires = [ "local-fs.target" ];
-      timerConfig.OnBootSec = "10m";
-      timerConfig.OnUnitActiveSec = cfg.cleanupInterval;
-    };
+      systemd.timers.snapper-cleanup = {
+        description = "Cleanup of Snapper Snapshots";
+        inherit documentation;
+        wantedBy = [ "timers.target" ];
+        requires = [ "local-fs.target" ];
+        timerConfig.OnBootSec = "10m";
+        timerConfig.OnUnitActiveSec = cfg.cleanupInterval;
+      };
 
-    systemd.services.snapper-boot = lib.optionalAttrs cfg.snapshotRootOnBoot {
-      description = "Take snapper snapshot of root on boot";
-      inherit documentation;
-      serviceConfig.ExecStart = "${pkgs.snapper}/bin/snapper --config root create --cleanup-algorithm number --description boot";
-      serviceConfig.Type = "oneshot";
-      requires = [ "local-fs.target" ];
-      wantedBy = [ "multi-user.target" ];
-      unitConfig.ConditionPathExists = "/etc/snapper/configs/root";
-    };
+      systemd.services.snapper-boot = lib.mkIf cfg.snapshotRootOnBoot {
+        description = "Take snapper snapshot of root on boot";
+        inherit documentation;
+        serviceConfig.ExecStart = "${pkgs.snapper}/bin/snapper --config root create --cleanup-algorithm number --description boot";
+        serviceConfig.Type = "oneshot";
+        requires = [ "local-fs.target" ];
+        wantedBy = [ "multi-user.target" ];
+        unitConfig.ConditionPathExists = "/etc/snapper/configs/root";
+      };
 
-    assertions =
-      concatMap
-        (name:
-          let
-            sub = cfg.configs.${name};
-          in
-          [ { assertion = !(sub ? extraConfig);
-              message = ''
-                The option definition `services.snapper.configs.${name}.extraConfig' no longer has any effect; please remove it.
-                The contents of this option should be migrated to attributes on `services.snapper.configs.${name}'.
-              '';
-            }
-          ] ++
+      assertions = concatMap (
+        name:
+        let
+          sub = cfg.configs.${name};
+        in
+        [
+          {
+            assertion = !(sub ? extraConfig);
+            message = ''
+              The option definition `services.snapper.configs.${name}.extraConfig' no longer has any effect; please remove it.
+              The contents of this option should be migrated to attributes on `services.snapper.configs.${name}'.
+            '';
+          }
+        ]
+        ++
           map
             (attr: {
               assertion = !(hasAttr attr sub);
@@ -246,8 +346,11 @@ in
                 The option definition `services.snapper.configs.${name}.${attr}' has been renamed to `services.snapper.configs.${name}.${toUpper attr}'.
               '';
             })
-            [ "fstype" "subvolume" ]
-        )
-        (attrNames cfg.configs);
-  });
+            [
+              "fstype"
+              "subvolume"
+            ]
+      ) (attrNames cfg.configs);
+    }
+  );
 }
diff --git a/nixos/modules/services/misc/sourcehut/service.nix b/nixos/modules/services/misc/sourcehut/service.nix
index ce5a0e78627c1..3507a49ea13a8 100644
--- a/nixos/modules/services/misc/sourcehut/service.nix
+++ b/nixos/modules/services/misc/sourcehut/service.nix
@@ -324,7 +324,8 @@ in
               };
               preStart =
                 let
-                  version = pkgs.sourcehut.${srvsrht}.version;
+                  package = pkgs.sourcehut.${srvsrht};
+                  version = package.version;
                   stateDir = "/var/lib/sourcehut/${srvsrht}";
                 in
                 mkBefore ''
@@ -336,14 +337,14 @@ in
                   if test ! -e ${stateDir}/db; then
                     # Setup the initial database.
                     # Note that it stamps the alembic head afterward
-                    ${cfg.python}/bin/${srvsrht}-initdb
+                    ${package}/bin/${srvsrht}-initdb
                     echo ${version} >${stateDir}/db
                   fi
 
                   ${optionalString cfg.settings.${iniKey}.migrate-on-upgrade ''
                     if [ "$(cat ${stateDir}/db)" != "${version}" ]; then
                       # Manage schema migrations using alembic
-                      ${cfg.python}/bin/${srvsrht}-migrate -a upgrade head
+                      ${package}/bin/${srvsrht}-migrate -a upgrade head
                       echo ${version} >${stateDir}/db
                     fi
                   ''}
@@ -389,7 +390,7 @@ in
               after = [ "network.target" "${srvsrht}.service" ];
               serviceConfig = {
                 Type = "oneshot";
-                ExecStart = "${cfg.python}/bin/${timerName}";
+                ExecStart = "${pkgs.sourcehut.${srvsrht}}/bin/${timerName}";
               };
             }
             (timer.service or { })
diff --git a/nixos/modules/services/misc/tandoor-recipes.nix b/nixos/modules/services/misc/tandoor-recipes.nix
index a2210f3d7db5a..1c903d280378e 100644
--- a/nixos/modules/services/misc/tandoor-recipes.nix
+++ b/nixos/modules/services/misc/tandoor-recipes.nix
@@ -22,7 +22,7 @@ let
     ${lib.toShellVars env}
     eval "$(${config.systemd.package}/bin/systemctl show -pUID,GID,MainPID tandoor-recipes.service)"
     exec ${pkgs.util-linux}/bin/nsenter \
-      -t $MainPID -m -S $UID -G $GID \
+      -t $MainPID -m -S $UID -G $GID --wdns=${env.MEDIA_ROOT} \
       ${pkg}/bin/tandoor-recipes "$@"
   '';
 in
@@ -88,7 +88,7 @@ in
         Group = "tandoor_recipes";
         DynamicUser = true;
         StateDirectory = "tandoor-recipes";
-        WorkingDirectory = "/var/lib/tandoor-recipes";
+        WorkingDirectory = env.MEDIA_ROOT;
         RuntimeDirectory = "tandoor-recipes";
 
         BindReadOnlyPaths = [
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/misc/wastebin.nix b/nixos/modules/services/misc/wastebin.nix
index 3d0af2862683d..f24bf94fa52bb 100644
--- a/nixos/modules/services/misc/wastebin.nix
+++ b/nixos/modules/services/misc/wastebin.nix
@@ -10,7 +10,7 @@ in
 
   options.services.wastebin = {
 
-    enable = mkEnableOption "Wastenbin pastebin service";
+    enable = mkEnableOption "Wastebin, a pastebin service";
 
     package = mkPackageOption pkgs "wastebin" { };
 
diff --git a/nixos/modules/services/misc/zoneminder.nix b/nixos/modules/services/misc/zoneminder.nix
index 84c3a6710c0db..d09cd87febfff 100644
--- a/nixos/modules/services/misc/zoneminder.nix
+++ b/nixos/modules/services/misc/zoneminder.nix
@@ -350,7 +350,7 @@ in {
           RestartSec = "10s";
           CacheDirectory = dirs cacheDirs;
           RuntimeDirectory = dirName;
-          ReadWriteDirectories = lib.mkIf useCustomDir [ cfg.storageDir ];
+          ReadWritePaths = lib.mkIf useCustomDir [ cfg.storageDir ];
           StateDirectory = dirs (lib.optionals (!useCustomDir) libDirs);
           LogsDirectory = dirName;
           PrivateTmp = true;
diff --git a/nixos/modules/services/monitoring/alloy.nix b/nixos/modules/services/monitoring/alloy.nix
new file mode 100644
index 0000000000000..abe8fcd7e1beb
--- /dev/null
+++ b/nixos/modules/services/monitoring/alloy.nix
@@ -0,0 +1,80 @@
+{ lib, pkgs, config, ... }:
+with lib;
+let
+  cfg = config.services.alloy;
+in
+{
+  meta = {
+    maintainers = with maintainers; [ flokli hbjydev ];
+  };
+
+  options.services.alloy = {
+    enable = mkEnableOption "Grafana Alloy";
+
+    package = mkPackageOption pkgs "grafana-alloy" { };
+
+    configPath = mkOption {
+      type = lib.types.path;
+      default = "/etc/alloy";
+      description = ''
+        Alloy configuration file/directory path.
+
+        We default to `/etc/alloy` here, and expect the user to configure a
+        configuration file via `environment.etc."alloy/config.alloy"`.
+
+        This allows config reload, contrary to specifying a store path.
+        A `reloadTrigger` for `config.alloy` is configured.
+
+        Other `*.alloy` files in the same directory (ignoring subdirs) are also
+        honored, but it's necessary to manually extend
+        `systemd.services.alloy.reloadTriggers` to enable config reload
+        during nixos-rebuild switch.
+
+        This can also point to another directory containing `*.alloy` files, or
+        a single Alloy file in the Nix store (at the cost of reload).
+
+        Component names must be unique across all Alloy configuration files, and
+        configuration blocks must not be repeated.
+
+        Alloy will continue to run if subsequent reloads of the configuration
+        file fail, potentially marking components as unhealthy depending on
+        the nature of the failure. When this happens, Alloy will continue
+        functioning in the last valid state.
+      '';
+    };
+
+    extraFlags = mkOption {
+      type = with lib.types; listOf str;
+      default = [ ];
+      example = [ "--server.http.listen-addr=127.0.0.1:12346" "--disable-reporting" ];
+      description = ''
+        Extra command-line flags passed to {command}`alloy run`.
+
+        See <https://grafana.com/docs/alloy/latest/reference/cli/run/>
+      '';
+    };
+  };
+
+
+  config = mkIf cfg.enable {
+    systemd.services.alloy = {
+      wantedBy = [ "multi-user.target" ];
+      reloadTriggers = [ config.environment.etc."alloy/config.alloy".source or null ];
+      serviceConfig = {
+        Restart = "always";
+        DynamicUser = true;
+        RestartSec = 2;
+        SupplementaryGroups = [
+          # allow to read the systemd journal for loki log forwarding
+          "systemd-journal"
+        ];
+        ExecStart = "${lib.getExe cfg.package} run ${cfg.configPath} ${escapeShellArgs cfg.extraFlags}";
+        ExecReload = "${pkgs.coreutils}/bin/kill -SIGHUP $MAINPID";
+        ConfigurationDirectory = "alloy";
+        StateDirectory = "alloy";
+        WorkingDirectory = "%S/alloy";
+        Type = "simple";
+      };
+    };
+  };
+}
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/grafana-reporter.nix b/nixos/modules/services/monitoring/grafana-reporter.nix
index 340ab7abd19b7..528041cab37af 100644
--- a/nixos/modules/services/monitoring/grafana-reporter.nix
+++ b/nixos/modules/services/monitoring/grafana-reporter.nix
@@ -60,7 +60,7 @@ in {
           "-templates ${cfg.templateDir}"
         ];
       in {
-        ExecStart = "${pkgs.grafana_reporter}/bin/grafana-reporter ${args}";
+        ExecStart = "${pkgs.grafana-reporter}/bin/grafana-reporter ${args}";
       };
     };
   };
diff --git a/nixos/modules/services/monitoring/grafana.nix b/nixos/modules/services/monitoring/grafana.nix
index 9d453c5394824..32919950adc1e 100644
--- a/nixos/modules/services/monitoring/grafana.nix
+++ b/nixos/modules/services/monitoring/grafana.nix
@@ -47,13 +47,6 @@ let
   datasourceFileOrDir = mkProvisionCfg "datasource" "datasources" cfg.provision.datasources;
   dashboardFileOrDir = mkProvisionCfg "dashboard" "providers" cfg.provision.dashboards;
 
-  notifierConfiguration = {
-    apiVersion = 1;
-    notifiers = cfg.provision.notifiers;
-  };
-
-  notifierFileOrDir = pkgs.writeText "notifier.yaml" (builtins.toJSON notifierConfiguration);
-
   generateAlertingProvisioningYaml = x:
     if (cfg.provision.alerting."${x}".path == null)
     then provisioningSettingsFormat.generate "${x}.yaml" cfg.provision.alerting."${x}".settings
@@ -74,10 +67,9 @@ let
     fi
   '';
   provisionConfDir = pkgs.runCommand "grafana-provisioning" { nativeBuildInputs = [ pkgs.xorg.lndir ]; } ''
-    mkdir -p $out/{alerting,datasources,dashboards,notifiers,plugins}
+    mkdir -p $out/{alerting,datasources,dashboards,plugins}
     ${ln { src = datasourceFileOrDir;    dir = "datasources"; filename = "datasource"; }}
     ${ln { src = dashboardFileOrDir;     dir = "dashboards";  filename = "dashboard"; }}
-    ${ln { src = notifierFileOrDir;      dir = "notifiers";   filename = "notifier"; }}
     ${ln { src = rulesFileOrDir;         dir = "alerting";    filename = "rules"; }}
     ${ln { src = contactPointsFileOrDir; dir = "alerting";    filename = "contactPoints"; }}
     ${ln { src = policiesFileOrDir;      dir = "alerting";    filename = "policies"; }}
@@ -161,73 +153,13 @@ let
       };
     };
   };
-
-  grafanaTypes.notifierConfig = types.submodule {
-    options = {
-      name = mkOption {
-        type = types.str;
-        default = "default";
-        description = "Notifier name.";
-      };
-      type = mkOption {
-        type = types.enum [ "dingding" "discord" "email" "googlechat" "hipchat" "kafka" "line" "teams" "opsgenie" "pagerduty" "prometheus-alertmanager" "pushover" "sensu" "sensugo" "slack" "telegram" "threema" "victorops" "webhook" ];
-        description = "Notifier type.";
-      };
-      uid = mkOption {
-        type = types.str;
-        description = "Unique notifier identifier.";
-      };
-      org_id = mkOption {
-        type = types.int;
-        default = 1;
-        description = "Organization ID.";
-      };
-      org_name = mkOption {
-        type = types.str;
-        default = "Main Org.";
-        description = "Organization name.";
-      };
-      is_default = mkOption {
-        type = types.bool;
-        description = "Is the default notifier.";
-        default = false;
-      };
-      send_reminder = mkOption {
-        type = types.bool;
-        default = true;
-        description = "Should the notifier be sent reminder notifications while alerts continue to fire.";
-      };
-      frequency = mkOption {
-        type = types.str;
-        default = "5m";
-        description = "How frequently should the notifier be sent reminders.";
-      };
-      disable_resolve_message = mkOption {
-        type = types.bool;
-        default = false;
-        description = "Turn off the message that sends when an alert returns to OK.";
-      };
-      settings = mkOption {
-        type = types.nullOr types.attrs;
-        default = null;
-        description = "Settings for the notifier type.";
-      };
-      secure_settings = mkOption {
-        type = types.nullOr types.attrs;
-        default = null;
-        description = ''
-          Secure settings for the notifier type. Please note that the contents of this option
-          will end up in a world-readable Nix store. Use the file provider
-          pointing at a reasonably secured file in the local filesystem
-          to work around that. Look at the documentation for details:
-          <https://grafana.com/docs/grafana/latest/setup-grafana/configure-grafana/#file-provider>
-        '';
-      };
-    };
-  };
 in
 {
   imports = [
+    (mkRemovedOptionModule [ "services" "grafana" "provision" "notifiers" ] ''
+      Notifiers (services.grafana.provision.notifiers) were removed in Grafana 11.
+    '')
+
     (mkRenamedOptionModule [ "services" "grafana" "protocol" ] [ "services" "grafana" "settings" "server" "protocol" ])
     (mkRenamedOptionModule [ "services" "grafana" "addr" ] [ "services" "grafana" "settings" "server" "http_addr" ])
     (mkRenamedOptionModule [ "services" "grafana" "port" ] [ "services" "grafana" "settings" "server" "http_port" ])
@@ -1256,15 +1188,6 @@ in
         };
       };
 
-
-      notifiers = mkOption {
-        description = "Grafana notifier configuration.";
-        default = [ ];
-        type = types.listOf grafanaTypes.notifierConfig;
-        apply = x: map _filter x;
-      };
-
-
       alerting = {
         rules = {
           path = mkOption {
@@ -1746,12 +1669,6 @@ in
             Use file provider or an env-var instead.
           '';
 
-        # Warn about deprecated notifiers.
-        deprecatedNotifiers = optional (cfg.provision.notifiers != [ ]) ''
-          Notifiers are deprecated upstream and will be removed in Grafana 11.
-          Use `services.grafana.provision.alerting.contactPoints` instead.
-        '';
-
         # Ensure that `secureJsonData` of datasources provisioned via `datasources.settings`
         # only uses file/env providers.
         secureJsonDataWithoutFileProvider = optional
@@ -1770,15 +1687,10 @@ in
             Declarations in the `secureJsonData`-block of a datasource will be leaked to the
             Nix store unless a file-provider or an env-var is used!
           '';
-
-        notifierSecureSettingsWithoutFileProvider = optional
-          (any (x: x.secure_settings != null) cfg.provision.notifiers)
-          "Notifier secure settings will be stored as plaintext in the Nix store! Use file provider instead.";
       in
       passwordWithoutFileProvider
-      ++ deprecatedNotifiers
       ++ secureJsonDataWithoutFileProvider
-      ++ notifierSecureSettingsWithoutFileProvider;
+      ;
 
     environment.systemPackages = [ cfg.package ];
 
diff --git a/nixos/modules/services/monitoring/loki.nix b/nixos/modules/services/monitoring/loki.nix
index ba63f95e7f1a8..307119ecbf8ba 100644
--- a/nixos/modules/services/monitoring/loki.nix
+++ b/nixos/modules/services/monitoring/loki.nix
@@ -94,11 +94,24 @@ in {
     systemd.services.loki = {
       description = "Loki Service Daemon";
       wantedBy = [ "multi-user.target" ];
+      after = [ "network.target" ];
 
       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/monitoring/netdata.nix b/nixos/modules/services/monitoring/netdata.nix
index 90e00e91deed2..8f89408bdea59 100644
--- a/nixos/modules/services/monitoring/netdata.nix
+++ b/nixos/modules/services/monitoring/netdata.nix
@@ -13,6 +13,9 @@ let
     ln -s /run/wrappers/bin/slabinfo.plugin $out/libexec/netdata/plugins.d/slabinfo.plugin
     ln -s /run/wrappers/bin/freeipmi.plugin $out/libexec/netdata/plugins.d/freeipmi.plugin
     ln -s /run/wrappers/bin/systemd-journal.plugin $out/libexec/netdata/plugins.d/systemd-journal.plugin
+    ln -s /run/wrappers/bin/logs-management.plugin $out/libexec/netdata/plugins.d/logs-management.plugin
+    ln -s /run/wrappers/bin/network-viewer.plugin $out/libexec/netdata/plugins.d/network-viewer.plugin
+    ln -s /run/wrappers/bin/debugfs.plugin $out/libexec/netdata/plugins.d/debugfs.plugin
   '';
 
   plugins = [
@@ -47,6 +50,7 @@ let
 
   defaultUser = "netdata";
 
+  isThereAnyWireGuardTunnels = config.networking.wireguard.enable || lib.any (c: lib.hasAttrByPath [ "netdevConfig" "Kind" ] c && c.netdevConfig.Kind == "wireguard") (builtins.attrValues config.systemd.network.netdevs);
 in {
   options = {
     services.netdata = {
@@ -86,6 +90,14 @@ in {
             Whether to enable python-based plugins
           '';
         };
+        recommendedPythonPackages = mkOption {
+          type = types.bool;
+          default = false;
+          description = ''
+            Whether to enable a set of recommended Python plugins
+            by installing extra Python packages.
+          '';
+        };
         extraPackages = mkOption {
           type = types.functionTo (types.listOf types.package);
           default = ps: [];
@@ -198,13 +210,26 @@ in {
         }
       ];
 
+    # Includes a set of recommended Python plugins in exchange of imperfect disk consumption.
+    services.netdata.python.extraPackages = lib.mkIf cfg.python.recommendedPythonPackages (ps: [
+      ps.requests
+      ps.pandas
+      ps.numpy
+      ps.psycopg2
+      ps.python-ldap
+      ps.netdata-pandas
+      ps.changefinder
+    ]);
+
     services.netdata.configDir.".opt-out-from-anonymous-statistics" = mkIf (!cfg.enableAnalyticsReporting) (pkgs.writeText ".opt-out-from-anonymous-statistics" "");
     environment.etc."netdata/netdata.conf".source = configFile;
     environment.etc."netdata/conf.d".source = configDirectory;
 
     systemd.services.netdata = {
       description = "Real time performance monitoring";
-      after = [ "network.target" ];
+      after = [ "network.target" "suid-sgid-wrappers.service" ];
+      # No wrapper means no "useful" netdata.
+      requires = [ "suid-sgid-wrappers.service" ];
       wantedBy = [ "multi-user.target" ];
       path = (with pkgs; [
           curl
@@ -213,10 +238,16 @@ in {
           which
           procps
           bash
+          nvme-cli # for go.d
+          iw # for charts.d
+          apcupsd # for charts.d
+          # TODO: firehol # for FireQoS -- this requires more NixOS module support.
           util-linux # provides logger command; required for syslog health alarms
       ])
         ++ lib.optional cfg.python.enable (pkgs.python3.withPackages cfg.python.extraPackages)
-        ++ lib.optional config.virtualisation.libvirtd.enable (config.virtualisation.libvirtd.package);
+        ++ lib.optional config.virtualisation.libvirtd.enable config.virtualisation.libvirtd.package
+        ++ lib.optional config.virtualisation.docker.enable config.virtualisation.docker.package
+        ++ lib.optionals config.virtualisation.podman.enable [ pkgs.jq config.virtualisation.podman.package ];
       environment = {
         PYTHONPATH = "${cfg.package}/libexec/netdata/python.d/python_modules";
         NETDATA_PIPENAME = "/run/netdata/ipc";
@@ -256,6 +287,8 @@ in {
         # Configuration directory and mode
         ConfigurationDirectory = "netdata";
         ConfigurationDirectoryMode = "0755";
+        # AmbientCapabilities
+        AmbientCapabilities = lib.optional isThereAnyWireGuardTunnels "CAP_NET_ADMIN";
         # Capabilities
         CapabilityBoundingSet = [
           "CAP_DAC_OVERRIDE"      # is required for freeipmi and slabinfo plugins
@@ -269,7 +302,7 @@ in {
           "CAP_SYS_CHROOT"        # is required for cgroups plugin
           "CAP_SETUID"            # is required for cgroups and cgroups-network plugins
           "CAP_SYSLOG"            # is required for systemd-journal plugin
-        ];
+        ] ++ lib.optional isThereAnyWireGuardTunnels "CAP_NET_ADMIN";
         # Sandboxing
         ProtectSystem = "full";
         ProtectHome = "read-only";
@@ -308,6 +341,14 @@ in {
         permissions = "u+rx,g+x,o-rwx";
       };
 
+      "debugfs.plugin" = {
+        source = "${cfg.package}/libexec/netdata/plugins.d/debugfs.plugin.org";
+        capabilities = "cap_dac_read_search+ep";
+        owner = cfg.user;
+        group = cfg.group;
+        permissions = "u+rx,g+x,o-rwx";
+      };
+
       "cgroup-network" = {
         source = "${cfg.package}/libexec/netdata/plugins.d/cgroup-network.org";
         capabilities = "cap_setuid+ep";
@@ -332,6 +373,14 @@ in {
         permissions = "u+rx,g+x,o-rwx";
       };
 
+      "logs-management.plugin" = {
+        source = "${cfg.package}/libexec/netdata/plugins.d/logs-management.plugin.org";
+        capabilities = "cap_dac_read_search,cap_syslog+ep";
+        owner = cfg.user;
+        group = cfg.group;
+        permissions = "u+rx,g+x,o-rwx";
+      };
+
       "slabinfo.plugin" = {
         source = "${cfg.package}/libexec/netdata/plugins.d/slabinfo.plugin.org";
         capabilities = "cap_dac_override+ep";
@@ -348,6 +397,14 @@ in {
         group = cfg.group;
         permissions = "u+rx,g+x,o-rwx";
       };
+    } // optionalAttrs (cfg.package.withNetworkViewer) {
+      "network-viewer.plugin" = {
+        source = "${cfg.package}/libexec/netdata/plugins.d/network-viewer.plugin.org";
+        capabilities = "cap_sys_admin,cap_dac_read_search,cap_sys_ptrace+ep";
+        owner = cfg.user;
+        group = cfg.group;
+        permissions = "u+rx,g+x,o-rwx";
+      };
     };
 
     security.pam.loginLimits = [
@@ -359,6 +416,8 @@ in {
       ${defaultUser} = {
         group = defaultUser;
         isSystemUser = true;
+        extraGroups = lib.optional config.virtualisation.docker.enable "docker"
+          ++ lib.optional config.virtualisation.podman.enable "podman";
       };
     };
 
diff --git a/nixos/modules/services/monitoring/prometheus/alertmanager-webhook-logger.nix b/nixos/modules/services/monitoring/prometheus/alertmanager-webhook-logger.nix
new file mode 100644
index 0000000000000..b4307a76e1b02
--- /dev/null
+++ b/nixos/modules/services/monitoring/prometheus/alertmanager-webhook-logger.nix
@@ -0,0 +1,70 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.services.prometheus.alertmanagerWebhookLogger;
+in
+{
+  options.services.prometheus.alertmanagerWebhookLogger = {
+    enable = mkEnableOption "Alertmanager Webhook Logger";
+
+    package = mkPackageOption pkgs "alertmanager-webhook-logger" { };
+
+    extraFlags = mkOption {
+      type = types.listOf types.str;
+      default = [];
+      description = "Extra command line options to pass to alertmanager-webhook-logger.";
+    };
+  };
+
+  config = mkIf cfg.enable {
+    systemd.services.alertmanager-webhook-logger = {
+      description = "Alertmanager Webhook Logger";
+
+      wantedBy = [ "multi-user.target" ];
+      after = [ "network-online.target" ];
+      wants = [ "network-online.target" ];
+
+      serviceConfig = {
+        ExecStart = ''
+          ${cfg.package}/bin/alertmanager-webhook-logger \
+          ${escapeShellArgs cfg.extraFlags}
+        '';
+
+        DynamicUser = true;
+        NoNewPrivileges = true;
+
+        ProtectProc = "invisible";
+        ProtectSystem = "strict";
+        ProtectHome = "tmpfs";
+
+        PrivateTmp = true;
+        PrivateDevices = true;
+        PrivateIPC = true;
+
+        ProtectHostname = true;
+        ProtectClock = true;
+        ProtectKernelTunables = true;
+        ProtectKernelModules = true;
+        ProtectKernelLogs = true;
+        ProtectControlGroups = true;
+
+        RestrictAddressFamilies = [ "AF_INET" "AF_INET6" ];
+        RestrictRealtime = true;
+        RestrictSUIDSGID = true;
+
+        SystemCallFilter = [
+          "@system-service"
+          "~@cpu-emulation"
+          "~@privileged"
+          "~@reboot"
+          "~@setuid"
+          "~@swap"
+        ];
+      };
+    };
+  };
+
+  meta.maintainers = [ maintainers.jpds ];
+}
diff --git a/nixos/modules/services/monitoring/prometheus/default.nix b/nixos/modules/services/monitoring/prometheus/default.nix
index 7e707a13b7903..4de80acfa9a8b 100644
--- a/nixos/modules/services/monitoring/prometheus/default.nix
+++ b/nixos/modules/services/monitoring/prometheus/default.nix
@@ -181,6 +181,10 @@ let
         communicating with external systems (federation, remote
         storage, Alertmanager).
       '';
+
+      query_log_file = mkOpt types.str ''
+        Path to the file prometheus should write its query log to.
+      '';
     };
   };
 
diff --git a/nixos/modules/services/monitoring/prometheus/exporters/bitcoin.nix b/nixos/modules/services/monitoring/prometheus/exporters/bitcoin.nix
index e44140b1f51a0..e1b7dc91a0d77 100644
--- a/nixos/modules/services/monitoring/prometheus/exporters/bitcoin.nix
+++ b/nixos/modules/services/monitoring/prometheus/exporters/bitcoin.nix
@@ -7,6 +7,8 @@ in
 {
   port = 9332;
   extraOpts = {
+    package = lib.mkPackageOption pkgs "prometheus-bitcoin-exporter" { };
+
     rpcUser = mkOption {
       type = types.str;
       default = "bitcoinrpc";
@@ -65,7 +67,7 @@ in
   serviceOpts = {
     script = ''
       export BITCOIN_RPC_PASSWORD=$(cat ${cfg.rpcPasswordFile})
-      exec ${pkgs.prometheus-bitcoin-exporter}/bin/bitcoind-monitor.py
+      exec ${cfg.package}/bin/bitcoind-monitor.py
     '';
 
     environment = {
diff --git a/nixos/modules/services/monitoring/scrutiny.nix b/nixos/modules/services/monitoring/scrutiny.nix
index 031f5a30cada6..c649d333e401a 100644
--- a/nixos/modules/services/monitoring/scrutiny.nix
+++ b/nixos/modules/services/monitoring/scrutiny.nix
@@ -140,8 +140,8 @@ in
 
             options.api.endpoint = mkOption {
               type = str;
-              default = "http://localhost:${toString cfg.settings.web.listen.port}";
-              defaultText = literalExpression ''"http://localhost:''${config.services.scrutiny.settings.web.listen.port}"'';
+              default = "http://${cfg.settings.web.listen.host}:${toString cfg.settings.web.listen.port}";
+              defaultText = literalExpression ''"http://''${config.services.scrutiny.settings.web.listen.host}:''${config.services.scrutiny.settings.web.listen.port}"'';
               description = "Scrutiny app API endpoint for sending metrics to.";
             };
 
diff --git a/nixos/modules/services/monitoring/zabbix-proxy.nix b/nixos/modules/services/monitoring/zabbix-proxy.nix
index 7fa471b6404a8..dec403df85ea8 100644
--- a/nixos/modules/services/monitoring/zabbix-proxy.nix
+++ b/nixos/modules/services/monitoring/zabbix-proxy.nix
@@ -103,7 +103,7 @@ in
 
         port = mkOption {
           type = types.port;
-          default = if cfg.database.type == "mysql" then mysql.port else pgsql.services.port;
+          default = if cfg.database.type == "mysql" then mysql.port else pgsql.settings.port;
           defaultText = literalExpression ''
             if config.${opt.database.type} == "mysql"
             then config.${options.services.mysql.port}
diff --git a/nixos/modules/services/network-filesystems/davfs2.nix b/nixos/modules/services/network-filesystems/davfs2.nix
index 23c04658031fb..49a363476c975 100644
--- a/nixos/modules/services/network-filesystems/davfs2.nix
+++ b/nixos/modules/services/network-filesystems/davfs2.nix
@@ -4,7 +4,7 @@ let
   inherit (lib.attrsets) optionalAttrs;
   inherit (lib.generators) toINIWithGlobalSection;
   inherit (lib.lists) optional;
-  inherit (lib.modules) mkIf;
+  inherit (lib.modules) mkIf mkRemovedOptionModule;
   inherit (lib.options) literalExpression mkEnableOption mkOption;
   inherit (lib.strings) escape;
   inherit (lib.types) attrsOf bool int lines oneOf str submodule;
@@ -20,17 +20,20 @@ let
     else toString value;
 
   configFile = pkgs.writeText "davfs2.conf" (
-    if (cfg.settings != { }) then
-      (toINIWithGlobalSection {
-        mkSectionName = escapeString;
-        mkKeyValue = k: v: "${k} ${formatValue v}";
-      } cfg.settings)
-    else
-      cfg.extraConfig
-  );
+    toINIWithGlobalSection {
+      mkSectionName = escapeString;
+      mkKeyValue = k: v: "${k} ${formatValue v}";
+    } cfg.settings);
 in
 {
 
+  imports = [
+    (mkRemovedOptionModule [ "services" "davfs2" "extraConfig" ] ''
+      The option extraConfig got removed, please migrate to
+      services.davfs2.settings instead.
+    '')
+  ];
+
   options.services.davfs2 = {
     enable = mkEnableOption "davfs2";
 
@@ -53,29 +56,6 @@ in
       '';
     };
 
-    extraConfig = mkOption {
-      type = lines;
-      default = "";
-      example = ''
-        proxy foo.bar:8080
-        use_locks 0
-
-        [/media/dav]
-        use_locks 1
-
-        [/home/otto/mywebspace]
-        gui_optimize 1
-      '';
-      description = ''
-        Extra lines appended to the configuration of davfs2.
-        See {manpage}`davfs2.conf(5)` for available settings.
-
-        **Note**: Please pass structured settings via
-        {option}`settings` instead, this option
-        will get deprecated in the future.
-      ''  ;
-    };
-
     settings = mkOption {
       type = submodule {
         freeformType = let
@@ -109,21 +89,6 @@ in
 
   config = mkIf cfg.enable {
 
-    assertions = [
-      {
-        assertion = cfg.extraConfig != "" -> cfg.settings == { };
-        message = ''
-          services.davfs2.extraConfig and services.davfs2.settings cannot be used together.
-          Please prefer using services.davfs2.settings.
-        '';
-      }
-    ];
-
-    warnings = optional (cfg.extraConfig != "") ''
-      services.davfs2.extraConfig will be deprecated in future releases;
-      please use services.davfs2.settings instead.
-    '';
-
     environment.systemPackages = [ pkgs.davfs2 ];
     environment.etc."davfs2/davfs2.conf".source = configFile;
 
diff --git a/nixos/modules/services/network-filesystems/samba.nix b/nixos/modules/services/network-filesystems/samba.nix
index 66ef3f14ed700..c70d0cf7beac3 100644
--- a/nixos/modules/services/network-filesystems/samba.nix
+++ b/nixos/modules/services/network-filesystems/samba.nix
@@ -201,14 +201,10 @@ in
               message   = "If samba.nsswins is enabled, then samba.enableWinbindd must also be enabled";
             }
           ];
-        # Always provide a smb.conf to shut up programs like smbclient and smbspool.
-        environment.etc."samba/smb.conf".source = mkOptionDefault (
-          if cfg.enable then configFile
-          else pkgs.writeText "smb-dummy.conf" "# Samba is disabled."
-        );
       }
 
       (mkIf cfg.enable {
+        environment.etc."samba/smb.conf".source = configFile;
 
         system.nssModules = optional cfg.nsswins samba;
         system.nssDatabases.hosts = optional cfg.nsswins "wins";
diff --git a/nixos/modules/services/networking/adguardhome.nix b/nixos/modules/services/networking/adguardhome.nix
index df9927351edc3..5be3e0bea224a 100644
--- a/nixos/modules/services/networking/adguardhome.nix
+++ b/nixos/modules/services/networking/adguardhome.nix
@@ -140,7 +140,7 @@ in {
       {
         assertion = cfg.settings != null
           -> !(hasAttrByPath [ "bind_port" ] cfg.settings);
-        message = "AdGuard option `settings.bind_host' has been superseded by `services.adguardhome.port'";
+        message = "AdGuard option `settings.bind_port' has been superseded by `services.adguardhome.port'";
       }
       {
         assertion = settings != null -> cfg.mutableSettings
@@ -167,8 +167,13 @@ in {
       preStart = optionalString (settings != null) ''
         if    [ -e "$STATE_DIRECTORY/AdGuardHome.yaml" ] \
            && [ "${toString cfg.mutableSettings}" = "1" ]; then
+          # First run a schema_version update on the existing configuration
+          # This ensures that both the new config and the existing one have the same schema_version
+          # Note: --check-config has the side effect of modifying the file at rest!
+          ${lib.getExe cfg.package} -c "$STATE_DIRECTORY/AdGuardHome.yaml" --check-config
+
           # Writing directly to AdGuardHome.yaml results in empty file
-          ${pkgs.yaml-merge}/bin/yaml-merge "$STATE_DIRECTORY/AdGuardHome.yaml" "${configFile}" > "$STATE_DIRECTORY/AdGuardHome.yaml.tmp"
+          ${lib.getExe pkgs.yaml-merge} "$STATE_DIRECTORY/AdGuardHome.yaml" "${configFile}" > "$STATE_DIRECTORY/AdGuardHome.yaml.tmp"
           mv "$STATE_DIRECTORY/AdGuardHome.yaml.tmp" "$STATE_DIRECTORY/AdGuardHome.yaml"
         else
           cp --force "${configFile}" "$STATE_DIRECTORY/AdGuardHome.yaml"
@@ -178,7 +183,7 @@ in {
 
       serviceConfig = {
         DynamicUser = true;
-        ExecStart = "${cfg.package}/bin/adguardhome ${args}";
+        ExecStart = "${lib.getExe cfg.package} ${args}";
         AmbientCapabilities = [ "CAP_NET_BIND_SERVICE" ]
           ++ optionals cfg.allowDHCP [ "CAP_NET_RAW" ];
         Restart = "always";
diff --git a/nixos/modules/services/networking/antennas.nix b/nixos/modules/services/networking/antennas.nix
index ef98af22f20f2..a37df953fc923 100644
--- a/nixos/modules/services/networking/antennas.nix
+++ b/nixos/modules/services/networking/antennas.nix
@@ -50,10 +50,7 @@ in
       };
 
       serviceConfig = {
-         ExecStart = "${pkgs.antennas}/bin/antennas";
-
-        # Antennas expects all resources like html and config to be relative to it's working directory
-        WorkingDirectory = "${pkgs.antennas}/libexec/antennas/deps/antennas/";
+        ExecStart = "${pkgs.antennas}/bin/antennas";
 
         # Hardening
         CapabilityBoundingSet = [ "" ];
diff --git a/nixos/modules/services/networking/aria2.nix b/nixos/modules/services/networking/aria2.nix
index f32f5682c9801..f0d5c5c8a21e3 100644
--- a/nixos/modules/services/networking/aria2.nix
+++ b/nixos/modules/services/networking/aria2.nix
@@ -1,98 +1,132 @@
 { config, lib, pkgs, ... }:
 
-with lib;
-
 let
   cfg = config.services.aria2;
 
   homeDir = "/var/lib/aria2";
-
-  settingsDir = "${homeDir}";
-  sessionFile = "${homeDir}/aria2.session";
-  downloadDir = "${homeDir}/Downloads";
-
-  rangesToStringList = map (x: builtins.toString x.from +"-"+ builtins.toString x.to);
-
-  settingsFile = pkgs.writeText "aria2.conf"
-  ''
-    dir=${cfg.downloadDir}
-    listen-port=${concatStringsSep "," (rangesToStringList cfg.listenPortRange)}
-    rpc-listen-port=${toString cfg.rpcListenPort}
-  '';
-
+  defaultRpcListenPort = 6800;
+  defaultDir = "${homeDir}/Downloads";
+
+  portRangesToString = ranges: lib.concatStringsSep "," (map
+    (x:
+      if x.from == x.to
+      then builtins.toString x.from
+      else builtins.toString x.from + "-" + builtins.toString x.to
+    )
+    ranges);
+
+  customToKeyValue = lib.generators.toKeyValue {
+    mkKeyValue = lib.generators.mkKeyValueDefault
+      {
+        mkValueString = v:
+          if builtins.isList v then portRangesToString v
+          else lib.generators.mkValueStringDefault { } v;
+      } "=";
+  };
 in
 {
   imports = [
-    (mkRemovedOptionModule [ "services" "aria2" "rpcSecret" ] "Use services.aria2.rpcSecretFile instead")
+    (lib.mkRemovedOptionModule [ "services" "aria2" "rpcSecret" ] "Use services.aria2.rpcSecretFile instead")
+    (lib.mkRemovedOptionModule [ "services" "aria2" "extraArguments" ] "Use services.aria2.settings instead")
+    (lib.mkRenamedOptionModule [ "services" "aria2" "downloadDir" ] [ "services" "aria2" "settings" "dir" ])
+    (lib.mkRenamedOptionModule [ "services" "aria2" "listenPortRange" ] [ "services" "aria2" "settings" "listen-port" ])
+    (lib.mkRenamedOptionModule [ "services" "aria2" "rpcListenPort" ] [ "services" "aria2" "settings" "rpc-listen-port" ])
   ];
 
   options = {
     services.aria2 = {
-      enable = mkOption {
-        type = types.bool;
+      enable = lib.mkOption {
+        type = lib.types.bool;
         default = false;
         description = ''
           Whether or not to enable the headless Aria2 daemon service.
 
-          Aria2 daemon can be controlled via the RPC interface using
-          one of many WebUI (http://localhost:6800/ by default).
+          Aria2 daemon can be controlled via the RPC interface using one of many
+          WebUIs (http://localhost:${toString defaultRpcListenPort}/ by default).
 
-          Targets are downloaded to ${downloadDir} by default and are
-          accessible to users in the "aria2" group.
+          Targets are downloaded to `${defaultDir}` by default and are
+          accessible to users in the `aria2` group.
         '';
       };
-      openPorts = mkOption {
-        type = types.bool;
+      openPorts = lib.mkOption {
+        type = lib.types.bool;
         default = false;
         description = ''
-          Open listen and RPC ports found in listenPortRange and rpcListenPort
-          options in the firewall.
-        '';
-      };
-      downloadDir = mkOption {
-        type = types.path;
-        default = downloadDir;
-        description = ''
-          Directory to store downloaded files.
-        '';
-      };
-      listenPortRange = mkOption {
-        type = types.listOf types.attrs;
-        default = [ { from = 6881; to = 6999; } ];
-        description = ''
-          Set UDP listening port range used by DHT(IPv4, IPv6) and UDP tracker.
+          Open listen and RPC ports found in `settings.listen-port` and
+          `settings.rpc-listen-port` options in the firewall.
         '';
       };
-      rpcListenPort = mkOption {
-        type = types.int;
-        default = 6800;
-        description = "Specify a port number for JSON-RPC/XML-RPC server to listen to. Possible Values: 1024-65535";
-      };
-      rpcSecretFile = mkOption {
-        type = types.path;
+      rpcSecretFile = lib.mkOption {
+        type = lib.types.path;
         example = "/run/secrets/aria2-rpc-token.txt";
         description = ''
           A file containing the RPC secret authorization token.
           Read https://aria2.github.io/manual/en/html/aria2c.html#rpc-auth to know how this option value is used.
         '';
       };
-      extraArguments = mkOption {
-        type = types.separatedString " ";
-        example = "--rpc-listen-all --remote-time=true";
-        default = "";
+      settings = lib.mkOption {
         description = ''
-          Additional arguments to be passed to Aria2.
+          Generates the `aria2.conf` file. Refer to [the documentation][0] for
+          all possible settings.
+
+          [0]: https://aria2.github.io/manual/en/html/aria2c.html#synopsis
         '';
+        default = { };
+        type = lib.types.submodule {
+          freeformType = with lib.types; attrsOf (oneOf [ bool int float singleLineStr ]);
+          options = {
+            save-session = lib.mkOption {
+              type = lib.types.singleLineStr;
+              default = "${homeDir}/aria2.session";
+              description = "Save error/unfinished downloads to FILE on exit.";
+            };
+            dir = lib.mkOption {
+              type = lib.types.singleLineStr;
+              default = defaultDir;
+              description = "Directory to store downloaded files.";
+            };
+            conf-path = lib.mkOption {
+              type = lib.types.singleLineStr;
+              default = "${homeDir}/aria2.conf";
+              description = "Configuration file path.";
+            };
+            enable-rpc = lib.mkOption {
+              type = lib.types.bool;
+              default = true;
+              description = "Enable JSON-RPC/XML-RPC server.";
+            };
+            listen-port = lib.mkOption {
+              type = with lib.types; listOf (attrsOf port);
+              default = [{ from = 6881; to = 6999; }];
+              description = "Set UDP listening port range used by DHT(IPv4, IPv6) and UDP tracker.";
+            };
+            rpc-listen-port = lib.mkOption {
+              type = lib.types.port;
+              default = defaultRpcListenPort;
+              description = "Specify a port number for JSON-RPC/XML-RPC server to listen to. Possible Values: 1024-65535";
+            };
+          };
+        };
       };
     };
   };
 
-  config = mkIf cfg.enable {
+  config = lib.mkIf cfg.enable {
+    assertions = [
+      {
+        assertion = cfg.settings.enable-rpc;
+        message = "RPC has to be enabled, the default module option takes care of that.";
+      }
+      {
+        assertion = !(cfg.settings ? rpc-secret);
+        message = "Set the RPC secret through services.aria2.rpcSecretFile so it will not end up in the world-readable nix store.";
+      }
+    ];
 
     # Need to open ports for proper functioning
-    networking.firewall = mkIf cfg.openPorts {
-      allowedUDPPortRanges = config.services.aria2.listenPortRange;
-      allowedTCPPorts = [ config.services.aria2.rpcListenPort ];
+    networking.firewall = lib.mkIf cfg.openPorts {
+      allowedUDPPortRanges = config.services.aria2.settings.listen-port;
+      allowedTCPPorts = [ config.services.aria2.settings.rpc-listen-port ];
     };
 
     users.users.aria2 = {
@@ -107,7 +141,7 @@ in
 
     systemd.tmpfiles.rules = [
       "d '${homeDir}' 0770 aria2 aria2 - -"
-      "d '${config.services.aria2.downloadDir}' 0770 aria2 aria2 - -"
+      "d '${config.services.aria2.settings.dir}' 0770 aria2 aria2 - -"
     ];
 
     systemd.services.aria2 = {
@@ -115,22 +149,25 @@ in
       after = [ "network.target" ];
       wantedBy = [ "multi-user.target" ];
       preStart = ''
-        if [[ ! -e "${sessionFile}" ]]
+        if [[ ! -e "${cfg.settings.save-session}" ]]
         then
-          touch "${sessionFile}"
+          touch "${cfg.settings.save-session}"
         fi
-        cp -f "${settingsFile}" "${settingsDir}/aria2.conf"
-        echo "rpc-secret=$(cat "$CREDENTIALS_DIRECTORY/rpcSecretFile")" >> "${settingsDir}/aria2.conf"
+        cp -f "${pkgs.writeText "aria2.conf" (customToKeyValue cfg.settings)}" "${cfg.settings.conf-path}"
+        chmod +w "${cfg.settings.conf-path}"
+        echo "rpc-secret=$(cat "$CREDENTIALS_DIRECTORY/rpcSecretFile")" >> "${cfg.settings.conf-path}"
       '';
 
       serviceConfig = {
         Restart = "on-abort";
-        ExecStart = "${pkgs.aria2}/bin/aria2c --enable-rpc --conf-path=${settingsDir}/aria2.conf ${config.services.aria2.extraArguments} --save-session=${sessionFile}";
+        ExecStart = "${pkgs.aria2}/bin/aria2c --conf-path=${cfg.settings.conf-path}";
         ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
         User = "aria2";
         Group = "aria2";
-        LoadCredential="rpcSecretFile:${cfg.rpcSecretFile}";
+        LoadCredential = "rpcSecretFile:${cfg.rpcSecretFile}";
       };
     };
   };
+
+  meta.maintainers = [ lib.maintainers.timhae ];
 }
diff --git a/nixos/modules/services/networking/clatd.nix b/nixos/modules/services/networking/clatd.nix
index 76e0c130ca466..de6cde4e979c0 100644
--- a/nixos/modules/services/networking/clatd.nix
+++ b/nixos/modules/services/networking/clatd.nix
@@ -43,7 +43,6 @@ in
 
       serviceConfig = {
         ExecStart = "${cfg.package}/bin/clatd -c ${configFile}";
-        startLimitIntervalSec = 0;
 
         # Hardening
         CapabilityBoundingSet = [
diff --git a/nixos/modules/services/networking/ddclient.nix b/nixos/modules/services/networking/ddclient.nix
index b912550e1155e..272a50eb92de8 100644
--- a/nixos/modules/services/networking/ddclient.nix
+++ b/nixos/modules/services/networking/ddclient.nix
@@ -11,7 +11,9 @@ let
     # This file can be used as a template for configFile or is automatically generated by Nix options.
     cache=${dataDir}/ddclient.cache
     foreground=YES
-    use=${cfg.use}
+    ${lib.optionalString (cfg.use != "") "use=${cfg.use}"}
+    ${lib.optionalString (cfg.use == "" && cfg.usev4 != "") "usev4=${cfg.usev4}"}
+    ${lib.optionalString (cfg.use == "" && cfg.usev6 != "") "usev6=${cfg.usev6}"}
     login=${cfg.username}
     password=${if cfg.protocol == "nsupdate" then "/run/${RuntimeDirectory}/ddclient.key" else "@password_placeholder@"}
     protocol=${cfg.protocol}
@@ -163,12 +165,26 @@ with lib;
       };
 
       use = mkOption {
-        default = "web, web=checkip.dyndns.com/, web-skip='Current IP Address: '";
+        default = "";
         type = str;
         description = ''
           Method to determine the IP address to send to the dynamic DNS provider.
         '';
       };
+      usev4 = mkOption {
+        default = "webv4, webv4=checkip.dyndns.com/, webv4-skip='Current IP Address: '";
+        type = str;
+        description = ''
+          Method to determine the IPv4 address to send to the dynamic DNS provider. Only used if `use` is not set.
+        '';
+      };
+      usev6 = mkOption {
+        default = "webv6, webv6=checkipv6.dyndns.com/, webv6-skip='Current IP Address: '";
+        type = str;
+        description = ''
+          Method to determine the IPv6 address to send to the dynamic DNS provider. Only used if `use` is not set.
+        '';
+      };
 
       verbose = mkOption {
         default = false;
@@ -204,6 +220,8 @@ with lib;
   ###### implementation
 
   config = mkIf config.services.ddclient.enable {
+    warnings = lib.optional (cfg.use != "") "Setting `use` is deprecated, ddclient now supports `usev4` and `usev6` for separate IPv4/IPv6 configuration.";
+
     systemd.services.ddclient = {
       description = "Dynamic DNS Client";
       wantedBy = [ "multi-user.target" ];
diff --git a/nixos/modules/services/networking/frr.nix b/nixos/modules/services/networking/frr.nix
index 7f611ce7b1c7d..df2b4035d2f07 100644
--- a/nixos/modules/services/networking/frr.nix
+++ b/nixos/modules/services/networking/frr.nix
@@ -23,10 +23,9 @@ let
     "pbr"
     "bfd"
     "fabric"
-    "mgmt"
   ];
 
-  allServices = services ++ [ "zebra" ];
+  allServices = services ++ [ "zebra" "mgmt" ];
 
   isEnabled = service: cfg.${service}.enable;
 
@@ -137,6 +136,20 @@ in
             '';
           };
         };
+        mgmt = (serviceOptions "mgmt") // {
+          enable = mkOption {
+            type = types.bool;
+            default = isEnabled "static";
+            defaultText = lib.literalExpression "config.services.frr.static.enable";
+            description = ''
+              Whether to enable the Configuration management daemon.
+
+              The Configuration management daemon is automatically
+              enabled if needed, at the moment this is when staticd
+              is enabled.
+            '';
+          };
+        };
       };
     }
     { options.services.frr = (genAttrs services serviceOptions); }
@@ -164,7 +177,7 @@ in
 
     environment.etc = let
       mkEtcLink = service: {
-        name = "frr/${service}.conf";
+        name = "frr/${daemonName service}.conf";
         value.source = configFile service;
       };
     in
@@ -196,18 +209,18 @@ in
               unitConfig.Documentation = if service == "zebra" then "man:zebra(8)"
                 else "man:${daemon}(8) man:zebra(8)";
 
-              restartTriggers = [
+              restartTriggers = mkIf (service != "mgmt") [
                 (configFile service)
               ];
-              reloadIfChanged = true;
+              reloadIfChanged = (service != "mgmt");
 
               serviceConfig = {
                 PIDFile = "frr/${daemon}.pid";
-                ExecStart = "${pkgs.frr}/libexec/frr/${daemon} -f /etc/frr/${service}.conf"
+                ExecStart = "${pkgs.frr}/libexec/frr/${daemon}"
                   + optionalString (scfg.vtyListenAddress != "") " -A ${scfg.vtyListenAddress}"
                   + optionalString (scfg.vtyListenPort != null) " -P ${toString scfg.vtyListenPort}"
                   + " " + (concatStringsSep " " scfg.extraOptions);
-                ExecReload = "${pkgs.python3.interpreter} ${pkgs.frr}/libexec/frr/frr-reload.py --reload --daemon ${daemonName service} --bindir ${pkgs.frr}/bin --rundir /run/frr /etc/frr/${service}.conf";
+                ExecReload = mkIf (service != "mgmt") "${pkgs.python3.interpreter} ${pkgs.frr}/libexec/frr/frr-reload.py --reload --daemon ${daemon} --bindir ${pkgs.frr}/bin --rundir /run/frr /etc/frr/${daemon}.conf";
                 Restart = "on-abnormal";
               };
             });
diff --git a/nixos/modules/services/networking/git-daemon.nix b/nixos/modules/services/networking/git-daemon.nix
index 6be72505c216e..522e6b14f868f 100644
--- a/nixos/modules/services/networking/git-daemon.nix
+++ b/nixos/modules/services/networking/git-daemon.nix
@@ -27,6 +27,8 @@ in
         '';
       };
 
+      package = mkPackageOption pkgs "git" { };
+
       basePath = mkOption {
         type = types.str;
         default = "";
@@ -119,7 +121,7 @@ in
     systemd.services.git-daemon = {
       after = [ "network.target" ];
       wantedBy = [ "multi-user.target" ];
-      script = "${pkgs.git}/bin/git daemon --reuseaddr "
+      script = "${getExe cfg.package} daemon --reuseaddr "
         + (optionalString (cfg.basePath != "") "--base-path=${cfg.basePath} ")
         + (optionalString (cfg.listenAddress != "") "--listen=${cfg.listenAddress} ")
         + "--port=${toString cfg.port} --user=${cfg.user} --group=${cfg.group} ${cfg.options} "
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/inadyn.nix b/nixos/modules/services/networking/inadyn.nix
index baa4302096c2c..7022673538c8a 100644
--- a/nixos/modules/services/networking/inadyn.nix
+++ b/nixos/modules/services/networking/inadyn.nix
@@ -202,7 +202,7 @@ in
         startAt = cfg.interval;
         serviceConfig = {
           Type = "oneshot";
-          ExecStart = ''${lib.getExe pkgs.inadyn} -f ${configFile} --cache-dir ''${CACHE_DIRECTORY}/inadyn -1 --foreground -l ${cfg.logLevel}'';
+          ExecStart = ''${lib.getExe pkgs.inadyn} -f ${configFile} --cache-dir ''${CACHE_DIRECTORY} -1 --foreground -l ${cfg.logLevel}'';
           LoadCredential = "config:${configFile}";
           CacheDirectory = "inadyn";
 
diff --git a/nixos/modules/services/networking/jotta-cli.md b/nixos/modules/services/networking/jotta-cli.md
index fee002a4e6046..335e5c8e38563 100644
--- a/nixos/modules/services/networking/jotta-cli.md
+++ b/nixos/modules/services/networking/jotta-cli.md
@@ -6,7 +6,7 @@ The [Jottacloud Command-line Tool](https://docs.jottacloud.com/en/articles/14368
 
 ```nix
 {
-  user.services.jotta-cli.enable = true;
+  services.jotta-cli.enable = true;
 }
 ```
 
@@ -15,7 +15,7 @@ This adds `jotta-cli` to `environment.systemPackages` and starts a user service
 ## Example Configuration {#module-services-jotta-cli-example-configuration}
 
 ```nix
-user.services.jotta-cli = {
+services.jotta-cli = {
   enable = true;
   options = [ "slow" ];
   package = pkgs.jotta-cli;
diff --git a/nixos/modules/services/networking/jotta-cli.nix b/nixos/modules/services/networking/jotta-cli.nix
index c7e6dad5453ca..e0fa1ef332fe6 100644
--- a/nixos/modules/services/networking/jotta-cli.nix
+++ b/nixos/modules/services/networking/jotta-cli.nix
@@ -2,10 +2,10 @@
 
 with lib;
 
-let cfg = config.user.services.jotta-cli;
+let cfg = config.services.jotta-cli;
 in {
   options = {
-    user.services.jotta-cli = {
+    services.jotta-cli = {
 
       enable = mkEnableOption "Jottacloud Command-line Tool";
 
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/mihomo.nix b/nixos/modules/services/networking/mihomo.nix
index 312530caeaade..d4bb10496279d 100644
--- a/nixos/modules/services/networking/mihomo.nix
+++ b/nixos/modules/services/networking/mihomo.nix
@@ -25,6 +25,7 @@ in
     webui = lib.mkOption {
       default = null;
       type = lib.types.nullOr lib.types.path;
+      example = lib.literalExpression "pkgs.metacubexd";
       description = ''
         Local web interface to use.
 
diff --git a/nixos/modules/services/networking/mycelium.nix b/nixos/modules/services/networking/mycelium.nix
index 9487a5daafee0..0d0b2945af4c1 100644
--- a/nixos/modules/services/networking/mycelium.nix
+++ b/nixos/modules/services/networking/mycelium.nix
@@ -60,6 +60,8 @@ in
     networking.firewall.allowedTCPPorts = lib.optionals cfg.openFirewall [ 9651 ];
     networking.firewall.allowedUDPPorts = lib.optionals cfg.openFirewall [ 9650 9651 ];
 
+    environment.systemPackages = [ cfg.package ];
+
     systemd.services.mycelium = {
       description = "Mycelium network";
       after = [ "network.target" ];
diff --git a/nixos/modules/services/networking/netbird.nix b/nixos/modules/services/networking/netbird.nix
index 7add377896cab..e68c39946fe3b 100644
--- a/nixos/modules/services/networking/netbird.nix
+++ b/nixos/modules/services/networking/netbird.nix
@@ -37,7 +37,6 @@ in
 {
   meta.maintainers = with maintainers; [
     misuzu
-    thubrecht
   ];
   meta.doc = ./netbird.md;
 
diff --git a/nixos/modules/services/networking/netbird/coturn.nix b/nixos/modules/services/networking/netbird/coturn.nix
index 746d70a07250d..29ff1e8fc15ee 100644
--- a/nixos/modules/services/networking/netbird/coturn.nix
+++ b/nixos/modules/services/networking/netbird/coturn.nix
@@ -60,6 +60,7 @@ in
       default = null;
       description = ''
         The password of the user used by netbird to connect to the coturn server.
+        Be advised this will be world readable in the nix store.
       '';
     };
 
@@ -142,7 +143,11 @@ in
           ];
         });
 
-      security.acme.certs.${cfg.domain}.postRun = optionalString cfg.useAcmeCertificates "systemctl restart coturn.service";
+      security.acme.certs = mkIf cfg.useAcmeCertificates {
+        ${cfg.domain}.postRun = ''
+          systemctl restart coturn.service
+        '';
+      };
 
       networking.firewall = {
         allowedUDPPorts = cfg.openPorts;
diff --git a/nixos/modules/services/networking/netbird/server.nix b/nixos/modules/services/networking/netbird/server.nix
index a4de0fda6a134..e3de286a04fa4 100644
--- a/nixos/modules/services/networking/netbird/server.nix
+++ b/nixos/modules/services/networking/netbird/server.nix
@@ -2,6 +2,7 @@
 
 let
   inherit (lib)
+    mkDefault
     mkEnableOption
     mkIf
     mkOption
@@ -15,7 +16,7 @@ in
 
 {
   meta = {
-    maintainers = with lib.maintainers; [ thubrecht ];
+    maintainers = with lib.maintainers; [patrickdag];
     doc = ./server.md;
   };
 
@@ -41,26 +42,46 @@ in
   config = mkIf cfg.enable {
     services.netbird.server = {
       dashboard = {
-        inherit (cfg) enable domain enableNginx;
+        domain = mkDefault cfg.domain;
+        enable = mkDefault cfg.enable;
+        enableNginx = mkDefault cfg.enableNginx;
 
         managementServer = "https://${cfg.domain}";
       };
 
       management =
         {
-          inherit (cfg) enable domain enableNginx;
+          domain = mkDefault cfg.domain;
+          enable = mkDefault cfg.enable;
+          enableNginx = mkDefault cfg.enableNginx;
         }
-        // (optionalAttrs cfg.coturn.enable {
+        // (optionalAttrs cfg.coturn.enable rec {
           turnDomain = cfg.domain;
           turnPort = config.services.coturn.tls-listening-port;
+          # We cannot merge a list of attrsets so we have to redefine the whole list
+          settings = {
+            TURNConfig.Turns = mkDefault [
+              {
+                Proto = "udp";
+                URI = "turn:${turnDomain}:${builtins.toString turnPort}";
+                Username = "netbird";
+                Password =
+                  if (cfg.coturn.password != null)
+                  then cfg.coturn.password
+                  else {_secret = cfg.coturn.passwordFile;};
+              }
+            ];
+          };
         });
 
       signal = {
-        inherit (cfg) enable domain enableNginx;
+        domain = mkDefault cfg.domain;
+        enable = mkDefault cfg.enable;
+        enableNginx = mkDefault cfg.enableNginx;
       };
 
       coturn = {
-        inherit (cfg) domain;
+        domain = mkDefault cfg.domain;
       };
     };
   };
diff --git a/nixos/modules/services/networking/networkmanager.nix b/nixos/modules/services/networking/networkmanager.nix
index e33bbb2af178f..b7143cf520f96 100644
--- a/nixos/modules/services/networking/networkmanager.nix
+++ b/nixos/modules/services/networking/networkmanager.nix
@@ -470,7 +470,7 @@ in
       -      [main]
       -      no-auto-default=*
       -    '''
-      +    extraConfig.main.no-auto-default = "*";
+      +    settings.main.no-auto-default = "*";
          };
       ```
     ''
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..92ecc1cb31a36 100644
--- a/nixos/modules/services/networking/rosenpass.nix
+++ b/nixos/modules/services/networking/rosenpass.nix
@@ -130,8 +130,8 @@ in
             relevant = config.systemd.network.enable;
             root = config.systemd.network.netdevs;
             peer = (x: x.wireguardPeers);
-            key = (x: if x.wireguardPeerConfig ? PublicKey then x.wireguardPeerConfig.PublicKey else null);
-            description = "${options.systemd.network.netdevs}.\"<name>\".wireguardPeers.*.wireguardPeerConfig.PublicKey";
+            key = x: x.PublicKey or null;
+            description = "${options.systemd.network.netdevs}.\"<name>\".wireguardPeers.*.PublicKey";
           }
           {
             relevant = config.networking.wireguard.enable;
@@ -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/ssh/sshd.nix b/nixos/modules/services/networking/ssh/sshd.nix
index c62bccd462d33..1e4e34a4f1675 100644
--- a/nixos/modules/services/networking/ssh/sshd.nix
+++ b/nixos/modules/services/networking/ssh/sshd.nix
@@ -5,11 +5,11 @@ with lib;
 let
 
   # The splicing information needed for nativeBuildInputs isn't available
-  # on the derivations likely to be used as `cfgc.package`.
+  # on the derivations likely to be used as `cfg.package`.
   # This middle-ground solution ensures *an* sshd can do their basic validation
   # on the configuration.
   validationPackage = if pkgs.stdenv.buildPlatform == pkgs.stdenv.hostPlatform
-    then cfgc.package
+    then cfg.package
     else pkgs.buildPackages.openssh;
 
   # dont use the "=" operator
@@ -169,6 +169,13 @@ in
         '';
       };
 
+      package = mkOption {
+        type = types.package;
+        default = config.programs.ssh.package;
+        defaultText = literalExpression "programs.ssh.package";
+        description = "OpenSSH package to use for sshd.";
+      };
+
       startWhenNeeded = mkOption {
         type = types.bool;
         default = false;
@@ -296,6 +303,17 @@ in
         '';
       };
 
+      authorizedKeysInHomedir = mkOption {
+        type = types.bool;
+        default = true;
+        description = ''
+          Enables the use of the `~/.ssh/authorized_keys` file.
+
+          Otherwise, the only files trusted by default are those in `/etc/ssh/authorized_keys.d`,
+          *i.e.* SSH keys from [](#opt-users.users._name_.openssh.authorizedKeys.keys).
+        '';
+      };
+
       authorizedKeysCommand = mkOption {
         type = types.str;
         default = "none";
@@ -331,7 +349,7 @@ in
           freeformType = settingsFormat.type;
           options = {
             AuthorizedPrincipalsFile = mkOption {
-              type = types.str;
+              type = types.nullOr types.str;
               default = "none"; # upstream default
               description = ''
                 Specifies a file that lists principal names that are accepted for certificate authentication. The default
@@ -339,16 +357,18 @@ in
               '';
             };
             LogLevel = mkOption {
-              type = types.enum [ "QUIET" "FATAL" "ERROR" "INFO" "VERBOSE" "DEBUG" "DEBUG1" "DEBUG2" "DEBUG3" ];
+              type = types.nullOr (types.enum [ "QUIET" "FATAL" "ERROR" "INFO" "VERBOSE" "DEBUG" "DEBUG1" "DEBUG2" "DEBUG3" ]);
               default = "INFO"; # upstream default
               description = ''
                 Gives the verbosity level that is used when logging messages from sshd(8). Logging with a DEBUG level
                 violates the privacy of users and is not recommended.
               '';
             };
-            UsePAM = mkEnableOption "PAM authentication" // { default = true; };
+            UsePAM =
+              mkEnableOption "PAM authentication"
+              // { default = true; type = types.nullOr types.bool; };
             UseDns = mkOption {
-              type = types.bool;
+              type = types.nullOr types.bool;
               # apply if cfg.useDns then "yes" else "no"
               default = false;
               description = ''
@@ -359,14 +379,14 @@ in
               '';
             };
             X11Forwarding = mkOption {
-              type = types.bool;
+              type = types.nullOr types.bool;
               default = false;
               description = ''
                 Whether to allow X11 connections to be forwarded.
               '';
             };
             PasswordAuthentication = mkOption {
-              type = types.bool;
+              type = types.nullOr types.bool;
               default = true;
               description = ''
                 Specifies whether password authentication is allowed.
@@ -374,20 +394,20 @@ in
             };
             PermitRootLogin = mkOption {
               default = "prohibit-password";
-              type = types.enum ["yes" "without-password" "prohibit-password" "forced-commands-only" "no"];
+              type = types.nullOr (types.enum ["yes" "without-password" "prohibit-password" "forced-commands-only" "no"]);
               description = ''
                 Whether the root user can login using ssh.
               '';
             };
             KbdInteractiveAuthentication = mkOption {
-              type = types.bool;
+              type = types.nullOr types.bool;
               default = true;
               description = ''
                 Specifies whether keyboard-interactive authentication is allowed.
               '';
             };
             GatewayPorts = mkOption {
-              type = types.str;
+              type = types.nullOr types.str;
               default = "no";
               description = ''
                 Specifies whether remote hosts are allowed to connect to
@@ -396,7 +416,7 @@ in
               '';
             };
             KexAlgorithms = mkOption {
-              type = types.listOf types.str;
+              type = types.nullOr (types.listOf types.str);
               default = [
                 "sntrup761x25519-sha512@openssh.com"
                 "curve25519-sha256"
@@ -413,7 +433,7 @@ in
               '';
             };
             Macs = mkOption {
-              type = types.listOf types.str;
+              type = types.nullOr (types.listOf types.str);
               default = [
                 "hmac-sha2-512-etm@openssh.com"
                 "hmac-sha2-256-etm@openssh.com"
@@ -429,14 +449,14 @@ in
               '';
             };
             StrictModes = mkOption {
-              type = types.bool;
+              type = types.nullOr (types.bool);
               default = true;
               description = ''
                 Whether sshd should check file modes and ownership of directories
               '';
             };
             Ciphers = mkOption {
-              type = types.listOf types.str;
+              type = types.nullOr (types.listOf types.str);
               default = [
                 "chacha20-poly1305@openssh.com"
                 "aes256-gcm@openssh.com"
@@ -491,7 +511,9 @@ in
               '';
             };
             # Disabled by default, since pam_motd handles this.
-            PrintMotd = mkEnableOption "printing /etc/motd when a user logs in interactively";
+            PrintMotd =
+              mkEnableOption "printing /etc/motd when a user logs in interactively"
+              // { type = types.nullOr types.bool; };
           };
         });
       };
@@ -533,8 +555,8 @@ in
       };
     users.groups.sshd = {};
 
-    services.openssh.moduliFile = mkDefault "${cfgc.package}/etc/ssh/moduli";
-    services.openssh.sftpServerExecutable = mkDefault "${cfgc.package}/libexec/sftp-server";
+    services.openssh.moduliFile = mkDefault "${cfg.package}/etc/ssh/moduli";
+    services.openssh.sftpServerExecutable = mkDefault "${cfg.package}/libexec/sftp-server";
 
     environment.etc = authKeysFiles // authPrincipalsFiles //
       { "ssh/moduli".source = cfg.moduliFile;
@@ -548,7 +570,7 @@ in
             wantedBy = optional (!cfg.startWhenNeeded) "multi-user.target";
             after = [ "network.target" ];
             stopIfChanged = false;
-            path = [ cfgc.package pkgs.gawk ];
+            path = [ cfg.package pkgs.gawk ];
             environment.LD_LIBRARY_PATH = nssModulesPath;
 
             restartTriggers = optionals (!cfg.startWhenNeeded) [
@@ -582,7 +604,7 @@ in
             serviceConfig =
               { ExecStart =
                   (optionalString cfg.startWhenNeeded "-") +
-                  "${cfgc.package}/bin/sshd " + (optionalString cfg.startWhenNeeded "-i ") +
+                  "${cfg.package}/bin/sshd " + (optionalString cfg.startWhenNeeded "-i ") +
                   "-D " +  # don't detach into a daemon process
                   "-f /etc/ssh/sshd_config";
                 KillMode = "process";
@@ -628,14 +650,17 @@ in
     security.pam.services.sshd = lib.mkIf cfg.settings.UsePAM
       { startSession = true;
         showMotd = true;
-        unixAuth = cfg.settings.PasswordAuthentication;
+        unixAuth =
+          if cfg.settings.PasswordAuthentication == true
+          then true
+          else false;
       };
 
     # These values are merged with the ones defined externally, see:
     # https://github.com/NixOS/nixpkgs/pull/10155
     # https://github.com/NixOS/nixpkgs/pull/41745
     services.openssh.authorizedKeysFiles =
-      [ "%h/.ssh/authorized_keys" "/etc/ssh/authorized_keys.d/%u" ];
+      lib.optional cfg.authorizedKeysInHomedir "%h/.ssh/authorized_keys" ++ [ "/etc/ssh/authorized_keys.d/%u" ];
 
     services.openssh.settings.AuthorizedPrincipalsFile = mkIf (authPrincipalsFiles != {}) "/etc/ssh/authorized_principals.d/%u";
 
@@ -690,6 +715,10 @@ in
 
     assertions = [{ assertion = if cfg.settings.X11Forwarding then cfgc.setXAuthLocation else true;
                     message = "cannot enable X11 forwarding without setting xauth location";}
+                  { assertion = (builtins.match "(.*\n)?(\t )*[Kk][Ee][Rr][Bb][Ee][Rr][Oo][Ss][Aa][Uu][Tt][Hh][Ee][Nn][Tt][Ii][Cc][Aa][Tt][Ii][Oo][Nn][ |\t|=|\"]+yes.*" "${configFile}\n${cfg.extraConfig}") != null -> cfgc.package.withKerberos;
+                    message = "cannot enable Kerberos authentication without using a package with Kerberos support";}
+                  { assertion = (builtins.match "(.*\n)?(\t )*[Gg][Ss][Ss][Aa][Pp][Ii][Aa][Uu][Tt][Hh][Ee][Nn][Tt][Ii][Cc][Aa][Tt][Ii][Oo][Nn][ |\t|=|\"]+yes.*" "${configFile}\n${cfg.extraConfig}") != null -> cfgc.package.withKerberos;
+                    message = "cannot enable GSSAPI authentication without using a package with Kerberos support";}
                   (let
                     duplicates =
                       # Filter out the groups with more than 1 element
diff --git a/nixos/modules/services/networking/sunshine.nix b/nixos/modules/services/networking/sunshine.nix
index 0749eaee95d8a..ec78db1f3f8e9 100644
--- a/nixos/modules/services/networking/sunshine.nix
+++ b/nixos/modules/services/networking/sunshine.nix
@@ -1,6 +1,6 @@
 { config, lib, pkgs, utils, ... }:
 let
-  inherit (lib) mkEnableOption mkPackageOption mkOption mkIf mkDefault types optionals getExe;
+  inherit (lib) mkEnableOption mkPackageOption mkOption literalExpression mkIf mkDefault types optionals getExe;
   inherit (utils) escapeSystemdExecArgs;
   cfg = config.services.sunshine;
 
@@ -46,7 +46,7 @@ in
 
         See https://docs.lizardbyte.dev/projects/sunshine/en/latest/about/advanced_usage.html#configuration for syntax.
       '';
-      example = ''
+      example = literalExpression ''
         {
           sunshine_name = "nixos";
         }
@@ -67,7 +67,7 @@ in
       description = ''
         Configuration for applications to be exposed to Moonlight. If this is set, no configuration is possible from the web UI, and must be by the `settings` option.
       '';
-      example = ''
+      example = literalExpression ''
         {
           env = {
             PATH = "$(PATH):$(HOME)/.local/bin";
diff --git a/nixos/modules/services/networking/tailscale-auth.nix b/nixos/modules/services/networking/tailscale-auth.nix
index c3a515212e782..f21d1f108911c 100644
--- a/nixos/modules/services/networking/tailscale-auth.nix
+++ b/nixos/modules/services/networking/tailscale-auth.nix
@@ -14,7 +14,7 @@ let
 in
 {
   options.services.tailscaleAuth = {
-    enable = mkEnableOption "Enable tailscale.nginx-auth, to authenticate users via tailscale.";
+    enable = mkEnableOption "tailscale.nginx-auth, to authenticate users via tailscale";
 
     package = mkPackageOption pkgs "tailscale-nginx-auth" {};
 
diff --git a/nixos/modules/services/networking/tailscale.nix b/nixos/modules/services/networking/tailscale.nix
index a79e47d8491b8..a690dc610e825 100644
--- a/nixos/modules/services/networking/tailscale.nix
+++ b/nixos/modules/services/networking/tailscale.nix
@@ -61,12 +61,21 @@ in {
     };
 
     extraUpFlags = mkOption {
-      description = "Extra flags to pass to {command}`tailscale up`.";
+      description = ''
+        Extra flags to pass to {command}`tailscale up`. Only applied if `authKeyFile` is specified.";
+      '';
       type = types.listOf types.str;
       default = [];
       example = ["--ssh"];
     };
 
+    extraSetFlags = mkOption {
+      description = "Extra flags to pass to {command}`tailscale set`.";
+      type = types.listOf types.str;
+      default = [];
+      example = ["--advertise-exit-node"];
+    };
+
     extraDaemonFlags = mkOption {
       description = "Extra flags to pass to {command}`tailscaled`.";
       type = types.listOf types.str;
@@ -120,6 +129,18 @@ in {
       '';
     };
 
+    systemd.services.tailscaled-set = mkIf (cfg.extraSetFlags != []) {
+      after = ["tailscaled.service"];
+      wants = ["tailscaled.service"];
+      wantedBy = [ "multi-user.target" ];
+      serviceConfig = {
+        Type = "oneshot";
+      };
+      script = ''
+        ${cfg.package}/bin/tailscale set ${escapeShellArgs cfg.extraSetFlags}
+      '';
+    };
+
     boot.kernel.sysctl = mkIf (cfg.useRoutingFeatures == "server" || cfg.useRoutingFeatures == "both") {
       "net.ipv4.conf.all.forwarding" = mkOverride 97 true;
       "net.ipv6.conf.all.forwarding" = mkOverride 97 true;
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/networking/wstunnel.nix b/nixos/modules/services/networking/wstunnel.nix
index efb65aead116a..bd7536351955a 100644
--- a/nixos/modules/services/networking/wstunnel.nix
+++ b/nixos/modules/services/networking/wstunnel.nix
@@ -1,95 +1,94 @@
-{ config, lib, options, pkgs, utils, ... }:
-with lib;
+{ config
+, lib
+, pkgs
+, ...
+}:
+
 let
   cfg = config.services.wstunnel;
-  attrsToArgs = attrs: utils.escapeSystemdExecArgs (
-    mapAttrsToList
-    (name: value: if value == true then "--${name}" else "--${name}=${value}")
-    attrs
-  );
+
+  hostPortToString = { host, port }: "${host}:${toString port}";
+
   hostPortSubmodule = {
     options = {
-      host = mkOption {
+      host = lib.mkOption {
         description = "The hostname.";
-        type = types.str;
+        type = lib.types.str;
       };
-      port = mkOption {
+      port = lib.mkOption {
         description = "The port.";
-        type = types.port;
-      };
-    };
-  };
-  localRemoteSubmodule = {
-    options = {
-      local = mkOption {
-        description = "Local address and port to listen on.";
-        type = types.submodule hostPortSubmodule;
-        example = {
-          host = "127.0.0.1";
-          port = 51820;
-        };
-      };
-      remote = mkOption {
-        description = "Address and port on remote to forward traffic to.";
-        type = types.submodule hostPortSubmodule;
-        example = {
-          host = "127.0.0.1";
-          port = 51820;
-        };
+        type = lib.types.port;
       };
     };
   };
-  hostPortToString = { host, port }: "${host}:${builtins.toString port}";
-  localRemoteToString = { local, remote }: utils.escapeSystemdExecArg "${hostPortToString local}:${hostPortToString remote}";
+
   commonOptions = {
-    enable = mkOption {
-      description = "Whether to enable this `wstunnel` instance.";
-      type = types.bool;
+    enable = lib.mkEnableOption "this `wstunnel` instance." // {
       default = true;
     };
 
-    package = mkPackageOption pkgs "wstunnel" {};
+    package = lib.mkPackageOption pkgs "wstunnel" { };
 
-    autoStart = mkOption {
-      description = "Whether this tunnel server should be started automatically.";
-      type = types.bool;
-      default = true;
-    };
+    autoStart =
+      lib.mkEnableOption "starting this wstunnel instance automatically." // {
+        default = true;
+      };
 
-    extraArgs = mkOption {
-      description = "Extra command line arguments to pass to `wstunnel`. Attributes of the form `argName = true;` will be translated to `--argName`, and `argName = \"value\"` to `--argName=value`.";
-      type = with types; attrsOf (either str bool);
-      default = {};
+    extraArgs = lib.mkOption {
+      description = ''
+        Extra command line arguments to pass to `wstunnel`.
+        Attributes of the form `argName = true;` will be translated to `--argName`,
+        and `argName = \"value\"` to `--argName value`.
+      '';
+      type = with lib.types; attrsOf (either str bool);
+      default = { };
       example = {
         "someNewOption" = true;
         "someNewOptionWithValue" = "someValue";
       };
     };
 
-    verboseLogging = mkOption {
-      description = "Enable verbose logging.";
-      type = types.bool;
-      default = false;
+    loggingLevel = lib.mkOption {
+      description = ''
+        Passed to --log-lvl
+
+        Control the log verbosity. i.e: TRACE, DEBUG, INFO, WARN, ERROR, OFF
+        For more details, checkout [EnvFilter](https://docs.rs/tracing-subscriber/latest/tracing_subscriber/filter/struct.EnvFilter.html#example-syntax)
+      '';
+      type = lib.types.nullOr lib.types.str;
+      example = "INFO";
+      default = null;
     };
 
-    environmentFile = mkOption {
-      description = "Environment file to be passed to the systemd service. Useful for passing secrets to the service to prevent them from being world-readable in the Nix store. Note however that the secrets are passed to `wstunnel` through the command line, which makes them locally readable for all users of the system at runtime.";
-      type = types.nullOr types.path;
+    environmentFile = lib.mkOption {
+      description = ''
+        Environment file to be passed to the systemd service.
+        Useful for passing secrets to the service to prevent them from being
+        world-readable in the Nix store.
+        Note however that the secrets are passed to `wstunnel` through
+        the command line, which makes them locally readable for all users of
+        the system at runtime.
+      '';
+      type = lib.types.nullOr lib.types.path;
       default = null;
       example = "/var/lib/secrets/wstunnelSecrets";
     };
   };
 
-  serverSubmodule = { config, ...}: {
+  serverSubmodule = { config, ... }: {
     options = commonOptions // {
-      listen = mkOption {
-        description = "Address and port to listen on. Setting the port to a value below 1024 will also give the process the required `CAP_NET_BIND_SERVICE` capability.";
-        type = types.submodule hostPortSubmodule;
+      listen = lib.mkOption {
+        description = ''
+          Address and port to listen on.
+          Setting the port to a value below 1024 will also give the process
+          the required `CAP_NET_BIND_SERVICE` capability.
+        '';
+        type = lib.types.submodule hostPortSubmodule;
         default = {
           host = "0.0.0.0";
           port = if config.enableHTTPS then 443 else 80;
         };
-        defaultText = literalExpression ''
+        defaultText = lib.literalExpression ''
           {
             host = "0.0.0.0";
             port = if enableHTTPS then 443 else 80;
@@ -97,250 +96,252 @@ let
         '';
       };
 
-      restrictTo = mkOption {
-        description = "Accepted traffic will be forwarded only to this service. Set to `null` to allow forwarding to arbitrary addresses.";
-        type = types.nullOr (types.submodule hostPortSubmodule);
-        example = {
+      restrictTo = lib.mkOption {
+        description = ''
+          Accepted traffic will be forwarded only to this service.
+        '';
+        type = lib.types.listOf (lib.types.submodule hostPortSubmodule);
+        default = [ ];
+        example = [{
           host = "127.0.0.1";
           port = 51820;
-        };
+        }];
       };
 
-      enableHTTPS = mkOption {
+      enableHTTPS = lib.mkOption {
         description = "Use HTTPS for the tunnel server.";
-        type = types.bool;
+        type = lib.types.bool;
         default = true;
       };
 
-      tlsCertificate = mkOption {
-        description = "TLS certificate to use instead of the hardcoded one in case of HTTPS connections. Use together with `tlsKey`.";
-        type = types.nullOr types.path;
+      tlsCertificate = lib.mkOption {
+        description = ''
+          TLS certificate to use instead of the hardcoded one in case of HTTPS connections.
+          Use together with `tlsKey`.
+        '';
+        type = lib.types.nullOr lib.types.path;
         default = null;
         example = "/var/lib/secrets/cert.pem";
       };
 
-      tlsKey = mkOption {
-        description = "TLS key to use instead of the hardcoded on in case of HTTPS connections. Use together with `tlsCertificate`.";
-        type = types.nullOr types.path;
+      tlsKey = lib.mkOption {
+        description = ''
+          TLS key to use instead of the hardcoded on in case of HTTPS connections.
+          Use together with `tlsCertificate`.
+        '';
+        type = lib.types.nullOr lib.types.path;
         default = null;
         example = "/var/lib/secrets/key.pem";
       };
 
-      useACMEHost = mkOption {
-        description = "Use a certificate generated by the NixOS ACME module for the given host. Note that this will not generate a new certificate - you will need to do so with `security.acme.certs`.";
-        type = types.nullOr types.str;
+      useACMEHost = lib.mkOption {
+        description = ''
+          Use a certificate generated by the NixOS ACME module for the given host.
+          Note that this will not generate a new certificate - you will need to do so with `security.acme.certs`.
+        '';
+        type = lib.types.nullOr lib.types.str;
         default = null;
         example = "example.com";
       };
     };
   };
+
   clientSubmodule = { config, ... }: {
     options = commonOptions // {
-      connectTo = mkOption {
+      connectTo = lib.mkOption {
         description = "Server address and port to connect to.";
-        type = types.submodule hostPortSubmodule;
-        example = {
-          host = "example.com";
-        };
-      };
-
-      enableHTTPS = mkOption {
-        description = "Enable HTTPS when connecting to the server.";
-        type = types.bool;
-        default = true;
-      };
-
-      localToRemote = mkOption {
-        description = "Local hosts and ports to listen on, plus the hosts and ports on remote to forward traffic to. Setting a local port to a value less than 1024 will additionally give the process the required CAP_NET_BIND_SERVICE capability.";
-        type = types.listOf (types.submodule localRemoteSubmodule);
-        default = [];
-        example = [ {
-          local = {
-            host = "127.0.0.1";
-            port = 8080;
-          };
-          remote = {
-            host = "127.0.0.1";
-            port = 8080;
-          };
-        } ];
+        type = lib.types.str;
+        example = "https://wstunnel.server.com:8443";
       };
 
-      dynamicToRemote = mkOption {
-        description = "Host and port for the SOCKS5 proxy to dynamically forward traffic to. Leave this at `null` to disable the SOCKS5 proxy. Setting the port to a value less than 1024 will additionally give the service the required CAP_NET_BIND_SERVICE capability.";
-        type = types.nullOr (types.submodule hostPortSubmodule);
-        default = null;
-        example = {
-          host = "127.0.0.1";
-          port = 1080;
-        };
+      localToRemote = lib.mkOption {
+        description = ''Listen on local and forwards traffic from remote.'';
+        type = lib.types.listOf (lib.types.str);
+        default = [ ];
+        example = [
+          "tcp://1212:google.com:443"
+          "unix:///tmp/wstunnel.sock:g.com:443"
+        ];
       };
 
-      udp = mkOption {
-        description = "Whether to forward UDP instead of TCP traffic.";
-        type = types.bool;
-        default = false;
+      remoteToLocal = lib.mkOption {
+        description = "Listen on remote and forwards traffic from local. Only tcp is supported";
+        type = lib.types.listOf lib.types.str;
+        default = [ ];
+        example = [
+          "tcp://1212:google.com:443"
+          "unix://wstunnel.sock:g.com:443"
+        ];
       };
 
-      udpTimeout = mkOption {
-        description = "When using UDP forwarding, timeout in seconds after which the tunnel connection is closed. `-1` means no timeout.";
-        type = types.int;
-        default = 30;
-      };
+      addNetBind = lib.mkEnableOption "Whether add CAP_NET_BIND_SERVICE to the tunnel service, this should be enabled if you want to bind port < 1024";
 
-      httpProxy = mkOption {
+      httpProxy = lib.mkOption {
         description = ''
           Proxy to use to connect to the wstunnel server (`USER:PASS@HOST:PORT`).
 
           ::: {.warning}
-          Passwords specified here will be world-readable in the Nix store! To pass a password to the service, point the `environmentFile` option to a file containing `PROXY_PASSWORD=<your-password-here>` and set this option to `<user>:$PROXY_PASSWORD@<host>:<port>`. Note however that this will also locally leak the passwords at runtime via e.g. /proc/<pid>/cmdline.
-
+          Passwords specified here will be world-readable in the Nix store!
+          To pass a password to the service, point the `environmentFile` option
+          to a file containing `PROXY_PASSWORD=<your-password-here>` and set
+          this option to `<user>:$PROXY_PASSWORD@<host>:<port>`.
+          Note however that this will also locally leak the passwords at
+          runtime via e.g. /proc/<pid>/cmdline.
           :::
         '';
-        type = types.nullOr types.str;
+        type = lib.types.nullOr lib.types.str;
         default = null;
       };
 
-      soMark = mkOption {
-        description = "Mark network packets with the SO_MARK sockoption with the specified value. Setting this option will also enable the required `CAP_NET_ADMIN` capability for the systemd service.";
-        type = types.nullOr types.int;
+      soMark = lib.mkOption {
+        description = ''
+          Mark network packets with the SO_MARK sockoption with the specified value.
+          Setting this option will also enable the required `CAP_NET_ADMIN` capability
+          for the systemd service.
+        '';
+        type = lib.types.nullOr lib.types.ints.unsigned;
         default = null;
       };
 
-      upgradePathPrefix = mkOption {
-        description = "Use a specific HTTP path prefix that will show up in the upgrade request to the `wstunnel` server. Useful when running `wstunnel` behind a reverse proxy.";
-        type = types.nullOr types.str;
+      upgradePathPrefix = lib.mkOption {
+        description = ''
+          Use a specific HTTP path prefix that will show up in the upgrade
+          request to the `wstunnel` server.
+          Useful when running `wstunnel` behind a reverse proxy.
+        '';
+        type = lib.types.nullOr lib.types.str;
         default = null;
         example = "wstunnel";
       };
 
-      hostHeader = mkOption {
-        description = "Use this as the HTTP host header instead of the real hostname. Useful for circumventing hostname-based firewalls.";
-        type = types.nullOr types.str;
-        default = null;
-      };
-
-      tlsSNI = mkOption {
+      tlsSNI = lib.mkOption {
         description = "Use this as the SNI while connecting via TLS. Useful for circumventing hostname-based firewalls.";
-        type = types.nullOr types.str;
+        type = lib.types.nullOr lib.types.str;
         default = null;
       };
 
-      tlsVerifyCertificate = mkOption {
+      tlsVerifyCertificate = lib.mkOption {
         description = "Whether to verify the TLS certificate of the server. It might be useful to set this to `false` when working with the `tlsSNI` option.";
-        type = types.bool;
+        type = lib.types.bool;
         default = true;
       };
 
       # The original argument name `websocketPingFrequency` is a misnomer, as the frequency is the inverse of the interval.
-      websocketPingInterval = mkOption {
-        description = "Do a heartbeat ping every N seconds to keep up the websocket connection.";
-        type = types.nullOr types.ints.unsigned;
+      websocketPingInterval = lib.mkOption {
+        description = "Frequency at which the client will send websocket ping to the server.";
+        type = lib.types.nullOr lib.types.ints.unsigned;
         default = null;
       };
 
-      upgradeCredentials = mkOption {
+      upgradeCredentials = lib.mkOption {
         description = ''
-          Use these credentials to authenticate during the HTTP upgrade request (Basic authorization type, `USER:[PASS]`).
+          Use these credentials to authenticate during the HTTP upgrade request
+          (Basic authorization type, `USER:[PASS]`).
 
           ::: {.warning}
-          Passwords specified here will be world-readable in the Nix store! To pass a password to the service, point the `environmentFile` option to a file containing `HTTP_PASSWORD=<your-password-here>` and set this option to `<user>:$HTTP_PASSWORD`. Note however that this will also locally leak the passwords at runtime via e.g. /proc/<pid>/cmdline.
+          Passwords specified here will be world-readable in the Nix store!
+          To pass a password to the service, point the `environmentFile` option
+          to a file containing `HTTP_PASSWORD=<your-password-here>` and set this
+          option to `<user>:$HTTP_PASSWORD`.
+          Note however that this will also locally leak the passwords at runtime
+          via e.g. /proc/<pid>/cmdline.
           :::
         '';
-        type = types.nullOr types.str;
+        type = lib.types.nullOr lib.types.str;
         default = null;
       };
 
-      customHeaders = mkOption {
+      customHeaders = lib.mkOption {
         description = "Custom HTTP headers to send during the upgrade request.";
-        type = types.attrsOf types.str;
-        default = {};
+        type = lib.types.attrsOf lib.types.str;
+        default = { };
         example = {
           "X-Some-Header" = "some-value";
         };
       };
     };
   };
+
   generateServerUnit = name: serverCfg: {
     name = "wstunnel-server-${name}";
-    value = {
-      description = "wstunnel server - ${name}";
-      requires = [ "network.target" "network-online.target" ];
-      after = [ "network.target" "network-online.target" ];
-      wantedBy = optional serverCfg.autoStart "multi-user.target";
-
-      serviceConfig = let
-        certConfig = config.security.acme.certs."${serverCfg.useACMEHost}";
-      in {
-        Type = "simple";
-        ExecStart = with serverCfg; let
-          resolvedTlsCertificate = if useACMEHost != null
-            then "${certConfig.directory}/fullchain.pem"
-            else tlsCertificate;
-          resolvedTlsKey = if useACMEHost != null
-            then "${certConfig.directory}/key.pem"
-            else tlsKey;
-        in ''
-          ${package}/bin/wstunnel \
-            --server \
-            ${optionalString (restrictTo != null)     "--restrictTo=${utils.escapeSystemdExecArg (hostPortToString restrictTo)}"} \
-            ${optionalString (resolvedTlsCertificate != null) "--tlsCertificate=${utils.escapeSystemdExecArg resolvedTlsCertificate}"} \
-            ${optionalString (resolvedTlsKey != null)         "--tlsKey=${utils.escapeSystemdExecArg resolvedTlsKey}"} \
-            ${optionalString verboseLogging "--verbose"} \
-            ${attrsToArgs extraArgs} \
-            ${utils.escapeSystemdExecArg "${if enableHTTPS then "wss" else "ws"}://${hostPortToString listen}"}
-        '';
-        EnvironmentFile = optional (serverCfg.environmentFile != null) serverCfg.environmentFile;
-        DynamicUser = true;
-        SupplementaryGroups = optional (serverCfg.useACMEHost != null) certConfig.group;
-        PrivateTmp = true;
-        AmbientCapabilities = optionals (serverCfg.listen.port < 1024) [ "CAP_NET_BIND_SERVICE" ];
-        NoNewPrivileges = true;
-        RestrictNamespaces = "uts ipc pid user cgroup";
-        ProtectSystem = "strict";
-        ProtectHome = true;
-        ProtectKernelTunables = true;
-        ProtectKernelModules = true;
-        ProtectControlGroups = true;
-        PrivateDevices = true;
-        RestrictSUIDSGID = true;
+    value =
+      let
+        certConfig = config.security.acme.certs.${serverCfg.useACMEHost};
+      in
+      {
+        description = "wstunnel server - ${name}";
+        requires = [ "network.target" "network-online.target" ];
+        after = [ "network.target" "network-online.target" ];
+        wantedBy = lib.optional serverCfg.autoStart "multi-user.target";
+
+        environment.RUST_LOG = serverCfg.loggingLevel;
+
+        serviceConfig = {
+          Type = "exec";
+          EnvironmentFile =
+            lib.optional (serverCfg.environmentFile != null) serverCfg.environmentFile;
+          DynamicUser = true;
+          SupplementaryGroups =
+            lib.optional (serverCfg.useACMEHost != null) certConfig.group;
+          PrivateTmp = true;
+          AmbientCapabilities =
+            lib.optionals (serverCfg.listen.port < 1024) [ "CAP_NET_BIND_SERVICE" ];
+          NoNewPrivileges = true;
+          RestrictNamespaces = "uts ipc pid user cgroup";
+          ProtectSystem = "strict";
+          ProtectHome = true;
+          ProtectKernelTunables = true;
+          ProtectKernelModules = true;
+          ProtectControlGroups = true;
+          PrivateDevices = true;
+          RestrictSUIDSGID = true;
+
+          Restart = "on-failure";
+          RestartSec = 2;
+          RestartSteps = 20;
+          RestartMaxDelaySec = "5min";
+        };
 
+        script = with serverCfg; ''
+          ${lib.getExe package} \
+            server \
+            ${lib.cli.toGNUCommandLineShell { } (
+              lib.recursiveUpdate
+              {
+                restrict-to = map hostPortToString restrictTo;
+                tls-certificate = if useACMEHost != null
+                                  then "${certConfig.directory}/fullchain.pem"
+                                  else "${tlsCertificate}";
+                tls-private-key = if useACMEHost != null
+                                  then "${certConfig.directory}/key.pem"
+                                  else "${tlsKey}";
+              }
+              extraArgs
+            )} \
+            ${lib.escapeShellArg "${if enableHTTPS then "wss" else "ws"}://${hostPortToString listen}"}
+        '';
       };
-    };
   };
+
   generateClientUnit = name: clientCfg: {
     name = "wstunnel-client-${name}";
     value = {
       description = "wstunnel client - ${name}";
       requires = [ "network.target" "network-online.target" ];
       after = [ "network.target" "network-online.target" ];
-      wantedBy = optional clientCfg.autoStart "multi-user.target";
+      wantedBy = lib.optional clientCfg.autoStart "multi-user.target";
+
+      environment.RUST_LOG = clientCfg.loggingLevel;
 
       serviceConfig = {
-        Type = "simple";
-        ExecStart = with clientCfg; ''
-          ${package}/bin/wstunnel \
-            ${concatStringsSep " " (builtins.map (x:          "--localToRemote=${localRemoteToString x}") localToRemote)} \
-            ${concatStringsSep " " (mapAttrsToList (n: v:     "--customHeaders=\"${n}: ${v}\"") customHeaders)} \
-            ${optionalString (dynamicToRemote != null)        "--dynamicToRemote=${utils.escapeSystemdExecArg (hostPortToString dynamicToRemote)}"} \
-            ${optionalString udp                              "--udp"} \
-            ${optionalString (httpProxy != null)              "--httpProxy=${httpProxy}"} \
-            ${optionalString (soMark != null)                 "--soMark=${toString soMark}"} \
-            ${optionalString (upgradePathPrefix != null)      "--upgradePathPrefix=${upgradePathPrefix}"} \
-            ${optionalString (hostHeader != null)             "--hostHeader=${hostHeader}"} \
-            ${optionalString (tlsSNI != null)                 "--tlsSNI=${tlsSNI}"} \
-            ${optionalString tlsVerifyCertificate             "--tlsVerifyCertificate"} \
-            ${optionalString (websocketPingInterval != null)  "--websocketPingFrequency=${toString websocketPingInterval}"} \
-            ${optionalString (upgradeCredentials != null)     "--upgradeCredentials=${upgradeCredentials}"} \
-            --udpTimeoutSec=${toString udpTimeout} \
-            ${optionalString verboseLogging "--verbose"} \
-            ${attrsToArgs extraArgs} \
-            ${utils.escapeSystemdExecArg "${if enableHTTPS then "wss" else "ws"}://${hostPortToString connectTo}"}
-        '';
-        EnvironmentFile = optional (clientCfg.environmentFile != null) clientCfg.environmentFile;
+        Type = "exec";
+        EnvironmentFile =
+          lib.optional (clientCfg.environmentFile != null) clientCfg.environmentFile;
         DynamicUser = true;
         PrivateTmp = true;
-        AmbientCapabilities = (optionals (clientCfg.soMark != null) [ "CAP_NET_ADMIN" ]) ++ (optionals ((clientCfg.dynamicToRemote.port or 1024) < 1024 || (any (x: x.local.port < 1024) clientCfg.localToRemote)) [ "CAP_NET_BIND_SERVICE" ]);
+        AmbientCapabilities =
+          (lib.optionals clientCfg.addNetBind [ "CAP_NET_BIND_SERVICE" ]) ++
+          (lib.optionals (clientCfg.soMark != null) [ "CAP_NET_ADMIN" ]);
         NoNewPrivileges = true;
         RestrictNamespaces = "uts ipc pid user cgroup";
         ProtectSystem = "strict";
@@ -350,80 +351,118 @@ let
         ProtectControlGroups = true;
         PrivateDevices = true;
         RestrictSUIDSGID = true;
+
+        Restart = "on-failure";
+        RestartSec = 2;
+        RestartSteps = 20;
+        RestartMaxDelaySec = "5min";
       };
+
+      script = with clientCfg; ''
+        ${lib.getExe package} \
+          client \
+          ${lib.cli.toGNUCommandLineShell { } (
+            lib.recursiveUpdate
+            {
+              local-to-remote = localToRemote;
+              remote-to-local = remoteToLocal;
+              http-headers = lib.mapAttrsToList (n: v: "${n}:${v}") customHeaders;
+              http-proxy = httpProxy;
+              socket-so-mark = soMark;
+              http-upgrade-path-prefix = upgradePathPrefix;
+              tls-sni-override = tlsSNI;
+              tls-verify-certificate = tlsVerifyCertificate;
+              websocket-ping-frequency-sec = websocketPingInterval;
+              http-upgrade-credentials = upgradeCredentials;
+            }
+            extraArgs
+          )} \
+          ${lib.escapeShellArg connectTo}
+      '';
     };
   };
-in {
+in
+{
   options.services.wstunnel = {
-    enable = mkEnableOption "wstunnel";
+    enable = lib.mkEnableOption "wstunnel";
 
-    servers = mkOption {
+    servers = lib.mkOption {
       description = "`wstunnel` servers to set up.";
-      type = types.attrsOf (types.submodule serverSubmodule);
-      default = {};
+      type = lib.types.attrsOf (lib.types.submodule serverSubmodule);
+      default = { };
       example = {
         "wg-tunnel" = {
-          listen.port = 8080;
+          listen = {
+            host = "0.0.0.0";
+            port = 8080;
+          };
           enableHTTPS = true;
           tlsCertificate = "/var/lib/secrets/fullchain.pem";
           tlsKey = "/var/lib/secrets/key.pem";
-          restrictTo = {
+          restrictTo = [{
             host = "127.0.0.1";
             port = 51820;
-          };
+          }];
         };
       };
     };
 
-    clients = mkOption {
+    clients = lib.mkOption {
       description = "`wstunnel` clients to set up.";
-      type = types.attrsOf (types.submodule clientSubmodule);
-      default = {};
+      type = lib.types.attrsOf (lib.types.submodule clientSubmodule);
+      default = { };
       example = {
         "wg-tunnel" = {
-          connectTo = {
-            host = "example.com";
-            port = 8080;
-          };
-          enableHTTPS = true;
-          localToRemote = {
-            local = {
-              host = "127.0.0.1";
-              port = 51820;
-            };
-            remote = {
-              host = "127.0.0.1";
-              port = 51820;
-            };
-          };
-          udp = true;
+          connectTo = "wss://wstunnel.server.com:8443";
+          localToRemote = [
+            "tcp://1212:google.com:443"
+            "tcp://2:n.lan:4?proxy_protocol"
+          ];
+          remoteToLocal = [
+            "socks5://[::1]:1212"
+            "unix://wstunnel.sock:g.com:443"
+          ];
         };
       };
     };
   };
 
-  config = mkIf cfg.enable {
-    systemd.services = (mapAttrs' generateServerUnit (filterAttrs (n: v: v.enable) cfg.servers)) // (mapAttrs' generateClientUnit (filterAttrs (n: v: v.enable) cfg.clients));
-
-    assertions = (mapAttrsToList (name: serverCfg: {
-      assertion = !(serverCfg.useACMEHost != null && (serverCfg.tlsCertificate != null || serverCfg.tlsKey != null));
-      message = ''
-        Options services.wstunnel.servers."${name}".useACMEHost and services.wstunnel.servers."${name}".{tlsCertificate, tlsKey} are mutually exclusive.
-      '';
-    }) cfg.servers) ++
-    (mapAttrsToList (name: serverCfg: {
-      assertion = !((serverCfg.tlsCertificate != null || serverCfg.tlsKey != null) && !(serverCfg.tlsCertificate != null && serverCfg.tlsKey != null));
-      message = ''
-        services.wstunnel.servers."${name}".tlsCertificate and services.wstunnel.servers."${name}".tlsKey need to be set together.
-      '';
-    }) cfg.servers) ++
-    (mapAttrsToList (name: clientCfg: {
-      assertion = !(clientCfg.localToRemote == [] && clientCfg.dynamicToRemote == null);
-      message = ''
-        Either one of services.wstunnel.clients."${name}".localToRemote or services.wstunnel.clients."${name}".dynamicToRemote must be set.
-      '';
-    }) cfg.clients);
+  config = lib.mkIf cfg.enable {
+    systemd.services =
+      (lib.mapAttrs' generateServerUnit (lib.filterAttrs (n: v: v.enable) cfg.servers)) //
+      (lib.mapAttrs' generateClientUnit (lib.filterAttrs (n: v: v.enable) cfg.clients));
+
+    assertions =
+      (lib.mapAttrsToList
+        (name: serverCfg: {
+          assertion =
+            !(serverCfg.useACMEHost != null && serverCfg.tlsCertificate != null);
+          message = ''
+            Options services.wstunnel.servers."${name}".useACMEHost and services.wstunnel.servers."${name}".{tlsCertificate, tlsKey} are mutually exclusive.
+          '';
+        })
+        cfg.servers) ++
+
+      (lib.mapAttrsToList
+        (name: serverCfg: {
+          assertion =
+            (serverCfg.tlsCertificate == null && serverCfg.tlsKey == null) ||
+            (serverCfg.tlsCertificate != null && serverCfg.tlsKey != null);
+          message = ''
+            services.wstunnel.servers."${name}".tlsCertificate and services.wstunnel.servers."${name}".tlsKey need to be set together.
+          '';
+        })
+        cfg.servers) ++
+
+      (lib.mapAttrsToList
+        (name: clientCfg: {
+          assertion = !(clientCfg.localToRemote == [ ] && clientCfg.remoteToLocal == [ ]);
+          message = ''
+            Either one of services.wstunnel.clients."${name}".localToRemote or services.wstunnel.clients."${name}".remoteToLocal must be set.
+          '';
+        })
+        cfg.clients);
   };
 
-  meta.maintainers = with maintainers; [ alyaeanyx ];
+  meta.maintainers = with lib.maintainers; [ alyaeanyx rvdp neverbehave ];
 }
diff --git a/nixos/modules/services/networking/zerotierone.nix b/nixos/modules/services/networking/zerotierone.nix
index 86c1efc629a98..68c04118fdd58 100644
--- a/nixos/modules/services/networking/zerotierone.nix
+++ b/nixos/modules/services/networking/zerotierone.nix
@@ -4,7 +4,9 @@ with lib;
 
 let
   cfg = config.services.zerotierone;
-  localConfFile = pkgs.writeText "zt-local.conf" (builtins.toJSON cfg.localConf);
+
+  settingsFormat = pkgs.formats.json {};
+  localConfFile = settingsFormat.generate "zt-local.conf" cfg.localConf;
   localConfFilePath = "/var/lib/zerotier-one/local.conf";
 in
 {
@@ -41,7 +43,7 @@ in
     example = {
       settings.allowTcpFallbackRelay = false;
     };
-    type = types.nullOr types.attrs;
+    type = settingsFormat.type;
   };
 
   config = mkIf cfg.enable {
@@ -60,7 +62,7 @@ in
         chown -R root:root /var/lib/zerotier-one
       '' + (concatMapStrings (netId: ''
         touch "/var/lib/zerotier-one/networks.d/${netId}.conf"
-      '') cfg.joinNetworks) + optionalString (cfg.localConf != null) ''
+      '') cfg.joinNetworks) + optionalString (cfg.localConf != {}) ''
         if [ -L "${localConfFilePath}" ]
         then
           rm ${localConfFilePath}
diff --git a/nixos/modules/services/search/qdrant.nix b/nixos/modules/services/search/qdrant.nix
index f28178a5f1751..41a4e9b41f6d9 100644
--- a/nixos/modules/services/search/qdrant.nix
+++ b/nixos/modules/services/search/qdrant.nix
@@ -60,6 +60,7 @@ in {
 
   config = mkIf cfg.enable {
     services.qdrant.settings = {
+      service.static_content_dir = mkDefault pkgs.qdrant-web-ui;
       storage.storage_path = mkDefault "/var/lib/qdrant/storage";
       storage.snapshots_path = mkDefault "/var/lib/qdrant/snapshots";
       # The following default values are the same as in the default config,
diff --git a/nixos/modules/services/search/quickwit.nix b/nixos/modules/services/search/quickwit.nix
new file mode 100644
index 0000000000000..6b2db935cf0bf
--- /dev/null
+++ b/nixos/modules/services/search/quickwit.nix
@@ -0,0 +1,190 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.services.quickwit;
+
+  settingsFormat = pkgs.formats.yaml {};
+  quickwitYml = settingsFormat.generate "quickwit.yml" cfg.settings;
+
+  usingDefaultDataDir = cfg.dataDir == "/var/lib/quickwit";
+  usingDefaultUserAndGroup = cfg.user == "quickwit" && cfg.group == "quickwit";
+in
+{
+
+  options.services.quickwit = {
+    enable = mkEnableOption "Quickwit";
+
+    package = lib.mkPackageOption pkgs "Quickwit" {
+      default = [ "quickwit" ];
+    };
+
+    settings = lib.mkOption {
+      type = lib.types.submodule {
+        freeformType = settingsFormat.type;
+
+        options."rest" = lib.mkOption {
+          default = {};
+          description = ''
+            Rest server configuration for Quickwit
+          '';
+
+          type = lib.types.submodule {
+            freeformType = settingsFormat.type;
+
+            options."listen_port" = lib.mkOption {
+              type = lib.types.port;
+              default = 7280;
+              description = ''
+                The port to listen on for HTTP REST traffic.
+              '';
+            };
+          };
+        };
+
+        options."grpc_listen_port" = lib.mkOption {
+          type = lib.types.port;
+          default = 7281;
+          description = ''
+            The port to listen on for gRPC traffic.
+          '';
+        };
+
+        options."listen_address" = lib.mkOption {
+          type = lib.types.str;
+          default = "127.0.0.1";
+          description = ''
+            Listen address of Quickwit.
+          '';
+        };
+
+        options."version" = lib.mkOption {
+          type = lib.types.float;
+          default = 0.7;
+          description = ''
+            Configuration file version.
+          '';
+        };
+      };
+
+      default = {};
+
+      description = ''
+        Quickwit configuration.
+      '';
+    };
+
+    dataDir = lib.mkOption {
+      type = lib.types.path;
+      default = "/var/lib/quickwit";
+      apply = converge (removeSuffix "/");
+      description = ''
+        Data directory for Quickwit. If you change this, you need to
+        manually create the directory. You also need to create the
+        `quickwit` user and group, or change
+        [](#opt-services.quickwit.user) and
+        [](#opt-services.quickwit.group) to existing ones with
+        access to the directory.
+      '';
+    };
+
+    user = lib.mkOption {
+      type = lib.types.str;
+      default = "quickwit";
+      description = ''
+        The user Quickwit runs as. Should be left at default unless
+        you have very specific needs.
+      '';
+    };
+
+    group = lib.mkOption {
+      type = lib.types.str;
+      default = "quickwit";
+      description = ''
+        The group quickwit runs as. Should be left at default unless
+        you have very specific needs.
+      '';
+    };
+
+    extraFlags = lib.mkOption {
+      description = "Extra command line options to pass to Quickwit.";
+      default = [ ];
+      type = lib.types.listOf lib.types.str;
+    };
+
+    restartIfChanged = lib.mkOption {
+      type = lib.types.bool;
+      description = ''
+        Automatically restart the service on config change.
+        This can be set to false to defer restarts on a server or cluster.
+        Please consider the security implications of inadvertently running an older version,
+        and the possibility of unexpected behavior caused by inconsistent versions across a cluster when disabling this option.
+      '';
+      default = true;
+    };
+  };
+
+  config = mkIf cfg.enable {
+    systemd.services.quickwit = {
+      description = "Quickwit";
+      wantedBy = [ "multi-user.target" ];
+      after = [ "network.target" ];
+      inherit (cfg) restartIfChanged;
+      environment = {
+        QW_DATA_DIR = cfg.dataDir;
+      };
+      serviceConfig = {
+        ExecStart = ''
+          ${cfg.package}/bin/quickwit run --config ${quickwitYml} \
+          ${escapeShellArgs cfg.extraFlags}
+        '';
+        User = cfg.user;
+        Group = cfg.group;
+        Restart = "on-failure";
+        DynamicUser = usingDefaultUserAndGroup && usingDefaultDataDir;
+        CapabilityBoundingSet = [ "" ];
+        DevicePolicy = "closed";
+        LockPersonality = true;
+        MemoryDenyWriteExecute = true;
+        NoNewPrivileges = true;
+        PrivateDevices = true;
+        ProcSubset = "pid";
+        ProtectClock = true;
+        ProtectHome = true;
+        ProtectHostname = true;
+        ProtectControlGroups = true;
+        ProtectKernelLogs = true;
+        ProtectKernelModules = true;
+        ProtectKernelTunables = true;
+        ProtectProc = "invisible";
+        ProtectSystem = "strict";
+        ReadWritePaths = [
+          "/var/lib/quickwit"
+        ];
+        RestrictAddressFamilies = [
+          "AF_NETLINK"
+          "AF_INET"
+          "AF_INET6"
+        ];
+        RestrictNamespaces = true;
+        RestrictRealtime = true;
+        RestrictSUIDSGID = true;
+        SystemCallArchitectures = "native";
+        SystemCallFilter = [
+          # 1. allow a reasonable set of syscalls
+          "@system-service @resources"
+          # 2. and deny unreasonable ones
+          "~@privileged"
+          # 3. then allow the required subset within denied groups
+          "@chown"
+        ];
+      } // (optionalAttrs (usingDefaultDataDir) {
+        StateDirectory = "quickwit";
+        StateDirectoryMode = "0700";
+      });
+    };
+
+    environment.systemPackages = [ cfg.package ];
+  };
+}
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..2dffeb993803f 100644
--- a/nixos/modules/services/security/oauth2-proxy-nginx.nix
+++ b/nixos/modules/services/security/oauth2-proxy-nginx.nix
@@ -64,25 +64,35 @@ 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;
         extraConfig = ''
+          auth_request off;
           proxy_set_header X-Scheme                $scheme;
           proxy_set_header X-Auth-Request-Redirect $scheme://$host$request_uri;
         '';
       };
     }
-  ] ++ 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 +112,7 @@ in
             proxy_pass_request_body           off;
           '';
         };
+
         "@redirectToAuth2ProxyLogin" = {
           return = "307 https://${cfg.domain}/oauth2/start?rd=$scheme://$host$request_uri";
           extraConfig = ''
@@ -114,16 +125,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 075e64b743b1e..a897f04ea6333 100644
--- a/nixos/modules/services/security/oauth2-proxy.nix
+++ b/nixos/modules/services/security/oauth2-proxy.nix
@@ -17,7 +17,7 @@ let
       inherit (cfg.github) org team;
     }; };
 
-    google = cfg: { google = with cfg.google; optionalAttrs (groups != []) {
+    google = cfg: { google = with cfg.google; lib.optionalAttrs (groups != []) {
       admin-email = adminEmail;
       service-account = serviceAccountJSON;
       group = groups;
@@ -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" ];
+        restartTriggers = [ cfg.keyFile ];
+        serviceConfig = {
+          User = "oauth2-proxy";
+          Restart = "always";
+          ExecStart = "${lib.getExe cfg.package} ${configString}";
+          EnvironmentFile = lib.mkIf (cfg.keyFile != null) cfg.keyFile;
+        };
       };
-    };
-
   };
 }
diff --git a/nixos/modules/services/security/sslmate-agent.nix b/nixos/modules/services/security/sslmate-agent.nix
index c850eb22a0311..57cb955a39dd9 100644
--- a/nixos/modules/services/security/sslmate-agent.nix
+++ b/nixos/modules/services/security/sslmate-agent.nix
@@ -6,7 +6,7 @@ let
   cfg = config.services.sslmate-agent;
 
 in {
-  meta.maintainers = with maintainers; [ wolfangaukang ];
+  meta.maintainers = [ ];
 
   options = {
     services.sslmate-agent = {
diff --git a/nixos/modules/services/security/step-ca.nix b/nixos/modules/services/security/step-ca.nix
index c708cb2b8910d..43bc402e7818b 100644
--- a/nixos/modules/services/security/step-ca.nix
+++ b/nixos/modules/services/security/step-ca.nix
@@ -4,7 +4,7 @@ let
   settingsFormat = (pkgs.formats.json { });
 in
 {
-  meta.maintainers = with lib.maintainers; [ mohe2015 ];
+  meta.maintainers = with lib.maintainers; [ ];
 
   options = {
     services.step-ca = {
@@ -107,7 +107,7 @@ in
           UMask = "0077";
           Environment = "HOME=%S/step-ca";
           WorkingDirectory = ""; # override upstream
-          ReadWriteDirectories = ""; # override upstream
+          ReadWritePaths = ""; # override upstream
 
           # LocalCredential handles file permission problems arising from the use of DynamicUser.
           LoadCredential = "intermediate_password:${cfg.intermediatePasswordFile}";
diff --git a/nixos/modules/services/security/vaultwarden/default.nix b/nixos/modules/services/security/vaultwarden/default.nix
index 33957be437b30..41f7de5d80fab 100644
--- a/nixos/modules/services/security/vaultwarden/default.nix
+++ b/nixos/modules/services/security/vaultwarden/default.nix
@@ -5,6 +5,8 @@ let
   user = config.users.users.vaultwarden.name;
   group = config.users.groups.vaultwarden.name;
 
+  StateDirectory = if lib.versionOlder config.system.stateVersion "24.11" then "bitwarden_rs" else "vaultwarden";
+
   # Convert name from camel case (e.g. disable2FARemember) to upper case snake case (e.g. DISABLE_2FA_REMEMBER).
   nameToEnvVar = name:
     let
@@ -23,7 +25,7 @@ let
       configEnv = lib.concatMapAttrs (name: value: lib.optionalAttrs (value != null) {
         ${nameToEnvVar name} = if lib.isBool value then lib.boolToString value else toString value;
       }) cfg.config;
-    in { DATA_FOLDER = "/var/lib/bitwarden_rs"; } // lib.optionalAttrs (!(configEnv ? WEB_VAULT_ENABLED) || configEnv.WEB_VAULT_ENABLED == "true") {
+    in { DATA_FOLDER = "/var/lib/${StateDirectory}"; } // lib.optionalAttrs (!(configEnv ? WEB_VAULT_ENABLED) || configEnv.WEB_VAULT_ENABLED == "true") {
       WEB_VAULT_FOLDER = "${cfg.webVaultPackage}/share/vaultwarden/vault";
     } // configEnv;
 
@@ -176,16 +178,45 @@ in {
         User = user;
         Group = group;
         EnvironmentFile = [ configFile ] ++ lib.optional (cfg.environmentFile != null) cfg.environmentFile;
-        ExecStart = "${vaultwarden}/bin/vaultwarden";
+        ExecStart = lib.getExe vaultwarden;
         LimitNOFILE = "1048576";
-        PrivateTmp = "true";
-        PrivateDevices = "true";
-        ProtectHome = "true";
+        CapabilityBoundingSet = [ "" ];
+        DeviceAllow = [ "" ];
+        DevicePolicy = "closed";
+        LockPersonality = true;
+        MemoryDenyWriteExecute = true;
+        NoNewPrivileges = true;
+        PrivateDevices = true;
+        PrivateTmp = true;
+        PrivateUsers = true;
+        ProcSubset = "pid";
+        ProtectClock = true;
+        ProtectControlGroups = true;
+        ProtectHome = true;
+        ProtectHostname = true;
+        ProtectKernelLogs = true;
+        ProtectKernelModules = true;
+        ProtectKernelTunables = true;
+        ProtectProc = "noaccess";
         ProtectSystem = "strict";
-        AmbientCapabilities = "CAP_NET_BIND_SERVICE";
-        StateDirectory = "bitwarden_rs";
+        RemoveIPC = true;
+        RestrictAddressFamilies = [
+          "AF_INET"
+          "AF_INET6"
+          "AF_UNIX"
+        ];
+        RestrictNamespaces = true;
+        RestrictRealtime = true;
+        RestrictSUIDSGID = true;
+        inherit StateDirectory;
         StateDirectoryMode = "0700";
+        SystemCallArchitectures = "native";
+        SystemCallFilter = [
+          "@system-service"
+          "~@privileged"
+        ];
         Restart = "always";
+        UMask = "0077";
       };
       wantedBy = [ "multi-user.target" ];
     };
@@ -193,7 +224,7 @@ in {
     systemd.services.backup-vaultwarden = lib.mkIf (cfg.backupDir != null) {
       description = "Backup vaultwarden";
       environment = {
-        DATA_FOLDER = "/var/lib/bitwarden_rs";
+        DATA_FOLDER = "/var/lib/${StateDirectory}";
         BACKUP_FOLDER = cfg.backupDir;
       };
       path = with pkgs; [ sqlite ];
diff --git a/nixos/modules/services/system/dbus.nix b/nixos/modules/services/system/dbus.nix
index 8dba0aca64337..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" ];
       };
     })
@@ -147,6 +151,10 @@ in
       };
 
       systemd.services.dbus = {
+        aliases = [
+          # hack aiding to prevent dbus from restarting when switching from dbus-broker back to dbus
+          "dbus-broker.service"
+        ];
         # Don't restart dbus-daemon. Bad things tend to happen if we do.
         reloadIfChanged = true;
         restartTriggers = [
@@ -158,6 +166,10 @@ in
       };
 
       systemd.user.services.dbus = {
+        aliases = [
+          # hack aiding to prevent dbus from restarting when switching from dbus-broker back to dbus
+          "dbus-broker.service"
+        ];
         # Don't restart dbus-daemon. Bad things tend to happen if we do.
         reloadIfChanged = true;
         restartTriggers = [
@@ -184,6 +196,8 @@ in
       # https://github.com/NixOS/nixpkgs/issues/108643
       systemd.services.dbus-broker = {
         aliases = [
+          # allow other services to just depend on dbus,
+          # but also a hack aiding to prevent dbus from restarting when switching from dbus-broker back to dbus
           "dbus.service"
         ];
         unitConfig = {
@@ -203,6 +217,8 @@ in
 
       systemd.user.services.dbus-broker = {
         aliases = [
+          # allow other services to just depend on dbus,
+          # but also a hack aiding to prevent dbus from restarting when switching from dbus-broker back to dbus
           "dbus.service"
         ];
         # Don't restart dbus. Bad things tend to happen if we do.
diff --git a/nixos/modules/services/system/kerberos/default.nix b/nixos/modules/services/system/kerberos/default.nix
index 7fe970c9609a9..34c7c6c84f865 100644
--- a/nixos/modules/services/system/kerberos/default.nix
+++ b/nixos/modules/services/system/kerberos/default.nix
@@ -1,75 +1,59 @@
-{config, lib, ...}:
+{ config, pkgs, lib, ... }:
 
 let
-  inherit (lib) mkOption mkIf types length attrNames;
+  inherit (lib) mkOption types;
   cfg = config.services.kerberos_server;
-  kerberos = config.security.krb5.package;
+  inherit (config.security.krb5) package;
 
-  aclEntry = {
-    options = {
-      principal = mkOption {
-        type = types.str;
-        description = "Which principal the rule applies to";
-      };
-      access = mkOption {
-        type = types.either
-          (types.listOf (types.enum ["add" "cpw" "delete" "get" "list" "modify"]))
-          (types.enum ["all"]);
-        default = "all";
-        description = "The changes the principal is allowed to make.";
-      };
-      target = mkOption {
-        type = types.str;
-        default = "*";
-        description = "The principals that 'access' applies to.";
-      };
-    };
-  };
-
-  realm = {
-    options = {
-      acl = mkOption {
-        type = types.listOf (types.submodule aclEntry);
-        default = [
-          { principal = "*/admin"; access = "all"; }
-          { principal = "admin"; access = "all"; }
-        ];
-        description = ''
-          The privileges granted to a user.
-        '';
-      };
-    };
-  };
+  format = import ../../../security/krb5/krb5-conf-format.nix { inherit pkgs lib; } { enableKdcACLEntries = true; };
 in
 
 {
   imports = [
+    (lib.mkRenamedOptionModule [ "services" "kerberos_server" "realms" ] [ "services" "kerberos_server" "settings" "realms" ])
+
     ./mit.nix
     ./heimdal.nix
   ];
 
-  ###### interface
   options = {
     services.kerberos_server = {
       enable = lib.mkEnableOption "the kerberos authentication server";
 
-      realms = mkOption {
-        type = types.attrsOf (types.submodule realm);
+      settings = mkOption {
+        type = format.type;
         description = ''
-          The realm(s) to serve keys for.
+          Settings for the kerberos server of choice.
+
+          See the following documentation:
+          - Heimdal: {manpage}`kdc.conf(5)`
+          - MIT Kerberos: <https://web.mit.edu/kerberos/krb5-1.21/doc/admin/conf_files/kdc_conf.html>
         '';
+        default = { };
       };
     };
   };
 
+  config = lib.mkIf cfg.enable {
+    environment.systemPackages = [ package ];
+    assertions = [
+      {
+        assertion = cfg.settings.realms != { };
+        message = "The server needs at least one realm";
+      }
+      {
+        assertion = lib.length (lib.attrNames cfg.settings.realms) <= 1;
+        message = "Only one realm per server is currently supported.";
+      }
+    ];
+
+    systemd.slices.system-kerberos-server = { };
+    systemd.targets.kerberos-server = {
+      wantedBy = [ "multi-user.target" ];
+    };
+  };
 
-  ###### implementation
-
-  config = mkIf cfg.enable {
-    environment.systemPackages = [ kerberos ];
-    assertions = [{
-      assertion = length (attrNames cfg.realms) <= 1;
-      message = "Only one realm per server is currently supported.";
-    }];
+  meta = {
+    doc = ./kerberos-server.md;
   };
 }
diff --git a/nixos/modules/services/system/kerberos/heimdal.nix b/nixos/modules/services/system/kerberos/heimdal.nix
index ecafc92766704..cec4dd276e6b9 100644
--- a/nixos/modules/services/system/kerberos/heimdal.nix
+++ b/nixos/modules/services/system/kerberos/heimdal.nix
@@ -1,68 +1,87 @@
 { pkgs, config, lib, ... } :
 
 let
-  inherit (lib) mkIf concatStringsSep concatMapStrings toList mapAttrs
-    mapAttrsToList;
+  inherit (lib)  mapAttrs;
   cfg = config.services.kerberos_server;
-  kerberos = config.security.krb5.package;
-  stateDir = "/var/heimdal";
-  aclFiles = mapAttrs
-    (name: {acl, ...}: pkgs.writeText "${name}.acl" (concatMapStrings ((
-      {principal, access, target, ...} :
-      "${principal}\t${concatStringsSep "," (toList access)}\t${target}\n"
-    )) acl)) cfg.realms;
+  package = config.security.krb5.package;
 
-  kdcConfigs = mapAttrsToList (name: value: ''
-    database = {
-      dbname = ${stateDir}/heimdal
-      acl_file = ${value}
-    }
-  '') aclFiles;
-  kdcConfFile = pkgs.writeText "kdc.conf" ''
-    [kdc]
-    ${concatStringsSep "\n" kdcConfigs}
-  '';
+  aclConfigs = lib.pipe cfg.settings.realms [
+    (mapAttrs (name: { acl, ... }: lib.concatMapStringsSep "\n" (
+      { principal, access, target, ... }:
+      "${principal}\t${lib.concatStringsSep "," (lib.toList access)}\t${target}"
+    ) acl))
+    (lib.mapAttrsToList (name: text:
+      {
+        dbname = "/var/lib/heimdal/heimdal";
+        acl_file = pkgs.writeText "${name}.acl" text;
+      }
+    ))
+  ];
+
+  finalConfig = cfg.settings // {
+    realms = mapAttrs (_: v: removeAttrs v [ "acl" ]) (cfg.settings.realms or { });
+    kdc = (cfg.settings.kdc or { }) // {
+      database = aclConfigs;
+    };
+  };
+
+  format = import ../../../security/krb5/krb5-conf-format.nix { inherit pkgs lib; } { enableKdcACLEntries = true; };
+
+  kdcConfFile = format.generate "kdc.conf" finalConfig;
 in
 
 {
-  # No documentation about correct triggers, so guessing at them.
+  config = lib.mkIf (cfg.enable && package.passthru.implementation == "heimdal") {
+    environment.etc."heimdal-kdc/kdc.conf".source = kdcConfFile;
+
+    systemd.tmpfiles.settings."10-heimdal" = let
+      databases = lib.pipe finalConfig.kdc.database [
+        (map (dbAttrs: dbAttrs.dbname or null))
+        (lib.filter (x: x != null))
+        lib.unique
+      ];
+    in lib.genAttrs databases (_: {
+      d = {
+        user = "root";
+        group = "root";
+        mode = "0700";
+      };
+    });
 
-  config = mkIf (cfg.enable && kerberos == pkgs.heimdal) {
     systemd.services.kadmind = {
       description = "Kerberos Administration Daemon";
-      wantedBy = [ "multi-user.target" ];
-      preStart = ''
-        mkdir -m 0755 -p ${stateDir}
-      '';
-      serviceConfig.ExecStart =
-        "${kerberos}/libexec/kadmind --config-file=/etc/heimdal-kdc/kdc.conf";
+      partOf = [ "kerberos-server.target" ];
+      wantedBy = [ "kerberos-server.target" ];
+      serviceConfig = {
+        ExecStart = "${package}/libexec/kadmind --config-file=/etc/heimdal-kdc/kdc.conf";
+        Slice = "system-kerberos-server.slice";
+        StateDirectory = "heimdal";
+      };
       restartTriggers = [ kdcConfFile ];
     };
 
     systemd.services.kdc = {
       description = "Key Distribution Center daemon";
-      wantedBy = [ "multi-user.target" ];
-      preStart = ''
-        mkdir -m 0755 -p ${stateDir}
-      '';
-      serviceConfig.ExecStart =
-        "${kerberos}/libexec/kdc --config-file=/etc/heimdal-kdc/kdc.conf";
+      partOf = [ "kerberos-server.target" ];
+      wantedBy = [ "kerberos-server.target" ];
+      serviceConfig = {
+        ExecStart = "${package}/libexec/kdc --config-file=/etc/heimdal-kdc/kdc.conf";
+        Slice = "system-kerberos-server.slice";
+        StateDirectory = "heimdal";
+      };
       restartTriggers = [ kdcConfFile ];
     };
 
     systemd.services.kpasswdd = {
       description = "Kerberos Password Changing daemon";
-      wantedBy = [ "multi-user.target" ];
-      preStart = ''
-        mkdir -m 0755 -p ${stateDir}
-      '';
-      serviceConfig.ExecStart = "${kerberos}/libexec/kpasswdd";
+      partOf = [ "kerberos-server.target" ];
+      wantedBy = [ "kerberos-server.target" ];
+      serviceConfig = {
+        ExecStart = "${package}/libexec/kpasswdd";
+        Slice = "system-kerberos-server.slice";
+        StateDirectory = "heimdal";
+      };
       restartTriggers = [ kdcConfFile ];
     };
-
-    environment.etc = {
-      # Can be set via the --config-file option to KDC
-      "heimdal-kdc/kdc.conf".source = kdcConfFile;
-    };
   };
 }
diff --git a/nixos/modules/services/system/kerberos/kerberos-server.md b/nixos/modules/services/system/kerberos/kerberos-server.md
new file mode 100644
index 0000000000000..80c71be1541e4
--- /dev/null
+++ b/nixos/modules/services/system/kerberos/kerberos-server.md
@@ -0,0 +1,55 @@
+# kerberos_server {#module-services-kerberos-server}
+
+Kerberos is a computer-network authentication protocol that works on the basis of tickets to allow nodes communicating over a non-secure network to prove their identity to one another in a secure manner.
+
+This module provides both the MIT and Heimdal implementations of the a Kerberos server.
+
+## Usage {#module-services-kerberos-server-usage}
+
+To enable a Kerberos server:
+
+```nix
+{
+  security.krb5 = {
+    # Here you can choose between the MIT and Heimdal implementations.
+    package = pkgs.krb5;
+    # package = pkgs.heimdal;
+
+    # Optionally set up a client on the same machine as the server
+    enable = true;
+    settings = {
+      libdefaults.default_realm = "EXAMPLE.COM";
+      realms."EXAMPLE.COM" = {
+        kdc = "kerberos.example.com";
+        admin_server = "kerberos.example.com";
+      };
+    };
+  }
+
+  services.kerberos-server = {
+    enable = true;
+    settings = {
+      realms."EXAMPLE.COM" = {
+        acl = [{ principal = "adminuser"; access=  ["add" "cpw"]; }];
+      };
+    };
+  };
+}
+```
+
+## Notes {#module-services-kerberos-server-notes}
+
+- The Heimdal documentation will sometimes assume that state is stored in `/var/heimdal`, but this module uses `/var/lib/heimdal` instead.
+- Due to the heimdal implementation being chosen through `security.krb5.package`, it is not possible to have a system with one implementation of the client and another of the server.
+- While `services.kerberos_server.settings` has a common freeform type between the two implementations, the actual settings that can be set can vary between the two implementations. To figure out what settings are available, you should consult the upstream documentation for the implementation you are using.
+
+## Upstream Documentation {#module-services-kerberos-server-upstream-documentation}
+
+- MIT Kerberos homepage: https://web.mit.edu/kerberos
+- MIT Kerberos docs: https://web.mit.edu/kerberos/krb5-latest/doc/index.html
+
+- Heimdal Kerberos GitHub wiki: https://github.com/heimdal/heimdal/wiki
+- Heimdal kerberos doc manpages (Debian unstable): https://manpages.debian.org/unstable/heimdal-docs/index.html
+- Heimdal Kerberos kdc manpages (Debian unstable): https://manpages.debian.org/unstable/heimdal-kdc/index.html
+
+Note the version number in the URLs, it may be different for the latest version.
diff --git a/nixos/modules/services/system/kerberos/mit.nix b/nixos/modules/services/system/kerberos/mit.nix
index a654bd1fe7e1b..9ce58986e27af 100644
--- a/nixos/modules/services/system/kerberos/mit.nix
+++ b/nixos/modules/services/system/kerberos/mit.nix
@@ -1,31 +1,37 @@
 { pkgs, config, lib, ... } :
 
 let
-  inherit (lib) mkIf concatStrings concatStringsSep concatMapStrings toList
-    mapAttrs mapAttrsToList;
+  inherit (lib) mapAttrs;
   cfg = config.services.kerberos_server;
-  kerberos = config.security.krb5.package;
-  stateDir = "/var/lib/krb5kdc";
+  package = config.security.krb5.package;
   PIDFile = "/run/kdc.pid";
+
+  format = import ../../../security/krb5/krb5-conf-format.nix { inherit pkgs lib; } { enableKdcACLEntries = true; };
+
   aclMap = {
     add = "a"; cpw = "c"; delete = "d"; get = "i"; list = "l"; modify = "m";
     all = "*";
   };
-  aclFiles = mapAttrs
-    (name: {acl, ...}: (pkgs.writeText "${name}.acl" (concatMapStrings (
-      {principal, access, target, ...} :
-      let access_code = map (a: aclMap.${a}) (toList access); in
-      "${principal} ${concatStrings access_code} ${target}\n"
-    ) acl))) cfg.realms;
-  kdcConfigs = mapAttrsToList (name: value: ''
-    ${name} = {
-      acl_file = ${value}
-    }
-  '') aclFiles;
-  kdcConfFile = pkgs.writeText "kdc.conf" ''
-    [realms]
-    ${concatStringsSep "\n" kdcConfigs}
-  '';
+
+  aclConfigs = lib.pipe cfg.settings.realms [
+    (mapAttrs (name: { acl, ... }: lib.concatMapStringsSep "\n" (
+      { principal, access, target, ... }: let
+        access_code = map (a: aclMap.${a}) (lib.toList access);
+      in "${principal} ${lib.concatStrings access_code} ${target}"
+    ) acl))
+
+    (lib.concatMapAttrs (name: text: {
+      ${name} = {
+        acl_file = pkgs.writeText "${name}.acl" text;
+      };
+    }))
+  ];
+
+  finalConfig = cfg.settings // {
+    realms = mapAttrs (n: v: (removeAttrs v [ "acl" ]) // aclConfigs.${n}) (cfg.settings.realms or { });
+  };
+
+  kdcConfFile = format.generate "kdc.conf" finalConfig;
   env = {
     # What Debian uses, could possibly link directly to Nix store?
     KRB5_KDC_PROFILE = "/etc/krb5kdc/kdc.conf";
@@ -33,36 +39,38 @@ let
 in
 
 {
-  config = mkIf (cfg.enable && kerberos == pkgs.krb5) {
+  config = lib.mkIf (cfg.enable && package.passthru.implementation == "krb5") {
+    environment = {
+      etc."krb5kdc/kdc.conf".source = kdcConfFile;
+      variables = env;
+    };
+
     systemd.services.kadmind = {
       description = "Kerberos Administration Daemon";
-      wantedBy = [ "multi-user.target" ];
-      preStart = ''
-        mkdir -m 0755 -p ${stateDir}
-      '';
-      serviceConfig.ExecStart = "${kerberos}/bin/kadmind -nofork";
+      partOf = [ "kerberos-server.target" ];
+      wantedBy = [ "kerberos-server.target" ];
+      serviceConfig = {
+        ExecStart = "${package}/bin/kadmind -nofork";
+        Slice = "system-kerberos-server.slice";
+        StateDirectory = "krb5kdc";
+      };
       restartTriggers = [ kdcConfFile ];
       environment = env;
     };
 
     systemd.services.kdc = {
       description = "Key Distribution Center daemon";
-      wantedBy = [ "multi-user.target" ];
-      preStart = ''
-        mkdir -m 0755 -p ${stateDir}
-      '';
+      partOf = [ "kerberos-server.target" ];
+      wantedBy = [ "kerberos-server.target" ];
       serviceConfig = {
         Type = "forking";
         PIDFile = PIDFile;
-        ExecStart = "${kerberos}/bin/krb5kdc -P ${PIDFile}";
+        ExecStart = "${package}/bin/krb5kdc -P ${PIDFile}";
+        Slice = "system-kerberos-server.slice";
+        StateDirectory = "krb5kdc";
       };
       restartTriggers = [ kdcConfFile ];
       environment = env;
     };
-
-    environment.etc = {
-      "krb5kdc/kdc.conf".source = kdcConfFile;
-    };
-    environment.variables = env;
   };
 }
diff --git a/nixos/modules/services/system/nix-daemon.nix b/nixos/modules/services/system/nix-daemon.nix
index 0a5b0e2fcb80a..3d44bdac34bf6 100644
--- a/nixos/modules/services/system/nix-daemon.nix
+++ b/nixos/modules/services/system/nix-daemon.nix
@@ -164,7 +164,7 @@ in
         nixPackage
         pkgs.nix-info
       ]
-      ++ optional (config.programs.bash.enableCompletion) pkgs.nix-bash-completions;
+      ++ optional (config.programs.bash.completion.enable) pkgs.nix-bash-completions;
 
     systemd.packages = [ nixPackage ];
 
diff --git a/nixos/modules/services/torrent/flood.nix b/nixos/modules/services/torrent/flood.nix
new file mode 100644
index 0000000000000..213f4ef046483
--- /dev/null
+++ b/nixos/modules/services/torrent/flood.nix
@@ -0,0 +1,85 @@
+{ config, lib, pkgs, utils, ... }:
+
+let
+  cfg = config.services.flood;
+in
+{
+  meta.maintainers = with lib.maintainers; [ thiagokokada ];
+
+  options.services.flood = {
+    enable = lib.mkEnableOption "flood";
+    package = lib.mkPackageOption pkgs "flood" { };
+    openFirewall = lib.mkEnableOption "" // {
+      description = "Whether to open the firewall for the port in {option}`services.flood.port`.";
+    };
+    port = lib.mkOption {
+      type = lib.types.int;
+      description = "Port to bind webserver.";
+      default = 3000;
+      example = 3001;
+    };
+    host = lib.mkOption {
+      type = lib.types.str;
+      description = "Host to bind webserver.";
+      default = "localhost";
+      example = "::";
+    };
+    extraArgs = lib.mkOption {
+      type = with lib.types; listOf str;
+      description = "Extra arguments passed to `flood`.";
+      default = [ ];
+      example = [ "--baseuri=/" ];
+    };
+  };
+
+  config = lib.mkIf cfg.enable {
+    systemd.services.flood = {
+      description = "A modern web UI for various torrent clients.";
+      after = [ "network.target" ];
+      wantedBy = [ "multi-user.target" ];
+      unitConfig = {
+        Documentation = "https://github.com/jesec/flood/wiki";
+      };
+      serviceConfig = {
+        Restart = "on-failure";
+        RestartSec = "3s";
+        ExecStart = utils.escapeSystemdExecArgs ([
+          (lib.getExe cfg.package)
+          "--host"
+          cfg.host
+          "--port"
+          (toString cfg.port)
+          "--rundir=/var/lib/flood"
+        ] ++ cfg.extraArgs);
+
+        CapabilityBoundingSet = [ "" ];
+        DynamicUser = true;
+        LockPersonality = true;
+        NoNewPrivileges = true;
+        PrivateDevices = true;
+        PrivateTmp = true;
+        ProtectClock = true;
+        ProtectControlGroups = true;
+        ProtectHome = true;
+        ProtectHostname = true;
+        ProtectKernelLogs = true;
+        ProtectKernelModules = true;
+        ProtectKernelTunables = true;
+        ProtectProc = "invisible";
+        ProtectSystem = "strict";
+        RestrictAddressFamilies = [ "AF_UNIX" "AF_INET" "AF_INET6" ];
+        RestrictNamespaces = true;
+        RestrictRealtime = true;
+        RestrictSUIDSGID = true;
+        StateDirectory = "flood";
+        SystemCallArchitectures = "native";
+        SystemCallFilter = [ "@system-service" "@pkey" "~@privileged" ];
+      };
+    };
+
+    networking.firewall.allowedTCPPorts = lib.mkIf cfg.openFirewall [
+      cfg.port
+    ];
+  };
+}
+
diff --git a/nixos/modules/services/torrent/transmission.nix b/nixos/modules/services/torrent/transmission.nix
index 52b472631dcfe..ceef0db78b094 100644
--- a/nixos/modules/services/torrent/transmission.nix
+++ b/nixos/modules/services/torrent/transmission.nix
@@ -174,7 +174,10 @@ in
         };
       };
 
-      package = mkPackageOption pkgs "transmission" {};
+      package = mkPackageOption pkgs "transmission" {
+        default = "transmission_3";
+        example = "pkgs.transmission_4";
+      };
 
       downloadDirPermissions = mkOption {
         type = with types; nullOr str;
diff --git a/nixos/modules/services/ttys/getty.nix b/nixos/modules/services/ttys/getty.nix
index 011016dd5fd14..e88bb4628635e 100644
--- a/nixos/modules/services/ttys/getty.nix
+++ b/nixos/modules/services/ttys/getty.nix
@@ -101,7 +101,7 @@ in
   config = {
     # Note: this is set here rather than up there so that changing
     # nixos.label would not rebuild manual pages
-    services.getty.greetingLine = mkDefault ''<<< Welcome to NixOS ${config.system.nixos.label} (\m) - \l >>>'';
+    services.getty.greetingLine = mkDefault ''<<< Welcome to ${config.system.nixos.distroName} ${config.system.nixos.label} (\m) - \l >>>'';
     services.getty.helpLine = mkIf (config.documentation.nixos.enable && config.documentation.doc.enable) "\nRun 'nixos-help' for the NixOS manual.";
 
     systemd.services."getty@" =
@@ -158,4 +158,5 @@ in
 
   };
 
+  meta.maintainers = with maintainers; [ RossComputerGuy ];
 }
diff --git a/nixos/modules/services/ttys/kmscon.nix b/nixos/modules/services/ttys/kmscon.nix
index 74314e1e76e40..031c5bbb383e1 100644
--- a/nixos/modules/services/ttys/kmscon.nix
+++ b/nixos/modules/services/ttys/kmscon.nix
@@ -107,7 +107,7 @@ in {
         fonts = optional (cfg.fonts != null) "font-name=${lib.concatMapStringsSep ", " (f: f.name) cfg.fonts}";
       in lib.concatStringsSep "\n" (render ++ fonts);
 
-    hardware.opengl.enable = mkIf cfg.hwRender true;
+    hardware.graphics.enable = mkIf cfg.hwRender true;
 
     fonts = mkIf (cfg.fonts != null) {
       fontconfig.enable = true;
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/video/photonvision.nix b/nixos/modules/services/video/photonvision.nix
index d4568258db7d2..e2b27b3cc4104 100644
--- a/nixos/modules/services/video/photonvision.nix
+++ b/nixos/modules/services/video/photonvision.nix
@@ -6,7 +6,7 @@ in
 {
   options = {
     services.photonvision = {
-      enable = lib.mkEnableOption "Enable PhotonVision";
+      enable = lib.mkEnableOption "PhotonVision";
 
       package = lib.mkPackageOption pkgs "photonvision" {};
 
diff --git a/nixos/modules/services/wayland/cage.nix b/nixos/modules/services/wayland/cage.nix
index 91949f197cfed..870ae58f8646e 100644
--- a/nixos/modules/services/wayland/cage.nix
+++ b/nixos/modules/services/wayland/cage.nix
@@ -101,7 +101,7 @@ in {
       session required ${config.systemd.package}/lib/security/pam_systemd.so
     '';
 
-    hardware.opengl.enable = mkDefault true;
+    hardware.graphics.enable = mkDefault true;
 
     systemd.targets.graphical.wants = [ "cage-tty1.service" ];
 
diff --git a/nixos/modules/services/wayland/hypridle.nix b/nixos/modules/services/wayland/hypridle.nix
new file mode 100644
index 0000000000000..5442802df9871
--- /dev/null
+++ b/nixos/modules/services/wayland/hypridle.nix
@@ -0,0 +1,26 @@
+{ lib, pkgs, config, ... }:
+
+let
+  cfg = config.services.hypridle;
+in
+{
+  options.services.hypridle = {
+    enable = lib.mkEnableOption "hypridle, Hyprland's idle daemon";
+    package = lib.mkPackageOption pkgs "hypridle" { };
+  };
+
+  config = lib.mkIf cfg.enable {
+    environment.systemPackages = [
+      cfg.package
+    ];
+
+    systemd.user.services.hypridle = {
+      description = "Hypridle idle daemon";
+      wantedBy = [ "graphical-session.target" ];
+      partOf = [ "graphical-session.target" ];
+      script = lib.getExe cfg.package;
+    };
+  };
+
+  meta.maintainers = with lib.maintainers; [ johnrtitor ];
+}
diff --git a/nixos/modules/services/web-apps/akkoma.nix b/nixos/modules/services/web-apps/akkoma.nix
index 7c9bf6c465164..8ba3c7eaa1e6a 100644
--- a/nixos/modules/services/web-apps/akkoma.nix
+++ b/nixos/modules/services/web-apps/akkoma.nix
@@ -119,7 +119,7 @@ let
         -o ${escapeShellArg cfg.user } \
         -g ${escapeShellArg cfg.group} \
         <(hexdump -n 16 -e '"%02x"' /dev/urandom) \
-        "$RUNTIME_DIRECTORY/cookie"
+        "''${RUNTIME_DIRECTORY%%:*}/cookie"
     '';
   };
 
@@ -131,7 +131,7 @@ let
         -o ${escapeShellArg cfg.user} \
         -g ${escapeShellArg cfg.group} \
         ${escapeShellArg cfg.dist.cookie._secret} \
-        "$RUNTIME_DIRECTORY/cookie"
+        "''${RUNTIME_DIRECTORY%%:*}/cookie"
     '';
   };
 
@@ -181,7 +181,7 @@ let
     name = "akkoma-config";
     runtimeInputs = with pkgs; [ coreutils replace-secret ];
     text = ''
-      cd "$RUNTIME_DIRECTORY"
+      cd "''${RUNTIME_DIRECTORY%%:*}"
       tmp="$(mktemp config.exs.XXXXXXXXXX)"
       trap 'rm -f "$tmp"' EXIT TERM
 
@@ -279,7 +279,7 @@ let
         cd "${cfg.package}"
 
         RUNTIME_DIRECTORY="''${RUNTIME_DIRECTORY:-/run/akkoma}"
-        AKKOMA_CONFIG_PATH="$RUNTIME_DIRECTORY/config.exs" \
+        AKKOMA_CONFIG_PATH="''${RUNTIME_DIRECTORY%%:*}/config.exs" \
         ERL_EPMD_ADDRESS="${cfg.dist.address}" \
         ERL_EPMD_PORT="${toString cfg.dist.epmdPort}" \
         ERL_FLAGS=${lib.escapeShellArg (lib.escapeShellArgs ([
@@ -287,7 +287,7 @@ let
           "-kernel" "inet_dist_listen_min" (toString cfg.dist.portMin)
           "-kernel" "inet_dist_listen_max" (toString cfg.dist.portMax)
         ] ++ cfg.dist.extraFlags))} \
-        RELEASE_COOKIE="$(<"$RUNTIME_DIRECTORY/cookie")" \
+        RELEASE_COOKIE="$(<"''${RUNTIME_DIRECTORY%%:*}/cookie")" \
         RELEASE_NAME="akkoma" \
           exec "${cfg.package}/bin/$(basename "$0")" "$@"
       '';
@@ -984,7 +984,7 @@ in {
         RemainAfterExit = true;
         UMask = "0077";
 
-        RuntimeDirectory = "akkoma";
+        RuntimeDirectory = mkBefore "akkoma";
 
         ExecStart = mkMerge [
           (mkIf (cfg.dist.cookie == null) [ genScript ])
@@ -1072,7 +1072,7 @@ in {
 
         ProtectProc = "noaccess";
         ProcSubset = "pid";
-        ProtectSystem = mkIf (!isConfined) "strict";
+        ProtectSystem = "strict";
         ProtectHome = true;
         PrivateTmp = true;
         PrivateDevices = true;
@@ -1136,6 +1136,6 @@ in {
     };
   };
 
-  meta.maintainers = with maintainers; [ mvs tcmal ];
+  meta.maintainers = with maintainers; [ mvs ];
   meta.doc = ./akkoma.md;
 }
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/firefly-iii.nix b/nixos/modules/services/web-apps/firefly-iii.nix
index b0024ce09c38e..338f049093202 100644
--- a/nixos/modules/services/web-apps/firefly-iii.nix
+++ b/nixos/modules/services/web-apps/firefly-iii.nix
@@ -3,8 +3,8 @@
 let
   inherit (lib) optionalString mkDefault mkIf mkOption mkEnableOption literalExpression;
   inherit (lib.types) nullOr attrsOf oneOf str int bool path package enum submodule;
-  inherit (lib.strings) concatMapStringsSep removePrefix toShellVars removeSuffix hasSuffix;
-  inherit (lib.attrsets) attrValues genAttrs filterAttrs mapAttrs' nameValuePair;
+  inherit (lib.strings) concatLines removePrefix toShellVars removeSuffix hasSuffix;
+  inherit (lib.attrsets) mapAttrsToList attrValues genAttrs filterAttrs mapAttrs' nameValuePair;
   inherit (builtins) isInt isString toString typeOf;
 
   cfg = config.services.firefly-iii;
@@ -21,18 +21,10 @@ let
     (filterAttrs (n: v: hasSuffix "_FILE" n) cfg.settings);
   env-nonfile-values = filterAttrs (n: v: ! hasSuffix "_FILE" n) cfg.settings;
 
-  envfile = pkgs.writeText "firefly-iii-env" ''
-    ${toShellVars env-file-values}
-    ${toShellVars env-nonfile-values}
-  '';
-
   fileenv-func = ''
-    cp --no-preserve=mode ${envfile} /tmp/firefly-iii-env
-    ${concatMapStringsSep "\n"
-      (n: "${pkgs.replace-secret}/bin/replace-secret ${n} ${n} /tmp/firefly-iii-env")
-      (attrValues env-file-values)}
     set -a
-    . /tmp/firefly-iii-env
+    ${toShellVars env-nonfile-values}
+    ${concatLines (mapAttrsToList (n: v: "${n}=\"$(< ${v})\"") env-file-values)}
     set +a
   '';
 
@@ -41,22 +33,21 @@ let
 
     ${optionalString (cfg.settings.DB_CONNECTION == "sqlite")
       "touch ${cfg.dataDir}/storage/database/database.sqlite"}
-    ${artisan} migrate --seed --no-interaction --force
-    ${artisan} firefly-iii:decrypt-all
+    ${artisan} cache:clear
+    ${artisan} package:discover
     ${artisan} firefly-iii:upgrade-database
-    ${artisan} firefly-iii:correct-database
-    ${artisan} firefly-iii:report-integrity
     ${artisan} firefly-iii:laravel-passport-keys
-    ${artisan} cache:clear
-
-    mv /tmp/firefly-iii-env /run/phpfpm/firefly-iii-env
+    ${artisan} view:cache
+    ${artisan} route:cache
+    ${artisan} config:cache
   '';
 
   commonServiceConfig = {
     Type = "oneshot";
     User = user;
     Group = group;
-    StateDirectory = "${removePrefix "/var/lib/" cfg.dataDir}";
+    StateDirectory = "firefly-iii";
+    ReadWritePaths = [cfg.dataDir];
     WorkingDirectory = cfg.package;
     PrivateTmp = true;
     PrivateDevices = true;
@@ -146,6 +137,7 @@ in {
 
     virtualHost = mkOption {
       type = str;
+      default = "localhost";
       description = ''
         The hostname at which you wish firefly-iii to be served. If you have
         enabled nginx using `services.firefly-iii.enableNginx` then this will
@@ -170,14 +162,15 @@ in {
     };
 
     settings = mkOption {
+      default = {};
       description = ''
         Options for firefly-iii configuration. Refer to
         <https://github.com/firefly-iii/firefly-iii/blob/main/.env.example> for
         details on supported values. All <option>_FILE values supported by
         upstream are supported here.
 
-        APP_URL will be set by `services.firefly-iii.virtualHost`, do not
-        redefine it here.
+        APP_URL will be the same as `services.firefly-iii.virtualHost` if the
+        former is unset in `services.firefly-iii.settings`.
       '';
       example = literalExpression ''
         {
@@ -192,7 +185,6 @@ in {
           DB_PASSWORD_FILE = "/var/secrets/firefly-iii-mysql-password.txt;
         }
       '';
-      default = {};
       type = submodule {
         freeformType = attrsOf (oneOf [str int bool]);
         options = {
@@ -216,9 +208,9 @@ in {
           };
           DB_PORT = mkOption {
             type = nullOr int;
-            default = if cfg.settings.DB_CONNECTION == "sqlite" then null
+            default = if cfg.settings.DB_CONNECTION == "pgsql" then 5432
                       else if cfg.settings.DB_CONNECTION == "mysql" then 3306
-                      else 5432;
+                      else null;
             defaultText = ''
               `null` if DB_CONNECTION is "sqlite", `3306` if "mysql", `5432` if "pgsql"
             '';
@@ -227,6 +219,21 @@ in {
               this value to be filled.
             '';
           };
+          DB_HOST = mkOption {
+            type = str;
+            default = if cfg.settings.DB_CONNECTION == "pgsql" then "/run/postgresql"
+                      else "localhost";
+            defaultText = ''
+              "localhost" if DB_CONNECTION is "sqlite" or "mysql", "/run/postgresql" if "pgsql".
+            '';
+            description = ''
+              The machine which hosts your database. This is left at the
+              default value for "mysql" because we use the "DB_SOCKET" option
+              to connect to a unix socket instead. "pgsql" requires that the
+              unix socket location be specified here instead of at "DB_SOCKET".
+              This option does not affect "sqlite".
+            '';
+          };
           APP_KEY_FILE = mkOption {
             type = path;
             description = ''
@@ -235,6 +242,20 @@ in {
               /dev/urandom | base64)" > /path/to/key-file`.
             '';
           };
+          APP_URL = mkOption {
+            type = str;
+            default = if cfg.virtualHost == "localhost" then "http://${cfg.virtualHost}"
+                      else "https://${cfg.virtualHost}";
+            defaultText = ''
+              http(s)://''${config.services.firefly-iii.virtualHost}
+            '';
+            description = ''
+              The APP_URL used by firefly-iii internally. Please make sure this
+              URL matches the external URL of your Firefly III installation. It
+              is used to validate specific requests and to generate URLs in
+              emails.
+            '';
+          };
         };
       };
     };
@@ -242,12 +263,6 @@ in {
 
   config = mkIf cfg.enable {
 
-    services.firefly-iii = {
-      settings = {
-        APP_URL = cfg.virtualHost;
-      };
-    };
-
     services.phpfpm.pools.firefly-iii = {
       inherit user group;
       phpPackage = cfg.package.phpPackage;
@@ -262,29 +277,25 @@ in {
       } // cfg.poolConfig;
     };
 
-    systemd.services.phpfpm-firefly-iii.serviceConfig = {
-      EnvironmentFile = "/run/phpfpm/firefly-iii-env";
-      ExecStartPost = "${pkgs.coreutils}/bin/rm /run/phpfpm/firefly-iii-env";
-    };
-
     systemd.services.firefly-iii-setup = {
+      after = [ "postgresql.service" "mysql.service" ];
       requiredBy = [ "phpfpm-firefly-iii.service" ];
       before = [ "phpfpm-firefly-iii.service" ];
       serviceConfig = {
         ExecStart = firefly-iii-maintenance;
-        RuntimeDirectory = "phpfpm";
-        RuntimeDirectoryPreserve = true;
+        RemainAfterExit = true;
       } // commonServiceConfig;
       unitConfig.JoinsNamespaceOf = "phpfpm-firefly-iii.service";
+      restartTriggers = [ cfg.package ];
     };
 
     systemd.services.firefly-iii-cron = {
+      after = [ "firefly-iii-setup.service" "postgresql.service" "mysql.service" ];
+      wants = [ "firefly-iii-setup.service" ];
       description = "Daily Firefly III cron job";
-      script = ''
-        ${fileenv-func}
-        ${artisan} firefly-iii:cron
-      '';
-      serviceConfig = commonServiceConfig;
+      serviceConfig = {
+        ExecStart = "${artisan} firefly-iii:cron";
+      } // commonServiceConfig;
     };
 
     systemd.timers.firefly-iii-cron = {
@@ -295,6 +306,7 @@ in {
         Persistent = true;
       };
       wantedBy = [ "timers.target" ];
+      restartTriggers = [ cfg.package ];
     };
 
     services.nginx = mkIf cfg.enableNginx {
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/freshrss.nix b/nixos/modules/services/web-apps/freshrss.nix
index 77c5ecb246171..021101fecaa48 100644
--- a/nixos/modules/services/web-apps/freshrss.nix
+++ b/nixos/modules/services/web-apps/freshrss.nix
@@ -10,7 +10,7 @@ in
   meta.maintainers = with maintainers; [ etu stunkymonkey mattchrist ];
 
   options.services.freshrss = {
-    enable = mkEnableOption "FreshRSS feed reader";
+    enable = mkEnableOption "FreshRSS RSS aggregator and reader with php-fpm backend.";
 
     package = mkPackageOption pkgs "freshrss" { };
 
@@ -108,7 +108,7 @@ in
       type = types.str;
       default = poolName;
       description = ''
-        Name of the phpfpm pool to use and setup. If not specified, a pool will be created
+        Name of the php-fpm pool to use and setup. If not specified, a pool will be created
         with default values.
       '';
     };
@@ -255,13 +255,10 @@ in
         {
           description = "Set up the state directory for FreshRSS before use";
           wantedBy = [ "multi-user.target" ];
-          serviceConfig = defaultServiceConfig //{
-            Type = "oneshot";
-            User = "freshrss";
-            Group = "freshrss";
-            StateDirectory = "freshrss";
-            WorkingDirectory = cfg.package;
+          serviceConfig = defaultServiceConfig // {
+            RemainAfterExit = true;
           };
+          restartIfChanged = true;
           environment = {
             DATA_PATH = cfg.dataDir;
           };
@@ -299,7 +296,7 @@ in
         environment = {
           DATA_PATH = cfg.dataDir;
         };
-        serviceConfig = defaultServiceConfig //{
+        serviceConfig = defaultServiceConfig // {
           ExecStart = "${cfg.package}/app/actualize_script.php";
         };
       };
diff --git a/nixos/modules/services/web-apps/invoiceplane.nix b/nixos/modules/services/web-apps/invoiceplane.nix
index 4d0e25958e35a..9a9f180b21021 100644
--- a/nixos/modules/services/web-apps/invoiceplane.nix
+++ b/nixos/modules/services/web-apps/invoiceplane.nix
@@ -39,20 +39,17 @@ let
 
   extraConfig = hostName: cfg: let
     settings = mapAttrsToList (k: v: "${k}=${mkPhpValue v}") cfg.settings;
-  in pkgs.writeText "extraConfig.php" ''
-    ${concatStringsSep "\n" settings}
-    ${toString cfg.extraConfig}
-  '';
+  in pkgs.writeText "extraConfig.php" (concatStringsSep "\n" settings);
 
   pkg = hostName: cfg: pkgs.stdenv.mkDerivation rec {
     pname = "invoiceplane-${hostName}";
     version = src.version;
     src = pkgs.invoiceplane;
 
-    postPhase = ''
+    postPatch = ''
       # Patch index.php file to load additional config file
       substituteInPlace index.php \
-        --replace "require('vendor/autoload.php');" "require('vendor/autoload.php'); \$dotenv = Dotenv\Dotenv::createImmutable(__DIR__, 'extraConfig.php'); \$dotenv->load();";
+        --replace-fail "require('vendor/autoload.php');" "require('vendor/autoload.php'); \$dotenv = Dotenv\Dotenv::createImmutable(__DIR__, 'extraConfig.php'); \$dotenv->load();";
     '';
 
     installPhase = ''
@@ -182,25 +179,6 @@ let
           '';
         };
 
-        extraConfig = mkOption {
-          type = types.nullOr types.lines;
-          default = null;
-          example = ''
-            SETUP_COMPLETED=true
-            DISABLE_SETUP=true
-            IP_URL=https://invoice.example.com
-          '';
-          description = ''
-            InvoicePlane configuration. Refer to
-            <https://github.com/InvoicePlane/InvoicePlane/blob/master/ipconfig.php.example>
-            for details on supported values.
-
-            **Note**: Please pass structured settings via
-            `services.invoiceplane.sites.${name}.settings` instead, this option
-            will get deprecated in the future.
-          '';
-        };
-
         settings = mkOption {
           type = types.attrsOf types.anything;
           default = {};
@@ -269,12 +247,6 @@ in
   # implementation
   config = mkIf (eachSite != {}) (mkMerge [{
 
-    warnings = flatten (mapAttrsToList (hostName: cfg: [
-      (optional (cfg.extraConfig != null) ''
-        services.invoiceplane.sites."${hostName}".extraConfig will be deprecated in future releases, please use the settings option now.
-      '')
-    ]) eachSite);
-
     assertions = flatten (mapAttrsToList (hostName: cfg: [
       { assertion = cfg.database.createLocally -> cfg.database.user == user;
         message = ''services.invoiceplane.sites."${hostName}".database.user must be ${user} if the database is to be automatically provisioned'';
diff --git a/nixos/modules/services/web-apps/keycloak.md b/nixos/modules/services/web-apps/keycloak.md
index 020bee4003489..4036885ce151c 100644
--- a/nixos/modules/services/web-apps/keycloak.md
+++ b/nixos/modules/services/web-apps/keycloak.md
@@ -68,13 +68,11 @@ to `/auth`. See the option description
 for more details.
 :::
 
-[](#opt-services.keycloak.settings.hostname-strict-backchannel)
-determines whether Keycloak should force all requests to go
-through the frontend URL. By default,
-Keycloak allows backend requests to
-instead use its local hostname or IP address and may also
-advertise it to clients through its OpenID Connect Discovery
-endpoint.
+[](#opt-services.keycloak.settings.hostname-backchannel-dynamic)
+Keycloak has the capability to offer a separate URL for backchannel requests,
+enabling internal communication while maintaining the use of a public URL
+for frontchannel requests. Moreover, the backchannel is dynamically
+resolved based on incoming headers endpoint.
 
 For more information on hostname configuration, see the [Hostname
 section of the Keycloak Server Installation and Configuration
diff --git a/nixos/modules/services/web-apps/keycloak.nix b/nixos/modules/services/web-apps/keycloak.nix
index cf1282b3d4cf4..36bae2575974e 100644
--- a/nixos/modules/services/web-apps/keycloak.nix
+++ b/nixos/modules/services/web-apps/keycloak.nix
@@ -328,8 +328,7 @@ in
             };
 
             hostname = mkOption {
-              type = nullOr str;
-              default = null;
+              type = str;
               example = "keycloak.example.com";
               description = ''
                 The hostname part of the public URL used as base for
@@ -340,16 +339,13 @@ in
               '';
             };
 
-            hostname-strict-backchannel = mkOption {
+            hostname-backchannel-dynamic = mkOption {
               type = bool;
               default = false;
               example = true;
               description = ''
-                Whether Keycloak should force all requests to go
-                through the frontend URL. By default, Keycloak allows
-                backend requests to instead use its local hostname or
-                IP address and may also advertise it to clients
-                through its OpenID Connect Discovery endpoint.
+                Enables dynamic resolving of backchannel URLs,
+                including hostname, scheme, port and context path.
 
                 See <https://www.keycloak.org/server/hostname>
                 for more information about hostname configuration.
@@ -466,7 +462,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
@@ -481,12 +478,20 @@ in
             message = "Setting up a local PostgreSQL db for Keycloak requires `standard_conforming_strings` turned on to work reliably";
           }
           {
-            assertion = cfg.settings.hostname != null || cfg.settings.hostname-url or null != null;
-            message = "Setting the Keycloak hostname is required, see `services.keycloak.settings.hostname`";
+            assertion = cfg.settings.hostname-url or null == null;
+            message = ''
+              The option `services.keycloak.settings.hostname-url' has been removed.
+              Set `services.keycloak.settings.hostname' instead.
+              See [New Hostname options](https://www.keycloak.org/docs/25.0.0/upgrading/#new-hostname-options) for details.
+            '';
           }
           {
-            assertion = !(cfg.settings.hostname != null && cfg.settings.hostname-url or null != null);
-            message = "`services.keycloak.settings.hostname` and `services.keycloak.settings.hostname-url` are mutually exclusive";
+            assertion = cfg.settings.hostname-strict-backchannel or null == null;
+            message = ''
+              The option `services.keycloak.settings.hostname-strict-backchannel' has been removed.
+              Set `services.keycloak.settings.hostname-backchannel-dynamic' instead.
+              See [New Hostname options](https://www.keycloak.org/docs/25.0.0/upgrading/#new-hostname-options) for details.
+            '';
           }
         ];
 
@@ -638,6 +643,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
@@ -663,7 +670,7 @@ in
             '' + ''
               export KEYCLOAK_ADMIN=admin
               export KEYCLOAK_ADMIN_PASSWORD=${escapeShellArg cfg.initialAdminPassword}
-              kc.sh start --optimized
+              kc.sh --verbose start --optimized
             '';
           };
 
diff --git a/nixos/modules/services/web-apps/mastodon.nix b/nixos/modules/services/web-apps/mastodon.nix
index 570f2770fb291..daebd6441cb5d 100644
--- a/nixos/modules/services/web-apps/mastodon.nix
+++ b/nixos/modules/services/web-apps/mastodon.nix
@@ -20,8 +20,6 @@ let
 
     DB_USER = cfg.database.user;
 
-    REDIS_HOST = cfg.redis.host;
-    REDIS_PORT = toString(cfg.redis.port);
     DB_HOST = cfg.database.host;
     DB_NAME = cfg.database.name;
     LOCAL_DOMAIN = cfg.localDomain;
@@ -34,6 +32,8 @@ let
 
     TRUSTED_PROXY_IP = cfg.trustedProxy;
   }
+  // lib.optionalAttrs (cfg.redis.host != null) { REDIS_HOST = cfg.redis.host; }
+  // lib.optionalAttrs (cfg.redis.port != null) { REDIS_PORT = toString(cfg.redis.port); }
   // lib.optionalAttrs (cfg.redis.createLocally && cfg.redis.enableUnixSocket) { REDIS_URL = "unix://${config.services.redis.servers.mastodon.unixSocket}"; }
   // lib.optionalAttrs (cfg.database.host != "/run/postgresql" && cfg.database.port != null) { DB_PORT = toString cfg.database.port; }
   // lib.optionalAttrs cfg.smtp.authenticate { SMTP_LOGIN  = cfg.smtp.user; }
@@ -90,6 +90,11 @@ let
     SystemCallArchitectures = "native";
   };
 
+  # Services that all Mastodon units After= and Requires= on
+  commonServices = lib.optional redisActuallyCreateLocally "redis-mastodon.service"
+    ++ lib.optional databaseActuallyCreateLocally "postgresql.service"
+    ++ lib.optional cfg.automaticMigrations "mastodon-init-db.service";
+
   envFile = pkgs.writeText "mastodon.env" (lib.concatMapStrings (s: s + "\n") (
     (lib.concatLists (lib.mapAttrsToList (name: value:
       lib.optional (value != null) ''${name}="${toString value}"''
@@ -117,14 +122,8 @@ let
       jobClassLabel = toString ([""] ++ processCfg.jobClasses);
       threads = toString (if processCfg.threads == null then cfg.sidekiqThreads else processCfg.threads);
     in {
-      after = [ "network.target" "mastodon-init-dirs.service" ]
-        ++ lib.optional redisActuallyCreateLocally "redis-mastodon.service"
-        ++ lib.optional databaseActuallyCreateLocally "postgresql.service"
-        ++ lib.optional cfg.automaticMigrations "mastodon-init-db.service";
-      requires = [ "mastodon-init-dirs.service" ]
-        ++ lib.optional redisActuallyCreateLocally "redis-mastodon.service"
-        ++ lib.optional databaseActuallyCreateLocally "postgresql.service"
-        ++ lib.optional cfg.automaticMigrations "mastodon-init-db.service";
+      after = [ "network.target" "mastodon-init-dirs.service" ] ++ commonServices;
+      requires = [ "mastodon-init-dirs.service" ] ++ commonServices;
       description = "Mastodon sidekiq${jobClassLabel}";
       wantedBy = [ "mastodon.target" ];
       environment = env // {
@@ -149,14 +148,8 @@ let
       (map (i: {
         name = "mastodon-streaming-${toString i}";
         value = {
-          after = [ "network.target" "mastodon-init-dirs.service" ]
-            ++ lib.optional redisActuallyCreateLocally "redis-mastodon.service"
-            ++ lib.optional databaseActuallyCreateLocally "postgresql.service"
-            ++ lib.optional cfg.automaticMigrations "mastodon-init-db.service";
-          requires = [ "mastodon-init-dirs.service" ]
-            ++ lib.optional redisActuallyCreateLocally "redis-mastodon.service"
-            ++ lib.optional databaseActuallyCreateLocally "postgresql.service"
-            ++ lib.optional cfg.automaticMigrations "mastodon-init-db.service";
+          after = [ "network.target" "mastodon-init-dirs.service" ] ++ commonServices;
+          requires = [ "mastodon-init-dirs.service" ] ++ commonServices;
           wantedBy = [ "mastodon.target" "mastodon-streaming.target" ];
           description = "Mastodon streaming ${toString i}";
           environment = env // { SOCKET = "/run/mastodon-streaming/streaming-${toString i}.socket"; };
@@ -401,14 +394,20 @@ in {
 
         host = lib.mkOption {
           description = "Redis host.";
-          type = lib.types.str;
-          default = "127.0.0.1";
+          type = lib.types.nullOr lib.types.str;
+          default = if cfg.redis.createLocally && !cfg.redis.enableUnixSocket then "127.0.0.1" else null;
+          defaultText = lib.literalExpression ''
+            if config.${opt.redis.createLocally} && !config.${opt.redis.enableUnixSocket} then "127.0.0.1" else null
+          '';
         };
 
         port = lib.mkOption {
           description = "Redis port.";
-          type = lib.types.port;
-          default = 31637;
+          type = lib.types.nullOr lib.types.port;
+          default = if cfg.redis.createLocally && !cfg.redis.enableUnixSocket then 31637 else null;
+          defaultText = lib.literalExpression ''
+            if config.${opt.redis.createLocally} && !config.${opt.redis.enableUnixSocket} then 31637 else null
+          '';
         };
 
         passwordFile = lib.mkOption {
@@ -632,6 +631,20 @@ in {
   config = lib.mkIf cfg.enable (lib.mkMerge [{
     assertions = [
       {
+        assertion = !redisActuallyCreateLocally -> (cfg.redis.host != "127.0.0.1" && cfg.redis.port != null);
+        message = ''
+          `services.mastodon.redis.host` and `services.mastodon.redis.port` need to be set if
+            `services.mastodon.redis.createLocally` is not enabled.
+        '';
+      }
+      {
+        assertion = redisActuallyCreateLocally -> (!cfg.redis.enableUnixSocket || (cfg.redis.host == null && cfg.redis.port == null));
+        message = ''
+          `services.mastodon.redis.enableUnixSocket` needs to be disabled if
+            `services.mastodon.redis.host` and `services.mastodon.redis.port` is used.
+        '';
+      }
+      {
         assertion = redisActuallyCreateLocally -> (!cfg.redis.enableUnixSocket || cfg.redis.passwordFile == null);
         message = ''
           <option>services.mastodon.redis.enableUnixSocket</option> needs to be disabled if
@@ -783,14 +796,8 @@ in {
     };
 
     systemd.services.mastodon-web = {
-      after = [ "network.target" "mastodon-init-dirs.service" ]
-        ++ lib.optional redisActuallyCreateLocally "redis-mastodon.service"
-        ++ lib.optional databaseActuallyCreateLocally "postgresql.service"
-        ++ lib.optional cfg.automaticMigrations "mastodon-init-db.service";
-      requires = [ "mastodon-init-dirs.service" ]
-        ++ lib.optional redisActuallyCreateLocally "redis-mastodon.service"
-        ++ lib.optional databaseActuallyCreateLocally "postgresql.service"
-        ++ lib.optional cfg.automaticMigrations "mastodon-init-db.service";
+      after = [ "network.target" "mastodon-init-dirs.service" ] ++ commonServices;
+      requires = [ "mastodon-init-dirs.service" ] ++ commonServices;
       wantedBy = [ "mastodon.target" ];
       description = "Mastodon web";
       environment = env // (if cfg.enableUnixSocket
diff --git a/nixos/modules/services/web-apps/mealie.nix b/nixos/modules/services/web-apps/mealie.nix
index 8f68828e7a0be..2484b2489c0d0 100644
--- a/nixos/modules/services/web-apps/mealie.nix
+++ b/nixos/modules/services/web-apps/mealie.nix
@@ -28,8 +28,6 @@ in
         Configuration of the Mealie service.
 
         See [the mealie documentation](https://nightly.mealie.io/documentation/getting-started/installation/backend-config/) for available options and default values.
-
-        In addition to the official documentation, you can set {env}`MEALIE_LOG_FILE`.
       '';
       example = {
         ALLOW_SIGNUP = "false";
@@ -61,6 +59,7 @@ in
         PRODUCTION = "true";
         ALEMBIC_CONFIG_FILE="${pkg}/config/alembic.ini";
         API_PORT = toString cfg.port;
+        BASE_URL = "http://localhost:${toString cfg.port}";
         DATA_DIR = "/var/lib/mealie";
         CRF_MODEL_PATH = "/var/lib/mealie/model.crfmodel";
       } // (builtins.mapAttrs (_: val: toString val) cfg.settings);
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-notify_push.nix b/nixos/modules/services/web-apps/nextcloud-notify_push.nix
index d6d17158a5590..4da5aff0c83e2 100644
--- a/nixos/modules/services/web-apps/nextcloud-notify_push.nix
+++ b/nixos/modules/services/web-apps/nextcloud-notify_push.nix
@@ -90,7 +90,7 @@ in
         export DATABASE_PASSWORD="$(<"${cfg.dbpassFile}")"
       '' + ''
         export DATABASE_URL="${dbUrl}"
-        ${cfg.package}/bin/notify_push '${cfgN.datadir}/config/config.php'
+        exec ${cfg.package}/bin/notify_push '${cfgN.datadir}/config/config.php'
       '';
       serviceConfig = {
         User = "nextcloud";
@@ -98,6 +98,7 @@ in
         RuntimeDirectory = [ "nextcloud-notify_push" ];
         Restart = "on-failure";
         RestartSec = "5s";
+        Type = "notify";
       };
     };
 
diff --git a/nixos/modules/services/web-apps/nextcloud.md b/nixos/modules/services/web-apps/nextcloud.md
index ec860d307b381..0b615deae44be 100644
--- a/nixos/modules/services/web-apps/nextcloud.md
+++ b/nixos/modules/services/web-apps/nextcloud.md
@@ -205,11 +205,6 @@ it complains loudly now. So nothing actionable here by default. Alternatively yo
 * set [](#opt-services.nextcloud.settings.log_type) to "file" to be able to view logs
   from the admin panel.
 
-### Your web server is not properly set up to resolve `.well-known` URLs, failed on: `/.well-known/caldav` {#module-services-nextcloud-warning-wellknown-caldav}
-
-This warning appearing seems to be an upstream issue and is being sorted out
-in [nextcloud/server#45033](https://github.com/nextcloud/server/issues/45033).
-
 ## Maintainer information {#module-services-nextcloud-maintainer-info}
 
 As stated in the previous paragraph, we must provide a clean upgrade-path for Nextcloud
diff --git a/nixos/modules/services/web-apps/nextcloud.nix b/nixos/modules/services/web-apps/nextcloud.nix
index 21f76938f20c5..f4560ed64bb4f 100644
--- a/nixos/modules/services/web-apps/nextcloud.nix
+++ b/nixos/modules/services/web-apps/nextcloud.nix
@@ -80,6 +80,12 @@ let
     mkKeyValue = generators.mkKeyValueDefault {} " = ";
   };
 
+  phpCli = concatStringsSep " " ([
+    "${getExe phpPackage}"
+  ] ++ optionals (cfg.cli.memoryLimit != null) [
+    "-dmemory_limit=${cfg.cli.memoryLimit}"
+  ]);
+
   occ = pkgs.writeScriptBin "nextcloud-occ" ''
     #! ${pkgs.runtimeShell}
     cd ${webroot}
@@ -89,7 +95,7 @@ let
     fi
     export NEXTCLOUD_CONFIG_DIR="${datadir}/config"
     $sudo \
-      ${phpPackage}/bin/php \
+      ${phpCli} \
       occ "$@"
   '';
 
@@ -196,6 +202,9 @@ let
 in {
 
   imports = [
+    (mkRenamedOptionModule
+      [ "services" "nextcloud" "cron" "memoryLimit" ]
+      [ "services" "nextcloud" "cli" "memoryLimit" ])
     (mkRemovedOptionModule [ "services" "nextcloud" "enableBrokenCiphersForSSE" ] ''
       This option has no effect since there's no supported Nextcloud version packaged here
       using OpenSSL for RC4 SSE.
@@ -446,7 +455,13 @@ in {
       dbtableprefix = mkOption {
         type = types.nullOr types.str;
         default = null;
-        description = "Table prefix in Nextcloud's database.";
+        description = ''
+          Table prefix in Nextcloud's database.
+
+          __Note:__ since Nextcloud 20 it's not an option anymore to create a database
+          schema with a custom table prefix. This option only exists for backwards compatibility
+          with installations that were originally provisioned with Nextcloud <20.
+        '';
       };
       adminuser = mkOption {
         type = types.str;
@@ -642,7 +657,6 @@ in {
       type = types.package;
       default = occ;
       defaultText = literalMD "generated script";
-      internal = true;
       description = ''
         The nextcloud-occ program preconfigured to target this Nextcloud instance.
       '';
@@ -793,11 +807,21 @@ in {
         '';
       };
     };
+
+    cli.memoryLimit = mkOption {
+      type = types.nullOr types.str;
+      default = null;
+      example = "1G";
+      description = ''
+        The `memory_limit` of PHP is equal to [](#opt-services.nextcloud.maxUploadSize).
+        The value can be customized for `nextcloud-cron.service` using this option.
+      '';
+    };
   };
 
   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.
@@ -816,6 +840,13 @@ in {
           Using config.services.nextcloud.poolConfig is deprecated and will become unsupported in a future release.
           Please migrate your configuration to config.services.nextcloud.poolSettings.
         '')
+        ++ (optional (cfg.config.dbtableprefix != null) ''
+          Using `services.nextcloud.config.dbtableprefix` is deprecated. Fresh installations with this
+          option set are not allowed anymore since v20.
+
+          If you have an existing installation with a custom table prefix, make sure it is
+          set correctly in `config.php` and remove the option from your NixOS config.
+        '')
         ++ (optional (versionOlder cfg.package.version "25") (upgradeWarning 24 "22.11"))
         ++ (optional (versionOlder cfg.package.version "26") (upgradeWarning 25 "23.05"))
         ++ (optional (versionOlder cfg.package.version "27") (upgradeWarning 26 "23.11"))
@@ -939,6 +970,7 @@ in {
 
         in {
           wantedBy = [ "multi-user.target" ];
+          wants = [ "nextcloud-update-db.service" ];
           before = [ "phpfpm-nextcloud.service" ];
           after = optional mysqlLocal "mysql.service" ++ optional pgsqlLocal "postgresql.service";
           requires = optional mysqlLocal "mysql.service" ++ optional pgsqlLocal "postgresql.service";
@@ -997,10 +1029,10 @@ in {
           after = [ "nextcloud-setup.service" ];
           environment.NEXTCLOUD_CONFIG_DIR = "${datadir}/config";
           serviceConfig = {
-            Type = "oneshot";
+            Type = "exec";
             User = "nextcloud";
-            ExecCondition = "${lib.getExe phpPackage} -f ${webroot}/occ status -e";
-            ExecStart = "${lib.getExe phpPackage} -f ${webroot}/cron.php";
+            ExecCondition = "${phpCli} -f ${webroot}/occ status -e";
+            ExecStart = "${phpCli} -f ${webroot}/cron.php";
             KillMode = "process";
           };
         };
@@ -1013,6 +1045,20 @@ in {
           };
           startAt = cfg.autoUpdateApps.startAt;
         };
+        nextcloud-update-db = {
+          after = [ "nextcloud-setup.service" ];
+          environment.NEXTCLOUD_CONFIG_DIR = "${datadir}/config";
+          script = ''
+            ${occ}/bin/nextcloud-occ db:add-missing-columns
+            ${occ}/bin/nextcloud-occ db:add-missing-indices
+            ${occ}/bin/nextcloud-occ db:add-missing-primary-keys
+          '';
+          serviceConfig = {
+            Type = "exec";
+            User = "nextcloud";
+            ExecCondition = "${phpCli} -f ${webroot}/occ status -e";
+          };
+        };
       };
 
       services.phpfpm = {
@@ -1105,10 +1151,10 @@ in {
             extraConfig = ''
               absolute_redirect off;
               location = /.well-known/carddav {
-                return 301 /remote.php/dav;
+                return 301 /remote.php/dav/;
               }
               location = /.well-known/caldav {
-                return 301 /remote.php/dav;
+                return 301 /remote.php/dav/;
               }
               location ~ ^/\.well-known/(?!acme-challenge|pki-validation) {
                 return 301 /index.php$request_uri;
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..9bd2cf310c0af
--- /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 { inherit (cfg) ollamaUrl; };
+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/node-red.nix b/nixos/modules/services/web-apps/node-red.nix
index 7c8a2a6687b9c..4c095ea79bbde 100644
--- a/nixos/modules/services/web-apps/node-red.nix
+++ b/nixos/modules/services/web-apps/node-red.nix
@@ -5,15 +5,6 @@ with lib;
 let
   cfg = config.services.node-red;
   defaultUser = "node-red";
-  finalPackage = if cfg.withNpmAndGcc then node-red_withNpmAndGcc else cfg.package;
-  node-red_withNpmAndGcc = pkgs.runCommand "node-red" {
-    nativeBuildInputs = [ pkgs.makeWrapper ];
-  }
-  ''
-    mkdir -p $out/bin
-    makeWrapper ${pkgs.nodePackages.node-red}/bin/node-red $out/bin/node-red \
-      --set PATH '${lib.makeBinPath [ pkgs.nodePackages.npm pkgs.gcc ]}:$PATH' \
-  '';
 in
 {
   options.services.node-red = {
@@ -127,11 +118,12 @@ in
       environment = {
         HOME = cfg.userDir;
       };
+      path = lib.optionals cfg.withNpmAndGcc [ pkgs.nodePackages.npm pkgs.gcc ];
       serviceConfig = mkMerge [
         {
           User = cfg.user;
           Group = cfg.group;
-          ExecStart = "${finalPackage}/bin/node-red ${pkgs.lib.optionalString cfg.safe "--safe"} --settings ${cfg.configFile} --port ${toString cfg.port} --userDir ${cfg.userDir} ${concatStringsSep " " (mapAttrsToList (name: value: "-D ${name}=${value}") cfg.define)}";
+          ExecStart = "${cfg.package}/bin/node-red ${pkgs.lib.optionalString cfg.safe "--safe"} --settings ${cfg.configFile} --port ${toString cfg.port} --userDir ${cfg.userDir} ${concatStringsSep " " (mapAttrsToList (name: value: "-D ${name}=${value}") cfg.define)}";
           PrivateTmp = true;
           Restart = "always";
           WorkingDirectory = cfg.userDir;
diff --git a/nixos/modules/services/web-apps/plausible.nix b/nixos/modules/services/web-apps/plausible.nix
index 8e49e591f75cd..1f909bbd67a36 100644
--- a/nixos/modules/services/web-apps/plausible.nix
+++ b/nixos/modules/services/web-apps/plausible.nix
@@ -276,8 +276,11 @@ in {
             ${lib.optionalString (cfg.mail.smtp.passwordFile != null)
               ''export SMTP_USER_PWD="$(< $CREDENTIALS_DIRECTORY/SMTP_USER_PWD )"''}
 
-            # setup
-            ${cfg.package}/createdb.sh
+            ${lib.optionalString cfg.database.postgres.setup ''
+              # setup
+              ${cfg.package}/createdb.sh
+            ''}
+
             ${cfg.package}/migrate.sh
             export IP_GEOLOCATION_DB=${pkgs.dbip-country-lite}/share/dbip/dbip-country-lite.mmdb
             ${cfg.package}/bin/plausible eval "(Plausible.Release.prepare() ; Plausible.Auth.create_user(\"$ADMIN_USER_NAME\", \"$ADMIN_USER_EMAIL\", \"$ADMIN_USER_PWD\"))"
@@ -326,6 +329,6 @@ in {
     ];
   };
 
-  meta.maintainers = with maintainers; [ ];
+  meta.maintainers = with maintainers; [ xanderio ];
   meta.doc = ./plausible.md;
 }
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..9786b61160260 100644
--- a/nixos/modules/services/web-apps/pretix.nix
+++ b/nixos/modules/services/web-apps/pretix.nix
@@ -310,7 +310,7 @@ in
               type = types.str;
               default = "redis+socket://${config.services.redis.servers.pretix.unixSocket}?virtual_host=1";
               defaultText = literalExpression ''
-                optionalString config.services.pretix.celery.enable "redis+socket://''${config.services.redis.servers.pretix.unixSocket}?virtual_host=1"
+                redis+socket://''${config.services.redis.servers.pretix.unixSocket}?virtual_host=1
               '';
               description = ''
                 URI to the celery backend used for the asynchronous job queue.
@@ -321,7 +321,7 @@ in
               type = types.str;
               default = "redis+socket://${config.services.redis.servers.pretix.unixSocket}?virtual_host=2";
               defaultText = literalExpression ''
-                optionalString config.services.pretix.celery.enable "redis+socket://''${config.services.redis.servers.pretix.unixSocket}?virtual_host=2"
+                redis+socket://''${config.services.redis.servers.pretix.unixSocket}?virtual_host=2
               '';
               description = ''
                 URI to the celery broker used for the asynchronous job queue.
@@ -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/slskd.nix b/nixos/modules/services/web-apps/slskd.nix
index 15a5fd1177adf..6254fe294eeed 100644
--- a/nixos/modules/services/web-apps/slskd.nix
+++ b/nixos/modules/services/web-apps/slskd.nix
@@ -5,7 +5,7 @@ let
   defaultUser = "slskd";
 in {
   options.services.slskd = with lib; with types; {
-    enable = mkEnableOption "enable slskd";
+    enable = mkEnableOption "slskd";
 
     package = mkPackageOptionMD pkgs "slskd" { };
 
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-apps/zitadel.nix b/nixos/modules/services/web-apps/zitadel.nix
index 99b0a0bc56f67..ed7fae8d9dda0 100644
--- a/nixos/modules/services/web-apps/zitadel.nix
+++ b/nixos/modules/services/web-apps/zitadel.nix
@@ -219,5 +219,5 @@ in
     users.groups.zitadel = lib.mkIf (cfg.group == "zitadel") { };
   };
 
-  meta.maintainers = with lib.maintainers; [ Sorixelle ];
+  meta.maintainers = [ ];
 }
diff --git a/nixos/modules/services/web-servers/bluemap.nix b/nixos/modules/services/web-servers/bluemap.nix
new file mode 100644
index 0000000000000..731468fd9a0ec
--- /dev/null
+++ b/nixos/modules/services/web-servers/bluemap.nix
@@ -0,0 +1,309 @@
+{ 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;
+      description = "Domain on which nginx will serve the bluemap webapp";
+    };
+
+    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 08ce50bff62c0..064a0c71b586b 100644
--- a/nixos/modules/services/web-servers/caddy/default.nix
+++ b/nixos/modules/services/web-servers/caddy/default.nix
@@ -360,14 +360,15 @@ in
       serviceConfig = let
         runOptions = ''--config ${configPath} ${optionalString (cfg.adapter != null) "--adapter ${cfg.adapter}"}'';
       in {
+        # Override the `ExecStart` line from upstream's systemd unit file by our own:
         # https://www.freedesktop.org/software/systemd/man/systemd.service.html#ExecStart=
         # 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;
-        ReadWriteDirectories = cfg.dataDir;
+        ReadWritePaths = [ cfg.dataDir ];
         StateDirectory = mkIf (cfg.dataDir == "/var/lib/caddy") [ "caddy" ];
         LogsDirectory = mkIf (cfg.logDir == "/var/log/caddy") [ "caddy" ];
         Restart = "on-failure";
diff --git a/nixos/modules/services/web-servers/garage.nix b/nixos/modules/services/web-servers/garage.nix
index 39ea8f21b126f..7cf71ff6ff06f 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.version "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/web-servers/nginx/tailscale-auth.nix b/nixos/modules/services/web-servers/nginx/tailscale-auth.nix
index ca272268f5724..de1d708cbb423 100644
--- a/nixos/modules/services/web-servers/nginx/tailscale-auth.nix
+++ b/nixos/modules/services/web-servers/nginx/tailscale-auth.nix
@@ -1,4 +1,4 @@
-{ config, lib, pkgs, ... }:
+{ config, lib, ... }:
 
 let
   inherit (lib)
@@ -22,7 +22,7 @@ in
   ];
 
   options.services.nginx.tailscaleAuth = {
-    enable = mkEnableOption "Enable tailscale.nginx-auth, to authenticate nginx users via tailscale.";
+    enable = mkEnableOption "tailscale.nginx-auth, to authenticate nginx users via tailscale";
 
     expectedTailnet = mkOption {
       default = "";
diff --git a/nixos/modules/services/web-servers/traefik.nix b/nixos/modules/services/web-servers/traefik.nix
index 9c53455bcf3d7..1a65ce21112ee 100644
--- a/nixos/modules/services/web-servers/traefik.nix
+++ b/nixos/modules/services/web-servers/traefik.nix
@@ -170,7 +170,7 @@ in {
         PrivateDevices = true;
         ProtectHome = true;
         ProtectSystem = "full";
-        ReadWriteDirectories = cfg.dataDir;
+        ReadWritePaths = [ cfg.dataDir ];
         RuntimeDirectory = "traefik";
       };
     };
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/desktop-managers/pantheon.nix b/nixos/modules/services/x11/desktop-managers/pantheon.nix
index 008bc65eb6a4f..0e9a06706d4f6 100644
--- a/nixos/modules/services/x11/desktop-managers/pantheon.nix
+++ b/nixos/modules/services/x11/desktop-managers/pantheon.nix
@@ -269,11 +269,6 @@ in
       programs.bash.vteIntegration = mkDefault true;
       programs.zsh.vteIntegration = mkDefault true;
 
-      # Use native GTK file chooser on Qt apps. This is because Qt does not know Pantheon.
-      # https://invent.kde.org/qt/qt/qtbase/-/blob/6.6/src/gui/platform/unix/qgenericunixthemes.cpp#L1312
-      # https://github.com/elementary/default-settings/blob/7.0.2/profile.d/qt-qpa-platformtheme.sh
-      environment.variables.QT_QPA_PLATFORMTHEME = mkDefault "gtk3";
-
       # Default Fonts
       fonts.packages = with pkgs; [
         inter
diff --git a/nixos/modules/services/x11/desktop-managers/phosh.nix b/nixos/modules/services/x11/desktop-managers/phosh.nix
index e8494b2c017c9..12b39f927c012 100644
--- a/nixos/modules/services/x11/desktop-managers/phosh.nix
+++ b/nixos/modules/services/x11/desktop-managers/phosh.nix
@@ -216,7 +216,7 @@ in
 
     security.pam.services.phosh = {};
 
-    hardware.opengl.enable = mkDefault true;
+    hardware.graphics.enable = mkDefault true;
 
     services.gnome.core-shell.enable = true;
     services.gnome.core-os-services.enable = true;
diff --git a/nixos/modules/services/x11/desktop-managers/plasma5.nix b/nixos/modules/services/x11/desktop-managers/plasma5.nix
index 7d80b9b2641c3..53d3b91bfa17c 100644
--- a/nixos/modules/services/x11/desktop-managers/plasma5.nix
+++ b/nixos/modules/services/x11/desktop-managers/plasma5.nix
@@ -327,7 +327,7 @@ in
       };
 
       # Enable GTK applications to load SVG icons
-      services.xserver.gdk-pixbuf.modulePackages = [ pkgs.librsvg ];
+      programs.gdk-pixbuf.modulePackages = [ pkgs.librsvg ];
 
       fonts.packages = with pkgs; [ cfg.notoPackage hack-font ];
       fonts.fontconfig.defaultFonts = {
diff --git a/nixos/modules/services/x11/desktop-managers/xfce.nix b/nixos/modules/services/x11/desktop-managers/xfce.nix
index 85d0d199de3f2..69a83ecb72065 100644
--- a/nixos/modules/services/x11/desktop-managers/xfce.nix
+++ b/nixos/modules/services/x11/desktop-managers/xfce.nix
@@ -116,7 +116,7 @@ in
     ] # TODO: NetworkManager doesn't belong here
       ++ optional config.networking.networkmanager.enable networkmanagerapplet
       ++ optional config.powerManagement.enable xfce4-power-manager
-      ++ optionals config.hardware.pulseaudio.enable [
+      ++ optionals (config.hardware.pulseaudio.enable || config.services.pipewire.pulse.enable) [
         pavucontrol
         # volume up/down keys support:
         # xfce4-pulseaudio-plugin includes all the functionalities of xfce4-volumed-pulse
@@ -153,7 +153,7 @@ in
     }];
 
     services.xserver.updateDbusEnvironment = true;
-    services.xserver.gdk-pixbuf.modulePackages = [ pkgs.librsvg ];
+    programs.gdk-pixbuf.modulePackages = [ pkgs.librsvg ];
 
     # Enable helpful DBus services.
     services.udisks2.enable = true;
diff --git a/nixos/modules/services/x11/window-managers/clfswm.nix b/nixos/modules/services/x11/window-managers/clfswm.nix
index 5500c77a038be..09b49962f2ad7 100644
--- a/nixos/modules/services/x11/window-managers/clfswm.nix
+++ b/nixos/modules/services/x11/window-managers/clfswm.nix
@@ -10,7 +10,7 @@ in
   options = {
     services.xserver.windowManager.clfswm = {
       enable = mkEnableOption "clfswm";
-      package = mkPackageOption pkgs [ "lispPackages" "clfswm" ] { };
+      package = mkPackageOption pkgs [ "sbclPackages" "clfswm" ] { };
     };
   };
 
diff --git a/nixos/modules/services/x11/window-managers/qtile.nix b/nixos/modules/services/x11/window-managers/qtile.nix
index 78152283a0a58..4603ca3fb50f0 100644
--- a/nixos/modules/services/x11/window-managers/qtile.nix
+++ b/nixos/modules/services/x11/window-managers/qtile.nix
@@ -4,10 +4,13 @@ with lib;
 
 let
   cfg = config.services.xserver.windowManager.qtile;
-  pyEnv = pkgs.python3.withPackages (p: [ (cfg.package.unwrapped or cfg.package) ] ++ (cfg.extraPackages p));
 in
 
 {
+  imports = [
+    (mkRemovedOptionModule [ "services" "xserver" "windowManager" "qtile" "backend" ] "The qtile package now provides separate display sessions for both X11 and Wayland.")
+  ];
+
   options.services.xserver.windowManager.qtile = {
     enable = mkEnableOption "qtile";
 
@@ -23,14 +26,6 @@ in
       '';
     };
 
-    backend = mkOption {
-      type = types.enum [ "x11" "wayland" ];
-      default = "x11";
-      description = ''
-          Backend to use in qtile: `x11` or `wayland`.
-      '';
-    };
-
     extraPackages = mkOption {
         type = types.functionTo (types.listOf types.package);
         default = _: [];
@@ -48,24 +43,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.session = [{
-      name = "qtile";
-      start = ''
-        ${pyEnv}/bin/qtile start -b ${cfg.backend} \
-        ${optionalString (cfg.configFile != null)
-        "--config \"${cfg.configFile}\""} &
-        waitPID=$!
-      '';
-    }];
+    services = {
+      xserver.windowManager.qtile.finalPackage = pkgs.python3.pkgs.qtile.override { extraPackages = cfg.extraPackages pkgs.python3.pkgs; };
+      displayManager.sessionPackages = [ cfg.finalPackage ];
+    };
 
-    environment.systemPackages = [
-      # pkgs.qtile is currently a buildenv of qtile and its dependencies.
-      # For userland commands, we want the underlying package so that
-      # packages such as python don't bleed into userland and overwrite intended behavior.
-      (cfg.package.unwrapped or cfg.package)
-    ];
+    environment = {
+      etc."xdg/qtile/config.py" = mkIf (cfg.configFile != null) { source = cfg.configFile; };
+      systemPackages = [ cfg.finalPackage ];
+    };
   };
 }
diff --git a/nixos/modules/services/x11/xserver.nix b/nixos/modules/services/x11/xserver.nix
index e13c273746701..57e83399eded6 100644
--- a/nixos/modules/services/x11/xserver.nix
+++ b/nixos/modules/services/x11/xserver.nix
@@ -302,7 +302,7 @@ in
         default = [ "modesetting" "fbdev" ];
         example = [
           "nvidia"
-          "amdgpu-pro"
+          "amdgpu"
         ];
         # TODO(@oxij): think how to easily add the rest, like those nvidia things
         relatedPackages = concatLists
@@ -716,10 +716,7 @@ in
 
         restartIfChanged = false;
 
-        environment =
-          optionalAttrs config.hardware.opengl.setLdLibraryPath
-            { LD_LIBRARY_PATH = lib.makeLibraryPath [ pkgs.addOpenGLRunpath.driverLink ]; }
-          // config.services.displayManager.environment;
+        environment = config.services.displayManager.environment;
 
         preStart =
           ''
@@ -728,9 +725,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/switch-to-configuration.pl b/nixos/modules/system/activation/switch-to-configuration.pl
index ba45231465fb4..cabc1dcc2d65a 100755
--- a/nixos/modules/system/activation/switch-to-configuration.pl
+++ b/nixos/modules/system/activation/switch-to-configuration.pl
@@ -472,6 +472,9 @@ sub handle_modified_unit { ## no critic(Subroutines::ProhibitManyArgs, Subroutin
             $units_to_reload->{$unit} = 1;
             record_unit($reload_list_file, $unit);
         }
+        elsif ($unit eq "dbus.service" || $unit eq "dbus-broker.service") {
+            # dbus service should only ever be reloaded, not started/stoped/restarted as that would break the system.
+        }
         elsif (!parse_systemd_bool(\%new_unit_info, "Service", "X-RestartIfChanged", 1) || parse_systemd_bool(\%new_unit_info, "Unit", "RefuseManualStop", 0) || parse_systemd_bool(\%new_unit_info, "Unit", "X-OnlyManualStart", 0)) {
             $units_to_skip->{$unit} = 1;
         } else {
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/activation/test.nix b/nixos/modules/system/activation/test.nix
index 8cf000451c6e3..fd251d5289579 100644
--- a/nixos/modules/system/activation/test.nix
+++ b/nixos/modules/system/activation/test.nix
@@ -5,7 +5,7 @@
 }:
 let
   node-forbiddenDependencies-fail = nixos ({ ... }: {
-    system.forbiddenDependenciesRegex = "-dev$";
+    system.forbiddenDependenciesRegexes = ["-dev$"];
     environment.etc."dev-dependency" = {
       text = "${expect.dev}";
     };
@@ -14,7 +14,7 @@ let
     boot.loader.grub.enable = false;
   });
   node-forbiddenDependencies-succeed = nixos ({ ... }: {
-    system.forbiddenDependenciesRegex = "-dev$";
+    system.forbiddenDependenciesRegexes = ["-dev$"];
     system.extraDependencies = [ expect.dev ];
     documentation.enable = false;
     fileSystems."/".device = "ignore-root-device";
diff --git a/nixos/modules/system/activation/top-level.nix b/nixos/modules/system/activation/top-level.nix
index 4cf3012646fa3..ed0ece19f2fa2 100644
--- a/nixos/modules/system/activation/top-level.nix
+++ b/nixos/modules/system/activation/top-level.nix
@@ -86,6 +86,7 @@ in
     ../build.nix
     (mkRemovedOptionModule [ "nesting" "clone" ] "Use `specialisation.«name» = { inheritParentConfig = true; configuration = { ... }; }` instead.")
     (mkRemovedOptionModule [ "nesting" "children" ] "Use `specialisation.«name».configuration = { ... }` instead.")
+    (mkRenamedOptionModule [ "system" "forbiddenDependenciesRegex" ] [ "system" "forbiddenDependenciesRegexes" ])
   ];
 
   options = {
@@ -160,12 +161,12 @@ in
       '';
     };
 
-    system.forbiddenDependenciesRegex = mkOption {
-      default = "";
-      example = "-dev$";
-      type = types.str;
+    system.forbiddenDependenciesRegexes = mkOption {
+      default = [];
+      example = ["-dev$"];
+      type = types.listOf types.str;
       description = ''
-        A POSIX Extended Regular Expression that matches store paths that
+        POSIX Extended Regular Expressions that match store paths that
         should not appear in the system closure, with the exception of {option}`system.extraDependencies`, which is not checked.
       '';
     };
@@ -289,15 +290,14 @@ in
             "$out/configuration.nix"
         '' +
       optionalString
-        (config.system.forbiddenDependenciesRegex != "")
-        ''
-          if [[ $forbiddenDependenciesRegex != "" && -n $closureInfo ]]; then
-            if forbiddenPaths="$(grep -E -- "$forbiddenDependenciesRegex" $closureInfo/store-paths)"; then
+        (config.system.forbiddenDependenciesRegexes != []) (lib.concatStringsSep "\n" (map (regex: ''
+          if [[ ${regex} != "" && -n $closureInfo ]]; then
+            if forbiddenPaths="$(grep -E -- "${regex}" $closureInfo/store-paths)"; then
               echo -e "System closure $out contains the following disallowed paths:\n$forbiddenPaths"
               exit 1
             fi
           fi
-        '';
+        '') config.system.forbiddenDependenciesRegexes));
 
     system.systemBuilderArgs = {
 
@@ -319,8 +319,7 @@ in
       # option, as opposed to `system.extraDependencies`.
       passedChecks = concatStringsSep " " config.system.checks;
     }
-    // lib.optionalAttrs (config.system.forbiddenDependenciesRegex != "") {
-      inherit (config.system) forbiddenDependenciesRegex;
+    // lib.optionalAttrs (config.system.forbiddenDependenciesRegexes != []) {
       closureInfo = pkgs.closureInfo { rootPaths = [
         # override to avoid  infinite recursion (and to allow using extraDependencies to add forbidden dependencies)
         (config.system.build.toplevel.overrideAttrs (_: { extraDependencies = []; closureInfo = null; }))
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/initrd-ssh.nix b/nixos/modules/system/boot/initrd-ssh.nix
index 9ce5a85b4f073..d1cd601c2d9b1 100644
--- a/nixos/modules/system/boot/initrd-ssh.nix
+++ b/nixos/modules/system/boot/initrd-ssh.nix
@@ -82,7 +82,7 @@ in
       type = types.bool;
       default = false;
       description = ''
-        Allow leaving {option}`config.boot.initrd.network.ssh` empty,
+        Allow leaving {option}`config.boot.initrd.network.ssh.hostKeys` empty,
         to deploy ssh host keys out of band.
       '';
     };
diff --git a/nixos/modules/system/boot/loader/systemd-boot/systemd-boot-builder.py b/nixos/modules/system/boot/loader/systemd-boot/systemd-boot-builder.py
index 03bff1dee5b9d..694d34d1c059a 100644
--- a/nixos/modules/system/boot/loader/systemd-boot/systemd-boot-builder.py
+++ b/nixos/modules/system/boot/loader/systemd-boot/systemd-boot-builder.py
@@ -196,8 +196,7 @@ def get_generations(profile: str | None = None) -> list[SystemIdentifier]:
         f"{NIX}/bin/nix-env",
         "--list-generations",
         "-p",
-        "/nix/var/nix/profiles/%s" % ("system-profiles/" + profile if profile else "system"),
-        "--option", "build-users-group", ""],
+        "/nix/var/nix/profiles/%s" % ("system-profiles/" + profile if profile else "system")],
         universal_newlines=True)
     gen_lines = gen_list.split('\n')
     gen_lines.pop()
diff --git a/nixos/modules/system/boot/loader/systemd-boot/systemd-boot.nix b/nixos/modules/system/boot/loader/systemd-boot/systemd-boot.nix
index cee8663f0040e..e73048dc2ecbe 100644
--- a/nixos/modules/system/boot/loader/systemd-boot/systemd-boot.nix
+++ b/nixos/modules/system/boot/loader/systemd-boot/systemd-boot.nix
@@ -323,15 +323,15 @@ in {
     assertions = [
       {
         assertion = (hasPrefix "/" efi.efiSysMountPoint);
-        message = "The ESP mount point '${efi.efiSysMountPoint}' must be an absolute path";
+        message = "The ESP mount point '${toString efi.efiSysMountPoint}' must be an absolute path";
       }
       {
         assertion = cfg.xbootldrMountPoint == null || (hasPrefix "/" cfg.xbootldrMountPoint);
-        message = "The XBOOTLDR mount point '${cfg.xbootldrMountPoint}' must be an absolute path";
+        message = "The XBOOTLDR mount point '${toString cfg.xbootldrMountPoint}' must be an absolute path";
       }
       {
         assertion = cfg.xbootldrMountPoint != efi.efiSysMountPoint;
-        message = "The XBOOTLDR mount point '${cfg.xbootldrMountPoint}' cannot be the same as the ESP mount point '${efi.efiSysMountPoint}'";
+        message = "The XBOOTLDR mount point '${toString cfg.xbootldrMountPoint}' cannot be the same as the ESP mount point '${toString efi.efiSysMountPoint}'";
       }
       {
         assertion = (config.boot.kernelPackages.kernel.features or { efiBootStub = true; }) ? efiBootStub;
diff --git a/nixos/modules/system/boot/networkd.nix b/nixos/modules/system/boot/networkd.nix
index bb899c8d89994..761bbe6e03d4a 100644
--- a/nixos/modules/system/boot/networkd.nix
+++ b/nixos/modules/system/boot/networkd.nix
@@ -17,11 +17,13 @@ let
           "ManageForeignRoutingPolicyRules"
           "ManageForeignRoutes"
           "RouteTable"
+          "IPv6PrivacyExtensions"
         ])
         (assertValueOneOf "SpeedMeter" boolValues)
         (assertInt "SpeedMeterIntervalSec")
         (assertValueOneOf "ManageForeignRoutingPolicyRules" boolValues)
         (assertValueOneOf "ManageForeignRoutes" boolValues)
+        (assertValueOneOf "IPv6PrivacyExtensions" (boolValues ++ ["prefer-public" "kernel"]))
       ];
 
       sectionDHCPv4 = checkUnitConfig "DHCPv4" [
@@ -384,7 +386,7 @@ let
         (assertValueOneOf "UDP6ZeroChecksumRx" boolValues)
       ];
 
-      sectionL2TPSession = checkUnitConfig "L2TPSession" [
+      sectionL2TPSession = checkUnitConfigWithLegacyKey "l2tpSessionConfig" "L2TPSession" [
         (assertOnlyFields [
           "Name"
           "SessionId"
@@ -419,7 +421,7 @@ let
       # NOTE The PresharedKey directive is missing on purpose here, please
       # do not add it to this list. The nix store is world-readable,let's
       # refrain ourselves from providing a footgun.
-      sectionWireGuardPeer = checkUnitConfig "WireGuardPeer" [
+      sectionWireGuardPeer = checkUnitConfigWithLegacyKey "wireguardPeerConfig" "WireGuardPeer" [
         (assertOnlyFields [
           "PublicKey"
           "PresharedKeyFile"
@@ -710,7 +712,7 @@ let
         (assertValueOneOf "KeepConfiguration" (boolValues ++ ["static" "dhcp-on-stop" "dhcp"]))
       ];
 
-      sectionAddress = checkUnitConfig "Address" [
+      sectionAddress = checkUnitConfigWithLegacyKey "addressConfig" "Address" [
         (assertOnlyFields [
           "Address"
           "Peer"
@@ -735,7 +737,7 @@ let
         (assertValueOneOf "AutoJoin" boolValues)
       ];
 
-      sectionRoutingPolicyRule = checkUnitConfig "RoutingPolicyRule" [
+      sectionRoutingPolicyRule = checkUnitConfigWithLegacyKey "routingPolicyRuleConfig" "RoutingPolicyRule" [
         (assertOnlyFields [
           "TypeOfService"
           "From"
@@ -770,7 +772,7 @@ let
         (assertRange "SuppressInterfaceGroup" 0 2147483647)
       ];
 
-      sectionRoute = checkUnitConfig "Route" [
+      sectionRoute = checkUnitConfigWithLegacyKey "routeConfig" "Route" [
         (assertOnlyFields [
           "Gateway"
           "GatewayOnLink"
@@ -950,6 +952,7 @@ let
           "UseGateway"
           "UseRoutePrefix"
           "Token"
+          "UsePREF64"
         ])
         (assertValueOneOf "UseDNS" boolValues)
         (assertValueOneOf "UseDomains" (boolValues ++ ["route"]))
@@ -960,6 +963,7 @@ let
         (assertValueOneOf "UseMTU" boolValues)
         (assertValueOneOf "UseGateway" boolValues)
         (assertValueOneOf "UseRoutePrefix" boolValues)
+        (assertValueOneOf "UsePREF64" boolValues)
       ];
 
       sectionDHCPServer = checkUnitConfig "DHCPServer" [
@@ -1031,7 +1035,15 @@ let
         (assertValueOneOf "EmitDomains" boolValues)
       ];
 
-      sectionIPv6Prefix = checkUnitConfig "IPv6Prefix" [
+      sectionIPv6PREF64Prefix = checkUnitConfigWithLegacyKey "ipv6PREF64PrefixConfig" "IPv6PREF64Prefix" [
+        (assertOnlyFields [
+          "Prefix"
+          "LifetimeSec"
+        ])
+        (assertInt "LifetimeSec")
+      ];
+
+      sectionIPv6Prefix = checkUnitConfigWithLegacyKey "ipv6PrefixConfig" "IPv6Prefix" [
         (assertOnlyFields [
           "AddressAutoconfiguration"
           "OnLink"
@@ -1046,7 +1058,7 @@ let
         (assertValueOneOf "Assign" boolValues)
       ];
 
-      sectionIPv6RoutePrefix = checkUnitConfig "IPv6RoutePrefix" [
+      sectionIPv6RoutePrefix = checkUnitConfigWithLegacyKey "ipv6RoutePrefixConfig" "IPv6RoutePrefix" [
         (assertOnlyFields [
           "Route"
           "LifetimeSec"
@@ -1055,7 +1067,7 @@ let
         (assertInt "LifetimeSec")
       ];
 
-      sectionDHCPServerStaticLease = checkUnitConfig "DHCPServerStaticLease" [
+      sectionDHCPServerStaticLease = checkUnitConfigWithLegacyKey "dhcpServerStaticLeaseConfig" "DHCPServerStaticLease" [
         (assertOnlyFields [
           "MACAddress"
           "Address"
@@ -1102,7 +1114,7 @@ let
         (assertRange "Priority" 0 63)
       ];
 
-      sectionBridgeFDB = checkUnitConfig "BridgeFDB" [
+      sectionBridgeFDB = checkUnitConfigWithLegacyKey "bridgeFDBConfig" "BridgeFDB" [
         (assertOnlyFields [
           "MACAddress"
           "Destination"
@@ -1119,7 +1131,7 @@ let
         (assertValueOneOf "AssociatedWith" [ "use" "self" "master" "router" ])
       ];
 
-      sectionBridgeMDB = checkUnitConfig "BridgeMDB" [
+      sectionBridgeMDB = checkUnitConfigWithLegacyKey "bridgeMDBConfig" "BridgeMDB" [
         (assertOnlyFields [
           "MulticastGroupAddress"
           "VLANId"
@@ -1522,7 +1534,7 @@ let
         (assertRange "Weight" 1 1023)
       ];
 
-      sectionBridgeVLAN = checkUnitConfig "BridgeVLAN" [
+      sectionBridgeVLAN = checkUnitConfigWithLegacyKey "bridgeVLANConfig" "BridgeVLAN" [
         (assertOnlyFields [
           "VLAN"
           "EgressUntagged"
@@ -1625,34 +1637,21 @@ let
 
   };
 
-
-  l2tpSessionOptions = {
-    options = {
-      l2tpSessionConfig = mkOption {
-        default = {};
-        type = types.addCheck (types.attrsOf unitOption) check.netdev.sectionL2TPSession;
-        description = ''
-          Each attribute in this set specifies an option in the
-          `[L2TPSession]` section of the unit.  See
-          {manpage}`systemd.netdev(5)` for details.
-        '';
-      };
-    };
-  };
-
-  wireguardPeerOptions = {
-    options = {
-      wireguardPeerConfig = mkOption {
-        default = {};
-        type = types.addCheck (types.attrsOf unitOption) check.netdev.sectionWireGuardPeer;
-        description = ''
-          Each attribute in this set specifies an option in the
-          `[WireGuardPeer]` section of the unit.  See
-          {manpage}`systemd.netdev(5)` for details.
-        '';
-      };
+  mkSubsectionType = oldKey: checkF:
+    let
+      type = types.addCheck (types.attrsOf unitOption) checkF;
+    in type // {
+      merge = loc: defs:
+        let
+          final = type.merge loc defs;
+        in
+        if final?${oldKey}
+          then warn
+            "Using '${oldKey}' is deprecated! Move all attributes inside one level up and remove it."
+            final.${oldKey}
+        else
+          final;
     };
-  };
 
   netdevOptions = commonNetworkOptions // {
 
@@ -1803,12 +1802,12 @@ let
 
     l2tpSessions = mkOption {
       default = [];
-      example = [ { l2tpSessionConfig={
+      example = [ {
         SessionId = 25;
         PeerSessionId = 26;
         Name = "l2tp-sess";
-      };}];
-      type = with types; listOf (submodule l2tpSessionOptions);
+      }];
+      type = types.listOf (mkSubsectionType "l2tpSessionConfig" check.netdev.sectionL2TPSession);
       description = ''
         Each item in this array specifies an option in the
         `[L2TPSession]` section of the unit. See
@@ -1836,14 +1835,14 @@ let
 
     wireguardPeers = mkOption {
       default = [];
-      example = [ { wireguardPeerConfig={
+      example = [ {
         Endpoint = "192.168.1.1:51820";
         PublicKey = "27s0OvaBBdHoJYkH9osZpjpgSOVNw+RaKfboT/Sfq0g=";
         PresharedKeyFile = "/etc/wireguard/psk.key";
         AllowedIPs = [ "10.0.0.1/32" ];
         PersistentKeepalive = 15;
-      };}];
-      type = with types; listOf (submodule wireguardPeerOptions);
+      } ];
+      type = types.listOf (mkSubsectionType "wireguardPeerConfig" check.netdev.sectionWireGuardPeer);
       description = ''
         Each item in this array specifies an option in the
         `[WireGuardPeer]` section of the unit. See
@@ -1915,143 +1914,6 @@ let
 
   };
 
-  addressOptions = {
-    options = {
-      addressConfig = mkOption {
-        example = { Address = "192.168.0.100/24"; };
-        type = types.addCheck (types.attrsOf unitOption) check.network.sectionAddress;
-        description = ''
-          Each attribute in this set specifies an option in the
-          `[Address]` section of the unit.  See
-          {manpage}`systemd.network(5)` for details.
-        '';
-      };
-    };
-  };
-
-  routingPolicyRulesOptions = {
-    options = {
-      routingPolicyRuleConfig = mkOption {
-        default = { };
-        example = { Table = 10; IncomingInterface = "eth1"; Family = "both"; };
-        type = types.addCheck (types.attrsOf unitOption) check.network.sectionRoutingPolicyRule;
-        description = ''
-          Each attribute in this set specifies an option in the
-          `[RoutingPolicyRule]` section of the unit.  See
-          {manpage}`systemd.network(5)` for details.
-        '';
-      };
-    };
-  };
-
-  routeOptions = {
-    options = {
-      routeConfig = mkOption {
-        default = {};
-        example = { Gateway = "192.168.0.1"; };
-        type = types.addCheck (types.attrsOf unitOption) check.network.sectionRoute;
-        description = ''
-          Each attribute in this set specifies an option in the
-          `[Route]` section of the unit.  See
-          {manpage}`systemd.network(5)` for details.
-        '';
-      };
-    };
-  };
-
-  ipv6PrefixOptions = {
-    options = {
-      ipv6PrefixConfig = mkOption {
-        default = {};
-        example = { Prefix = "fd00::/64"; };
-        type = types.addCheck (types.attrsOf unitOption) check.network.sectionIPv6Prefix;
-        description = ''
-          Each attribute in this set specifies an option in the
-          `[IPv6Prefix]` section of the unit.  See
-          {manpage}`systemd.network(5)` for details.
-        '';
-      };
-    };
-  };
-
-  ipv6RoutePrefixOptions = {
-    options = {
-      ipv6RoutePrefixConfig = mkOption {
-        default = {};
-        example = { Route = "fd00::/64"; };
-        type = types.addCheck (types.attrsOf unitOption) check.network.sectionIPv6RoutePrefix;
-        description = ''
-          Each attribute in this set specifies an option in the
-          `[IPv6RoutePrefix]` section of the unit.  See
-          {manpage}`systemd.network(5)` for details.
-        '';
-      };
-    };
-  };
-
-  dhcpServerStaticLeaseOptions = {
-    options = {
-      dhcpServerStaticLeaseConfig = mkOption {
-        default = {};
-        example = { MACAddress = "65:43:4a:5b:d8:5f"; Address = "192.168.1.42"; };
-        type = types.addCheck (types.attrsOf unitOption) check.network.sectionDHCPServerStaticLease;
-        description = ''
-          Each attribute in this set specifies an option in the
-          `[DHCPServerStaticLease]` section of the unit.  See
-          {manpage}`systemd.network(5)` for details.
-
-          Make sure to configure the corresponding client interface to use
-          `ClientIdentifier=mac`.
-        '';
-      };
-    };
-  };
-
-  bridgeFDBOptions = {
-    options = {
-      bridgeFDBConfig = mkOption {
-        default = {};
-        example = { MACAddress = "65:43:4a:5b:d8:5f"; Destination = "192.168.1.42"; VNI = 20; };
-        type = types.addCheck (types.attrsOf unitOption) check.network.sectionBridgeFDB;
-        description = ''
-          Each attribute in this set specifies an option in the
-          `[BridgeFDB]` section of the unit.  See
-          {manpage}`systemd.network(5)` for details.
-        '';
-      };
-    };
-  };
-
-  bridgeMDBOptions = {
-    options = {
-      bridgeMDBConfig = mkOption {
-        default = {};
-        example = { MulticastGroupAddress = "ff02::1:2:3:4"; VLANId = 10; };
-        type = types.addCheck (types.attrsOf unitOption) check.network.sectionBridgeMDB;
-        description = ''
-          Each attribute in this set specifies an option in the
-          `[BridgeMDB]` section of the unit.  See
-          {manpage}`systemd.network(5)` for details.
-        '';
-      };
-    };
-  };
-
-  bridgeVLANOptions = {
-    options = {
-      bridgeVLANConfig = mkOption {
-        default = {};
-        example = { VLAN = 20; };
-        type = types.addCheck (types.attrsOf unitOption) check.network.sectionBridgeVLAN;
-        description = ''
-          Each attribute in this set specifies an option in the
-          `[BridgeVLAN]` section of the unit.  See
-          {manpage}`systemd.network(5)` for details.
-        '';
-      };
-    };
-  };
-
   networkOptions = commonNetworkOptions // {
 
     linkConfig = mkOption {
@@ -2161,10 +2023,20 @@ let
       '';
     };
 
+    ipv6PREF64Prefixes = mkOption {
+      default = [];
+      example = [ { Prefix = "64:ff9b::/96"; } ];
+      type = types.listOf (mkSubsectionType "ipv6PREF64PrefixConfig" check.network.sectionIPv6PREF64Prefix);
+      description = ''
+        A list of IPv6PREF64Prefix sections to be added to the unit. See
+        {manpage}`systemd.network(5)` for details.
+      '';
+    };
+
     dhcpServerStaticLeases = mkOption {
       default = [];
-      example = [ { dhcpServerStaticLeaseConfig = { MACAddress = "65:43:4a:5b:d8:5f"; Address = "192.168.1.42"; }; } ];
-      type = with types; listOf (submodule dhcpServerStaticLeaseOptions);
+      example = [ { MACAddress = "65:43:4a:5b:d8:5f"; Address = "192.168.1.42"; } ];
+      type = types.listOf (mkSubsectionType "dhcpServerStaticLeaseConfig" check.network.sectionDHCPServerStaticLease);
       description = ''
         A list of DHCPServerStaticLease sections to be added to the unit.  See
         {manpage}`systemd.network(5)` for details.
@@ -2173,8 +2045,8 @@ let
 
     ipv6Prefixes = mkOption {
       default = [];
-      example = [ { ipv6PrefixConfig = { AddressAutoconfiguration = true; OnLink = true; }; } ];
-      type = with types; listOf (submodule ipv6PrefixOptions);
+      example = [ { AddressAutoconfiguration = true; OnLink = true; } ];
+      type = types.listOf (mkSubsectionType "ipv6PrefixConfig" check.network.sectionIPv6Prefix);
       description = ''
         A list of ipv6Prefix sections to be added to the unit.  See
         {manpage}`systemd.network(5)` for details.
@@ -2183,8 +2055,8 @@ let
 
     ipv6RoutePrefixes = mkOption {
       default = [];
-      example = [ { ipv6RoutePrefixConfig = { Route = "fd00::/64"; LifetimeSec = 3600; }; } ];
-      type = with types; listOf (submodule ipv6RoutePrefixOptions);
+      example = [ { Route = "fd00::/64"; LifetimeSec = 3600; } ];
+      type = types.listOf (mkSubsectionType "ipv6RoutePrefixConfig" check.network.sectionIPv6RoutePrefix);
       description = ''
         A list of ipv6RoutePrefix sections to be added to the unit.  See
         {manpage}`systemd.network(5)` for details.
@@ -2204,8 +2076,8 @@ let
 
     bridgeFDBs = mkOption {
       default = [];
-      example = [ { bridgeFDBConfig = { MACAddress = "90:e2:ba:43:fc:71"; Destination = "192.168.100.4"; VNI = 3600; }; } ];
-      type = with types; listOf (submodule bridgeFDBOptions);
+      example = [ { MACAddress = "90:e2:ba:43:fc:71"; Destination = "192.168.100.4"; VNI = 3600; } ];
+      type = types.listOf (mkSubsectionType "bridgeFDBConfig" check.network.sectionBridgeFDB);
       description = ''
         A list of BridgeFDB sections to be added to the unit.  See
         {manpage}`systemd.network(5)` for details.
@@ -2214,8 +2086,8 @@ let
 
     bridgeMDBs = mkOption {
       default = [];
-      example = [ { bridgeMDBConfig = { MulticastGroupAddress = "ff02::1:2:3:4"; VLANId = 10; } ; } ];
-      type = with types; listOf (submodule bridgeMDBOptions);
+      example = [ { MulticastGroupAddress = "ff02::1:2:3:4"; VLANId = 10; } ];
+      type = types.listOf (mkSubsectionType "bridgeMDBConfig" check.network.sectionBridgeMDB);
       description = ''
         A list of BridgeMDB sections to be added to the unit.  See
         {manpage}`systemd.network(5)` for details.
@@ -2532,8 +2404,8 @@ let
 
     bridgeVLANs = mkOption {
       default = [];
-      example = [ { bridgeVLANConfig = { VLAN = "10-20"; }; } ];
-      type = with types; listOf (submodule bridgeVLANOptions);
+      example = [ { VLAN = "10-20"; } ];
+      type = types.listOf (mkSubsectionType "bridgeVLANConfig" check.network.sectionBridgeVLAN);
       description = ''
         A list of BridgeVLAN sections to be added to the unit.  See
         {manpage}`systemd.network(5)` for details.
@@ -2683,7 +2555,8 @@ let
 
     addresses = mkOption {
       default = [ ];
-      type = with types; listOf (submodule addressOptions);
+      example = [ { Address = "192.168.0.100/24"; } ];
+      type = types.listOf (mkSubsectionType "addressConfig" check.network.sectionAddress);
       description = ''
         A list of address sections to be added to the unit.  See
         {manpage}`systemd.network(5)` for details.
@@ -2692,7 +2565,8 @@ let
 
     routingPolicyRules = mkOption {
       default = [ ];
-      type = with types; listOf (submodule routingPolicyRulesOptions);
+      example = [ { Table = 10; IncomingInterface = "eth1"; Family = "both"; } ];
+      type = types.listOf (mkSubsectionType "routingPolicyRuleConfig" check.network.sectionRoutingPolicyRule);
       description = ''
         A list of routing policy rules sections to be added to the unit.  See
         {manpage}`systemd.network(5)` for details.
@@ -2701,7 +2575,8 @@ let
 
     routes = mkOption {
       default = [ ];
-      type = with types; listOf (submodule routeOptions);
+      example = [ { Gateway = "192.168.0.1"; } ];
+      type = types.listOf (mkSubsectionType "routeConfig" check.network.sectionRoute);
       description = ''
         A list of route sections to be added to the unit.  See
         {manpage}`systemd.network(5)` for details.
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/stage-1-init.sh b/nixos/modules/system/boot/stage-1-init.sh
index 59cf1a47fb7f9..23e9df2189e78 100644
--- a/nixos/modules/system/boot/stage-1-init.sh
+++ b/nixos/modules/system/boot/stage-1-init.sh
@@ -576,6 +576,7 @@ while read -u 3 mountPoint; do
       mount -t "$fsType" /dev/root /tmp-iso
       mountFS tmpfs /iso size="$fsSize" tmpfs
 
+      echo "copying ISO contents to RAM..."
       cp -r /tmp-iso/* /mnt-root/iso/
 
       umount /tmp-iso
diff --git a/nixos/modules/system/boot/systemd.nix b/nixos/modules/system/boot/systemd.nix
index c82924763d5e8..14a4ab596b52c 100644
--- a/nixos/modules/system/boot/systemd.nix
+++ b/nixos/modules/system/boot/systemd.nix
@@ -503,8 +503,8 @@ in
     environment.systemPackages = [ cfg.package ];
 
     environment.etc = let
-      # generate contents for /etc/systemd/system-${type} from attrset of links and packages
-      hooks = type: links: pkgs.runCommand "system-${type}" {
+      # generate contents for /etc/systemd/${dir} from attrset of links and packages
+      hooks = dir: links: pkgs.runCommand "${dir}" {
           preferLocalBuild = true;
           packages = cfg.packages;
       } ''
@@ -512,7 +512,7 @@ in
         mkdir -p $out
         for package in $packages
         do
-          for hook in $package/lib/systemd/system-${type}/*
+          for hook in $package/lib/systemd/${dir}/*
           do
             ln -s $hook $out/
           done
@@ -562,8 +562,9 @@ in
         ${cfg.sleep.extraConfig}
       '';
 
-      "systemd/system-generators" = { source = hooks "generators" cfg.generators; };
-      "systemd/system-shutdown" = { source = hooks "shutdown" cfg.shutdown; };
+      "systemd/user-generators" = { source = hooks "user-generators" cfg.user.generators; };
+      "systemd/system-generators" = { source = hooks "system-generators" cfg.generators; };
+      "systemd/system-shutdown" = { source = hooks "system-shutdown" cfg.shutdown; };
     });
 
     services.dbus.enable = true;
diff --git a/nixos/modules/system/boot/systemd/coredump.nix b/nixos/modules/system/boot/systemd/coredump.nix
index 1f29f6686d0d0..ccf5d449b94a3 100644
--- a/nixos/modules/system/boot/systemd/coredump.nix
+++ b/nixos/modules/system/boot/systemd/coredump.nix
@@ -53,7 +53,7 @@ in {
           pkgs.substitute {
             src = "${systemd}/example/sysctl.d/50-coredump.conf";
             substitutions = [
-              "--replace"
+              "--replace-fail"
               "${systemd}"
               "${pkgs.symlinkJoin { name = "systemd"; paths = [ systemd ]; }}"
             ];
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/system/boot/systemd/sysusers.nix b/nixos/modules/system/boot/systemd/sysusers.nix
index de70009705973..476251e140456 100644
--- a/nixos/modules/system/boot/systemd/sysusers.nix
+++ b/nixos/modules/system/boot/systemd/sysusers.nix
@@ -12,7 +12,7 @@ let
     ${lib.concatLines (lib.mapAttrsToList
       (username: opts:
         let
-          uid = if opts.uid == null then "-" else toString opts.uid;
+          uid = if opts.uid == null then "/var/lib/nixos/uid/${username}" else toString opts.uid;
         in
           ''u ${username} ${uid}:${opts.group} "${opts.description}" ${opts.home} ${utils.toShellPath opts.shell}''
       )
@@ -21,7 +21,7 @@ let
 
     # Groups
     ${lib.concatLines (lib.mapAttrsToList
-      (groupname: opts: ''g ${groupname} ${if opts.gid == null then "-" else toString opts.gid}'') userCfg.groups)
+      (groupname: opts: ''g ${groupname} ${if opts.gid == null then "/var/lib/nixos/gid/${groupname}" else toString opts.gid}'') userCfg.groups)
     }
 
     # Group membership
@@ -106,6 +106,23 @@ in
             };
           })
           (lib.filterAttrs (_username: opts: opts.home != "/var/empty") userCfg.users);
+
+        # Create uid/gid marker files for those without an explicit id
+        tmpfiles.settings.nixos-uid = lib.mapAttrs'
+          (username: opts: lib.nameValuePair "/var/lib/nixos/uid/${username}" {
+            f = {
+              user = username;
+            };
+          })
+          (lib.filterAttrs (_username: opts: opts.uid == null) userCfg.users);
+
+        tmpfiles.settings.nixos-gid = lib.mapAttrs'
+          (groupname: opts: lib.nameValuePair "/var/lib/nixos/gid/${groupname}" {
+            f = {
+              group = groupname;
+            };
+          })
+          (lib.filterAttrs (_groupname: opts: opts.gid == null) userCfg.groups);
       })
 
       (lib.mkIf config.users.mutableUsers {
diff --git a/nixos/modules/system/boot/systemd/user.nix b/nixos/modules/system/boot/systemd/user.nix
index 2685cf7e283a2..53fca631678c1 100644
--- a/nixos/modules/system/boot/systemd/user.nix
+++ b/nixos/modules/system/boot/systemd/user.nix
@@ -144,6 +144,18 @@ in {
       };
     };
 
+    systemd.user.generators = mkOption {
+      type = types.attrsOf types.path;
+      default = {};
+      example = { systemd-gpt-auto-generator = "/dev/null"; };
+      description = ''
+        Definition of systemd generators; see {manpage}`systemd.generator(5)`.
+
+        For each `NAME = VALUE` pair of the attrSet, a link is generated from
+        `/etc/systemd/user-generators/NAME` to `VALUE`.
+      '';
+    };
+
     systemd.additionalUpstreamUserUnits = mkOption {
       default = [];
       type = types.listOf types.str;
diff --git a/nixos/modules/system/etc/build-composefs-dump.py b/nixos/modules/system/etc/build-composefs-dump.py
index bba454dd888d6..fe739a621ec4d 100644
--- a/nixos/modules/system/etc/build-composefs-dump.py
+++ b/nixos/modules/system/etc/build-composefs-dump.py
@@ -175,7 +175,7 @@ def main() -> None:
                 paths[glob_target] = composefs_path
                 add_leading_directories(glob_target, attrs, paths)
         else:  # Without globbing
-            if mode == "symlink":
+            if mode == "symlink" or mode == "direct-symlink":
                 composefs_path = ComposefsPath(
                     attrs,
                     # A high approximation of the size of a symlink
@@ -184,24 +184,23 @@ def main() -> None:
                     mode="0777",
                     payload=source,
                 )
+            elif os.path.isdir(source):
+                composefs_path = ComposefsPath(
+                    attrs,
+                    size=4096,
+                    filetype=FileType.directory,
+                    mode=mode,
+                    payload=source,
+                )
             else:
-                if os.path.isdir(source):
-                    composefs_path = ComposefsPath(
-                        attrs,
-                        size=4096,
-                        filetype=FileType.directory,
-                        mode=mode,
-                        payload=source,
-                    )
-                else:
-                    composefs_path = ComposefsPath(
-                        attrs,
-                        size=os.stat(source).st_size,
-                        filetype=FileType.file,
-                        mode=mode,
-                        # payload needs to be relative path in this case
-                        payload=target.lstrip("/"),
-                    )
+                composefs_path = ComposefsPath(
+                    attrs,
+                    size=os.stat(source).st_size,
+                    filetype=FileType.file,
+                    mode=mode,
+                    # payload needs to be relative path in this case
+                    payload=target.lstrip("/"),
+                )
             paths[target] = composefs_path
             add_leading_directories(target, attrs, paths)
 
diff --git a/nixos/modules/system/etc/etc.nix b/nixos/modules/system/etc/etc.nix
index 9fded1e1c9742..80ca69e495e9d 100644
--- a/nixos/modules/system/etc/etc.nix
+++ b/nixos/modules/system/etc/etc.nix
@@ -62,7 +62,7 @@ let
     ]) etc'}
   '';
 
-  etcHardlinks = filter (f: f.mode != "symlink") etc';
+  etcHardlinks = filter (f: f.mode != "symlink" && f.mode != "direct-symlink") etc';
 
   build-composefs-dump = pkgs.runCommand "build-composefs-dump.py"
     {
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/tasks/network-interfaces-scripted.nix b/nixos/modules/tasks/network-interfaces-scripted.nix
index 2f2d282fbefb4..bbf2d337aac64 100644
--- a/nixos/modules/tasks/network-interfaces-scripted.nix
+++ b/nixos/modules/tasks/network-interfaces-scripted.nix
@@ -203,10 +203,10 @@ let
                   ''
                     echo "${cidr}" >> $state
                     echo -n "adding address ${cidr}... "
-                    if out=$(ip addr add "${cidr}" dev "${i.name}" 2>&1); then
+                    if out=$(ip addr replace "${cidr}" dev "${i.name}" 2>&1); then
                       echo "done"
-                    elif ! echo "$out" | grep "File exists" >/dev/null 2>&1; then
-                      echo "'ip addr add "${cidr}" dev "${i.name}"' failed: $out"
+                    else
+                      echo "'ip addr replace "${cidr}" dev "${i.name}"' failed: $out"
                       exit 1
                     fi
                   ''
diff --git a/nixos/modules/tasks/network-interfaces-systemd.nix b/nixos/modules/tasks/network-interfaces-systemd.nix
index 2009c9a7e6e28..c1241d11de879 100644
--- a/nixos/modules/tasks/network-interfaces-systemd.nix
+++ b/nixos/modules/tasks/network-interfaces-systemd.nix
@@ -32,13 +32,13 @@ let
     optionalAttrs (gateway != null && gateway.interface != null) {
       networks."40-${gateway.interface}" = {
         matchConfig.Name = gateway.interface;
-        routes = [{
-          routeConfig = {
+        routes = [
+          ({
             Gateway = gateway.address;
           } // optionalAttrs (gateway.metric != null) {
             Metric = gateway.metric;
-          };
-        }];
+          })
+        ];
       };
     }
   ));
@@ -95,65 +95,64 @@ let
       address = forEach (interfaceIps i)
         (ip: "${ip.address}/${toString ip.prefixLength}");
       routes = forEach (interfaceRoutes i)
-        (route: {
+        (route: mkMerge [
           # Most of these route options have not been tested.
           # Please fix or report any mistakes you may find.
-          routeConfig =
-            optionalAttrs (route.address != null && route.prefixLength != null) {
-              Destination = "${route.address}/${toString route.prefixLength}";
-            } //
-            optionalAttrs (route.options ? fastopen_no_cookie) {
-              FastOpenNoCookie = route.options.fastopen_no_cookie;
-            } //
-            optionalAttrs (route.via != null) {
-              Gateway = route.via;
-            } //
-            optionalAttrs (route.type != null) {
-              Type = route.type;
-            } //
-            optionalAttrs (route.options ? onlink) {
-              GatewayOnLink = true;
-            } //
-            optionalAttrs (route.options ? initrwnd) {
-              InitialAdvertisedReceiveWindow = route.options.initrwnd;
-            } //
-            optionalAttrs (route.options ? initcwnd) {
-              InitialCongestionWindow = route.options.initcwnd;
-            } //
-            optionalAttrs (route.options ? pref) {
-              IPv6Preference = route.options.pref;
-            } //
-            optionalAttrs (route.options ? mtu) {
-              MTUBytes = route.options.mtu;
-            } //
-            optionalAttrs (route.options ? metric) {
-              Metric = route.options.metric;
-            } //
-            optionalAttrs (route.options ? src) {
-              PreferredSource = route.options.src;
-            } //
-            optionalAttrs (route.options ? protocol) {
-              Protocol = route.options.protocol;
-            } //
-            optionalAttrs (route.options ? quickack) {
-              QuickAck = route.options.quickack;
-            } //
-            optionalAttrs (route.options ? scope) {
-              Scope = route.options.scope;
-            } //
-            optionalAttrs (route.options ? from) {
-              Source = route.options.from;
-            } //
-            optionalAttrs (route.options ? table) {
-              Table = route.options.table;
-            } //
-            optionalAttrs (route.options ? advmss) {
-              TCPAdvertisedMaximumSegmentSize = route.options.advmss;
-            } //
-            optionalAttrs (route.options ? ttl-propagate) {
-              TTLPropagate = route.options.ttl-propagate == "enabled";
-            };
-        });
+          (mkIf (route.address != null && route.prefixLength != null) {
+            Destination = "${route.address}/${toString route.prefixLength}";
+          })
+          (mkIf (route.options ? fastopen_no_cookie) {
+            FastOpenNoCookie = route.options.fastopen_no_cookie;
+          })
+          (mkIf (route.via != null) {
+            Gateway = route.via;
+          })
+          (mkIf (route.type != null) {
+            Type = route.type;
+          })
+          (mkIf (route.options ? onlink) {
+            GatewayOnLink = true;
+          })
+          (mkIf (route.options ? initrwnd) {
+            InitialAdvertisedReceiveWindow = route.options.initrwnd;
+          })
+          (mkIf (route.options ? initcwnd) {
+            InitialCongestionWindow = route.options.initcwnd;
+          })
+          (mkIf (route.options ? pref) {
+            IPv6Preference = route.options.pref;
+          })
+          (mkIf (route.options ? mtu) {
+            MTUBytes = route.options.mtu;
+          })
+          (mkIf (route.options ? metric) {
+            Metric = route.options.metric;
+          })
+          (mkIf (route.options ? src) {
+            PreferredSource = route.options.src;
+          })
+          (mkIf (route.options ? protocol) {
+            Protocol = route.options.protocol;
+          })
+          (mkIf (route.options ? quickack) {
+            QuickAck = route.options.quickack;
+          })
+          (mkIf (route.options ? scope) {
+            Scope = route.options.scope;
+          })
+          (mkIf (route.options ? from) {
+            Source = route.options.from;
+          })
+          (mkIf (route.options ? table) {
+            Table = route.options.table;
+          })
+          (mkIf (route.options ? advmss) {
+            TCPAdvertisedMaximumSegmentSize = route.options.advmss;
+          })
+          (mkIf (route.options ? ttl-propagate) {
+            TTLPropagate = route.options.ttl-propagate == "enabled";
+          })
+        ]);
       networkConfig.IPv6PrivacyExtensions = "kernel";
       linkConfig = optionalAttrs (i.macAddress != null) {
         MACAddress = i.macAddress;
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/containerd.nix b/nixos/modules/virtualisation/containerd.nix
index ea89a994b172a..73fb9f3b55d2f 100644
--- a/nixos/modules/virtualisation/containerd.nix
+++ b/nixos/modules/virtualisation/containerd.nix
@@ -84,7 +84,6 @@ in
         # "limits" defined below are adopted from upstream: https://github.com/containerd/containerd/blob/master/containerd.service
         LimitNPROC = "infinity";
         LimitCORE = "infinity";
-        LimitNOFILE = "infinity";
         TasksMax = "infinity";
         OOMScoreAdjust = "-999";
 
diff --git a/nixos/modules/virtualisation/containers.nix b/nixos/modules/virtualisation/containers.nix
index 65620dd3935b8..c3639f660dfe3 100644
--- a/nixos/modules/virtualisation/containers.nix
+++ b/nixos/modules/virtualisation/containers.nix
@@ -53,13 +53,6 @@ in
 
     storage.settings = mkOption {
       type = toml.type;
-      default = {
-        storage = {
-          driver = "overlay";
-          graphroot = "/var/lib/containers/storage";
-          runroot = "/run/containers/storage";
-        };
-      };
       description = "storage.conf configuration";
     };
 
@@ -124,6 +117,12 @@ in
       };
     };
 
+    virtualisation.containers.storage.settings.storage = {
+      driver = lib.mkDefault "overlay";
+      graphroot = lib.mkDefault "/var/lib/containers/storage";
+      runroot = lib.mkDefault "/run/containers/storage";
+    };
+
     environment.etc = {
       "containers/containers.conf".source =
         toml.generate "containers.conf" cfg.containersConf.settings;
diff --git a/nixos/modules/virtualisation/docker.nix b/nixos/modules/virtualisation/docker.nix
index bcc649dcbec0a..8a0894ed85c3d 100644
--- a/nixos/modules/virtualisation/docker.nix
+++ b/nixos/modules/virtualisation/docker.nix
@@ -244,8 +244,8 @@ in
       };
 
       assertions = [
-        { assertion = cfg.enableNvidia && pkgs.stdenv.isx86_64 -> config.hardware.opengl.driSupport32Bit or false;
-          message = "Option enableNvidia on x86_64 requires 32bit support libraries";
+        { assertion = cfg.enableNvidia && pkgs.stdenv.isx86_64 -> config.hardware.graphics.enable32Bit or false;
+          message = "Option enableNvidia on x86_64 requires 32-bit support libraries";
         }];
 
       virtualisation.docker.daemon.settings = {
diff --git a/nixos/modules/virtualisation/incus.nix b/nixos/modules/virtualisation/incus.nix
index 4d04853d20a56..87568390bd3b8 100644
--- a/nixos/modules/virtualisation/incus.nix
+++ b/nixos/modules/virtualisation/incus.nix
@@ -105,6 +105,37 @@ let
       path = "${pkgs.OVMFFull.fd}/FV/${ovmf-prefix}_VARS.fd";
     }
   ];
+
+  environment = lib.mkMerge [
+    {
+      INCUS_LXC_TEMPLATE_CONFIG = "${pkgs.lxcfs}/share/lxc/config";
+      INCUS_OVMF_PATH = ovmf;
+      INCUS_USBIDS_PATH = "${pkgs.hwdata}/share/hwdata/usb.ids";
+      PATH = lib.mkForce serverBinPath;
+    }
+    (lib.mkIf (cfg.ui.enable) { "INCUS_UI" = cfg.ui.package; })
+  ];
+
+  incus-startup = pkgs.writeShellScript "incus-startup" ''
+    case "$1" in
+        start)
+          systemctl is-active incus.service -q && exit 0
+          exec incusd activateifneeded
+        ;;
+
+        stop)
+          systemctl is-active incus.service -q || exit 0
+          exec incusd shutdown
+        ;;
+
+        *)
+          echo "unknown argument \`$1'" >&2
+          exit 1
+        ;;
+    esac
+
+    exit 0
+  '';
 in
 {
   meta = {
@@ -137,6 +168,14 @@ in
         description = "The incus client package to use. This package is added to PATH.";
       };
 
+      softDaemonRestart = lib.mkOption {
+        type = lib.types.bool;
+        default = true;
+        description = ''
+          Allow for incus.service to be stopped without affecting running instances.
+        '';
+      };
+
       preseed = lib.mkOption {
         type = lib.types.nullOr (lib.types.submodule { freeformType = preseedFormat.type; });
 
@@ -282,6 +321,8 @@ in
     systemd.services.incus = {
       description = "Incus Container and Virtual Machine Management Daemon";
 
+      inherit environment;
+
       wantedBy = lib.mkIf (!cfg.socketActivation) [ "multi-user.target" ];
       after = [
         "network-online.target"
@@ -296,20 +337,10 @@ in
 
       wants = [ "network-online.target" ];
 
-      environment = lib.mkMerge [
-        {
-          INCUS_LXC_TEMPLATE_CONFIG = "${pkgs.lxcfs}/share/lxc/config";
-          INCUS_OVMF_PATH = ovmf;
-          INCUS_USBIDS_PATH = "${pkgs.hwdata}/share/hwdata/usb.ids";
-          PATH = lib.mkForce serverBinPath;
-        }
-        (lib.mkIf (cfg.ui.enable) { "INCUS_UI" = cfg.ui.package; })
-      ];
-
       serviceConfig = {
         ExecStart = "${cfg.package}/bin/incusd --group incus-admin";
         ExecStartPost = "${cfg.package}/bin/incusd waitready --timeout=${cfg.startTimeout}";
-        ExecStop = "${cfg.package}/bin/incus admin shutdown";
+        ExecStop = lib.optionalString (!cfg.softDaemonRestart) "${cfg.package}/bin/incus admin shutdown";
 
         KillMode = "process"; # when stopping, leave the containers alone
         Delegate = "yes";
@@ -324,6 +355,27 @@ in
       };
     };
 
+    systemd.services.incus-startup = lib.mkIf cfg.softDaemonRestart {
+      description = "Incus Instances Startup/Shutdown";
+
+      inherit environment;
+
+      after = [
+        "incus.service"
+        "incus.socket"
+      ];
+      requires = [ "incus.socket" ];
+
+      serviceConfig = {
+        ExecStart = "${incus-startup} start";
+        ExecStop = "${incus-startup} stop";
+        RemainAfterExit = true;
+        TimeoutStartSec = "600s";
+        TimeoutStopSec = "600s";
+        Type = "oneshot";
+      };
+    };
+
     systemd.sockets.incus = {
       description = "Incus UNIX socket";
       wantedBy = [ "sockets.target" ];
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/lxd-agent.nix b/nixos/modules/virtualisation/lxd-agent.nix
index 8d536e18a34e4..d319371478481 100644
--- a/nixos/modules/virtualisation/lxd-agent.nix
+++ b/nixos/modules/virtualisation/lxd-agent.nix
@@ -50,7 +50,7 @@ in {
   };
 
   options = {
-    virtualisation.lxd.agent.enable = lib.mkEnableOption "Enable LXD agent";
+    virtualisation.lxd.agent.enable = lib.mkEnableOption "LXD agent";
   };
 
   config = lib.mkIf cfg.enable {
diff --git a/nixos/modules/virtualisation/oci-containers.nix b/nixos/modules/virtualisation/oci-containers.nix
index 4308d410c69c7..f4fa934231798 100644
--- a/nixos/modules/virtualisation/oci-containers.nix
+++ b/nixos/modules/virtualisation/oci-containers.nix
@@ -221,6 +221,13 @@ let
           example = "hello-world";
         };
 
+        preRunExtraOptions = mkOption {
+          type = with types; listOf str;
+          default = [];
+          description = "Extra options for {command}`${defaultBackend}` that go before the `run` argument.";
+          example = [ "--runtime" "runsc" ];
+        };
+
         extraOptions = mkOption {
           type = with types; listOf str;
           default = [];
@@ -284,7 +291,9 @@ let
       else throw "Unhandled backend: ${cfg.backend}";
 
     script = concatStringsSep " \\\n  " ([
-      "exec ${cfg.backend} run"
+      "exec ${cfg.backend} "
+    ]  ++ map escapeShellArg container.preRunExtraOptions ++ [
+      "run"
       "--rm"
       "--name=${escapedName}"
       "--log-driver=${container.log-driver}"
diff --git a/nixos/modules/virtualisation/oci-image.nix b/nixos/modules/virtualisation/oci-image.nix
index d4af5016dd71c..1e2b90bfd46e2 100644
--- a/nixos/modules/virtualisation/oci-image.nix
+++ b/nixos/modules/virtualisation/oci-image.nix
@@ -9,10 +9,10 @@ in
   config = {
     system.build.OCIImage = import ../../lib/make-disk-image.nix {
       inherit config lib pkgs;
+      inherit (cfg) diskSize;
       name = "oci-image";
       configFile = ./oci-config-user.nix;
       format = "qcow2";
-      diskSize = 8192;
       partitionTableType = if cfg.efi then "efi" else "legacy";
     };
 
diff --git a/nixos/modules/virtualisation/oci-options.nix b/nixos/modules/virtualisation/oci-options.nix
index 0dfedc6a530c8..76f3475a42817 100644
--- a/nixos/modules/virtualisation/oci-options.nix
+++ b/nixos/modules/virtualisation/oci-options.nix
@@ -9,6 +9,12 @@
           Whether the OCI instance is using EFI.
         '';
       };
+      diskSize = lib.mkOption {
+        type = lib.types.int;
+        default = 8192;
+        description = "Size of the disk image created in MB.";
+        example = "diskSize = 12 * 1024; # 12GiB";
+      };
     };
   };
 }
diff --git a/nixos/modules/virtualisation/proxmox-image.nix b/nixos/modules/virtualisation/proxmox-image.nix
index 6349bcef99e6b..01ad86c08cd78 100644
--- a/nixos/modules/virtualisation/proxmox-image.nix
+++ b/nixos/modules/virtualisation/proxmox-image.nix
@@ -16,7 +16,7 @@ with lib;
       };
       scsihw = mkOption {
         type = types.str;
-        default = "virtio-scsi-pci";
+        default = "virtio-scsi-single";
         example = "lsi";
         description = ''
           SCSI controller type. Must be one of the supported values given in
@@ -158,6 +158,31 @@ with lib;
         any specific VMID.
       '';
     };
+    cloudInit = {
+      enable = mkOption {
+        type = types.bool;
+        default = true;
+        description = ''
+          Whether the VM should accept cloud init configurations from PVE.
+        '';
+      };
+      defaultStorage = mkOption {
+        default = "local-lvm";
+        example = "tank";
+        type = types.str;
+        description = ''
+          Default storage name for cloud init drive.
+        '';
+      };
+      device = mkOption {
+        default = "ide2";
+        example = "scsi0";
+        type = types.str;
+        description = ''
+          Bus/device to which the cloud init drive is attached.
+        '';
+      };
+    };
   };
 
   config = let
@@ -216,37 +241,21 @@ with lib;
           seccompSupport = false;
           guestAgentSupport = false;
         }).overrideAttrs ( super: rec {
-
-          version = "7.2.1";
+          # Check https://github.com/proxmox/pve-qemu/tree/master for the version
+          # of qemu and patch to use
+          version = "8.1.5";
           src = pkgs.fetchurl {
-            url= "https://download.qemu.org/qemu-${version}.tar.xz";
-            sha256 = "sha256-jIVpms+dekOl/immTN1WNwsMLRrQdLr3CYqCTReq1zs=";
+            url = "https://download.qemu.org/qemu-${version}.tar.xz";
+            hash = "sha256-l2Ox7+xP1JeWtQgNCINRLXDLY4nq1lxmHMNoalIjKJY=";
           };
           patches = [
             # Proxmox' VMA tool is published as a particular patch upon QEMU
-            (pkgs.fetchpatch {
-              url =
-                let
-                  rev = "abb04bb6272c1202ca9face0827917552b9d06f6";
-                  path = "debian/patches/pve/0027-PVE-Backup-add-vma-backup-format-code.patch";
-                in "https://git.proxmox.com/?p=pve-qemu.git;a=blob_plain;hb=${rev};f=${path}";
-              hash = "sha256-3d0HHdvaExCry6zcULnziYnWIAnn24vECkI4sjj2BMg=";
-            })
-
-            # Proxmox' VMA tool uses O_DIRECT which fails on tmpfs
-            # Filed to upstream issue tracker: https://bugzilla.proxmox.com/show_bug.cgi?id=4710
-            (pkgs.writeText "inline.patch" ''
-                --- a/vma-writer.c   2023-05-01 15:11:13.361341177 +0200
-                +++ b/vma-writer.c   2023-05-01 15:10:51.785293129 +0200
-                @@ -306,7 +306,7 @@
-                             /* try to use O_NONBLOCK */
-                             fcntl(vmaw->fd, F_SETFL, fcntl(vmaw->fd, F_GETFL)|O_NONBLOCK);
-                         } else  {
-                -            oflags = O_NONBLOCK|O_DIRECT|O_WRONLY|O_EXCL;
-                +            oflags = O_NONBLOCK|O_WRONLY|O_EXCL;
-                             vmaw->fd = qemu_create(filename, oflags, 0644, errp);
-                         }
-            '')
+            "${pkgs.fetchFromGitHub {
+              owner = "proxmox";
+              repo = "pve-qemu";
+              rev = "71dd2d48f9122e60e4c0a8480122a27aab15dc70";
+              hash = "sha256-Q8AxNv4geDdlbVIWphRO5P3ESo0SGgvUpVPmPJzubJM=";
+            }}/debian/patches/pve/0027-PVE-Backup-add-vma-backup-format-code.patch"
           ];
 
           buildInputs = super.buildInputs ++ [ pkgs.libuuid ];
@@ -262,7 +271,7 @@ with lib;
         mv "vzdump-qemu-${cfg.filenameSuffix}.vma.zst" $out/
 
         mkdir -p $out/nix-support
-        echo "file vma $out/vzdump-qemu-${cfg.filenameSuffix}.vma.zst" >> $out/nix-support/hydra-build-products
+        echo "file vma $out/vzdump-qemu-${cfg.filenameSuffix}.vma.zst" > $out/nix-support/hydra-build-products
       '';
       inherit (cfg.qemuConf) additionalSpace diskSize bootSize;
       format = "raw";
@@ -298,6 +307,20 @@ with lib;
       fsType = "vfat";
     };
 
-    services.qemuGuest.enable = lib.mkDefault true;
+    networking = mkIf cfg.cloudInit.enable {
+      hostName = mkForce "";
+      useDHCP = false;
+    };
+
+    services = {
+      cloud-init = mkIf cfg.cloudInit.enable {
+        enable = true;
+        network.enable = true;
+      };
+      sshd.enable = mkDefault true;
+      qemuGuest.enable = true;
+    };
+
+    proxmox.qemuExtraConf.${cfg.cloudInit.device} = "${cfg.cloudInit.defaultStorage}:vm-9999-cloudinit,media=cdrom";
   };
 }
diff --git a/nixos/modules/virtualisation/proxmox-lxc.nix b/nixos/modules/virtualisation/proxmox-lxc.nix
index 9b9f99e5b8172..ff1c0972166cf 100644
--- a/nixos/modules/virtualisation/proxmox-lxc.nix
+++ b/nixos/modules/virtualisation/proxmox-lxc.nix
@@ -55,6 +55,8 @@ with lib;
         loader.initScript.enable = true;
       };
 
+      console.enable = true;
+
       networking = mkIf (!cfg.manageNetwork) {
         useDHCP = false;
         useHostResolvConf = false;
@@ -68,8 +70,13 @@ with lib;
         startWhenNeeded = mkDefault true;
       };
 
-      systemd.mounts = mkIf (!cfg.privileged)
-        [{ where = "/sys/kernel/debug"; enable = false; }];
+      systemd = {
+        mounts = mkIf (!cfg.privileged) [{
+          enable = false;
+          where = "/sys/kernel/debug";
+        }];
+        services."getty@".unitConfig.ConditionPathExists = [ "" "/dev/%I" ];
+      };
 
     };
 }
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/modules/virtualisation/spice-usb-redirection.nix b/nixos/modules/virtualisation/spice-usb-redirection.nix
index 255327f2622c9..1631a91ccf863 100644
--- a/nixos/modules/virtualisation/spice-usb-redirection.nix
+++ b/nixos/modules/virtualisation/spice-usb-redirection.nix
@@ -22,5 +22,5 @@
     };
   };
 
-  meta.maintainers = [ lib.maintainers.lheckemann ];
+  meta.maintainers = [ ];
 }
diff --git a/nixos/modules/virtualisation/vagrant-guest.nix b/nixos/modules/virtualisation/vagrant-guest.nix
index 2fad376086e34..120a2a2324d21 100644
--- a/nixos/modules/virtualisation/vagrant-guest.nix
+++ b/nixos/modules/virtualisation/vagrant-guest.nix
@@ -11,8 +11,7 @@ let
     #!${pkgs.runtimeShell}
     if [ ! -e ~/.ssh/authorized_keys ]; then
       mkdir -m 0700 -p ~/.ssh
-      echo "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA6NF8iallvQVp22WDkTkyrtvp9eWW6A8YVr+kz4TjGYe7gHzIw+niNltGEFHzD8+v1I2YJ6oXevct1YeS0o9HZyN1Q9qgCgzUFtdOKLv6IedplqoPkcmF0aYet2PkEDo3MlTBckFXPITAMzF8dJSIFo9D8HfdOV0IAdx4O7PtixWKn5y2hMNG0zQPyUecp4pzC6kivAIhyfHilFR61RGL+GPXQ2MWZWFYbAGjyiYJnAmCP3NOTd0jMZEnDkbUvxhMmBYSdETk1rRgm+R4LOzFUGaHqHDLKLX+FIPKcF96hrucXzcWyLbIbEgE98OHlnVYCzRdK8jlqm8tehUc9c9WhQ== vagrant insecure public key" >> ~/.ssh/authorized_keys
-      chmod 0600 ~/.ssh/authorized_keys
+      install -m 0600 <(echo "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA6NF8iallvQVp22WDkTkyrtvp9eWW6A8YVr+kz4TjGYe7gHzIw+niNltGEFHzD8+v1I2YJ6oXevct1YeS0o9HZyN1Q9qgCgzUFtdOKLv6IedplqoPkcmF0aYet2PkEDo3MlTBckFXPITAMzF8dJSIFo9D8HfdOV0IAdx4O7PtixWKn5y2hMNG0zQPyUecp4pzC6kivAIhyfHilFR61RGL+GPXQ2MWZWFYbAGjyiYJnAmCP3NOTd0jMZEnDkbUvxhMmBYSdETk1rRgm+R4LOzFUGaHqHDLKLX+FIPKcF96hrucXzcWyLbIbEgE98OHlnVYCzRdK8jlqm8tehUc9c9WhQ== vagrant insecure public key") ~/.ssh/authorized_keys
     fi
   '';
 in
diff --git a/nixos/modules/virtualisation/virtualbox-guest.nix b/nixos/modules/virtualisation/virtualbox-guest.nix
index 649ff3abb9ae9..b4933cffa2c0c 100644
--- a/nixos/modules/virtualisation/virtualbox-guest.nix
+++ b/nixos/modules/virtualisation/virtualbox-guest.nix
@@ -31,7 +31,9 @@ let
   };
 in
 {
-  ###### interface
+  imports = [
+    (mkRenamedOptionModule [ "virtualisation" "virtualbox" "guest" "draganddrop" ] [ "virtualisation" "virtualbox" "guest" "dragAndDrop" ])
+  ];
 
   options.virtualisation.virtualbox.guest = {
     enable = mkOption {
@@ -52,7 +54,7 @@ in
       description = "Whether to enable seamless mode. When activated windows from the guest appear next to the windows of the host.";
     };
 
-    draganddrop = mkOption {
+    dragAndDrop = mkOption {
       default = true;
       type = types.bool;
       description = "Whether to enable drag and drop support.";
@@ -111,5 +113,10 @@ in
         systemd.user.services.virtualboxClientSeamless = mkVirtualBoxUserService "--seamless";
       }
     )
+    (
+      mkIf cfg.dragAndDrop {
+        systemd.user.services.virtualboxClientDragAndDrop = mkVirtualBoxUserService "--draganddrop";
+      }
+    )
   ]);
 }
diff --git a/nixos/modules/virtualisation/virtualbox-host.nix b/nixos/modules/virtualisation/virtualbox-host.nix
index 609799995c527..a34fe132ba7e1 100644
--- a/nixos/modules/virtualisation/virtualbox-host.nix
+++ b/nixos/modules/virtualisation/virtualbox-host.nix
@@ -134,7 +134,7 @@ in
     assertions = [
       {
         assertion = !cfg.addNetworkInterface;
-        message = "VirtualBox KVM only supports standard NAT networking for VMs. Please turn off virtualisation.virtualbox.host.addNetworkInferface.";
+        message = "VirtualBox KVM only supports standard NAT networking for VMs. Please turn off virtualisation.virtualbox.host.addNetworkInterface.";
       }
 
       {