about summary refs log tree commit diff
path: root/nixpkgs/nixos
diff options
context:
space:
mode:
authorAlyssa Ross <hi@alyssa.is>2023-12-01 19:00:09 +0100
committerAlyssa Ross <hi@alyssa.is>2023-12-01 19:00:09 +0100
commit9e9b07490d5bab5d115c66b80bdb10ff0c11ed8d (patch)
tree4368f9e4cb2d5b93a956c085337e45cb70f1e331 /nixpkgs/nixos
parenta9cbfb6941b47d6f50129e6e36927882392daed7 (diff)
parent2344fe1da14cb08b0c18743b207995f9b8597915 (diff)
downloadnixlib-9e9b07490d5bab5d115c66b80bdb10ff0c11ed8d.tar
nixlib-9e9b07490d5bab5d115c66b80bdb10ff0c11ed8d.tar.gz
nixlib-9e9b07490d5bab5d115c66b80bdb10ff0c11ed8d.tar.bz2
nixlib-9e9b07490d5bab5d115c66b80bdb10ff0c11ed8d.tar.lz
nixlib-9e9b07490d5bab5d115c66b80bdb10ff0c11ed8d.tar.xz
nixlib-9e9b07490d5bab5d115c66b80bdb10ff0c11ed8d.tar.zst
nixlib-9e9b07490d5bab5d115c66b80bdb10ff0c11ed8d.zip
Merge https://github.com/NixOS/nixpkgs
Diffstat (limited to 'nixpkgs/nixos')
-rw-r--r--nixpkgs/nixos/doc/manual/configuration/linux-kernel.chapter.md66
-rw-r--r--nixpkgs/nixos/doc/manual/installation/upgrading.chapter.md16
-rw-r--r--nixpkgs/nixos/doc/manual/release-notes/rl-2311.section.md1670
-rw-r--r--nixpkgs/nixos/doc/manual/release-notes/rl-2405.section.md41
-rw-r--r--nixpkgs/nixos/maintainers/scripts/lxd/lxd-container-image-inner.nix2
-rw-r--r--nixpkgs/nixos/modules/config/pulseaudio.nix1
-rw-r--r--nixpkgs/nixos/modules/config/sysctl.nix3
-rw-r--r--nixpkgs/nixos/modules/config/xdg/portal.nix67
-rw-r--r--nixpkgs/nixos/modules/hardware/ckb-next.nix9
-rw-r--r--nixpkgs/nixos/modules/hardware/digitalbitbox.nix9
-rw-r--r--nixpkgs/nixos/modules/hardware/opentabletdriver.nix9
-rw-r--r--nixpkgs/nixos/modules/hardware/video/nvidia.nix11
-rw-r--r--nixpkgs/nixos/modules/i18n/input-method/ibus.nix2
-rw-r--r--nixpkgs/nixos/modules/installer/tools/tools.nix9
-rw-r--r--nixpkgs/nixos/modules/misc/locate.nix10
-rw-r--r--nixpkgs/nixos/modules/module-list.nix19
-rw-r--r--nixpkgs/nixos/modules/profiles/hardened.nix4
-rw-r--r--nixpkgs/nixos/modules/profiles/macos-builder.nix13
-rw-r--r--nixpkgs/nixos/modules/programs/_1password-gui.nix2
-rw-r--r--nixpkgs/nixos/modules/programs/_1password.nix2
-rw-r--r--nixpkgs/nixos/modules/programs/atop.nix9
-rw-r--r--nixpkgs/nixos/modules/programs/captive-browser.nix10
-rw-r--r--nixpkgs/nixos/modules/programs/darling.nix2
-rw-r--r--nixpkgs/nixos/modules/programs/digitalbitbox/default.nix9
-rw-r--r--nixpkgs/nixos/modules/programs/direnv.nix4
-rw-r--r--nixpkgs/nixos/modules/programs/dmrconfig.nix7
-rw-r--r--nixpkgs/nixos/modules/programs/dublin-traceroute.nix31
-rw-r--r--nixpkgs/nixos/modules/programs/environment.nix2
-rw-r--r--nixpkgs/nixos/modules/programs/evince.nix7
-rw-r--r--nixpkgs/nixos/modules/programs/feedbackd.nix9
-rw-r--r--nixpkgs/nixos/modules/programs/file-roller.nix7
-rw-r--r--nixpkgs/nixos/modules/programs/flashrom.nix2
-rw-r--r--nixpkgs/nixos/modules/programs/flexoptix-app.nix7
-rw-r--r--nixpkgs/nixos/modules/programs/gamescope.nix9
-rw-r--r--nixpkgs/nixos/modules/programs/git.nix24
-rw-r--r--nixpkgs/nixos/modules/programs/gnupg.nix9
-rw-r--r--nixpkgs/nixos/modules/programs/htop.nix9
-rw-r--r--nixpkgs/nixos/modules/programs/hyprland.nix5
-rw-r--r--nixpkgs/nixos/modules/programs/i3lock.nix14
-rw-r--r--nixpkgs/nixos/modules/programs/iay.nix4
-rw-r--r--nixpkgs/nixos/modules/programs/java.nix9
-rw-r--r--nixpkgs/nixos/modules/programs/joycond-cemuhook.nix17
-rw-r--r--nixpkgs/nixos/modules/programs/k40-whisperer.nix10
-rw-r--r--nixpkgs/nixos/modules/programs/kdeconnect.nix10
-rw-r--r--nixpkgs/nixos/modules/programs/mininet.nix33
-rw-r--r--nixpkgs/nixos/modules/programs/minipro.nix2
-rw-r--r--nixpkgs/nixos/modules/programs/mtr.nix9
-rw-r--r--nixpkgs/nixos/modules/programs/nano.nix2
-rw-r--r--nixpkgs/nixos/modules/programs/neovim.nix7
-rw-r--r--nixpkgs/nixos/modules/programs/nexttrace.nix2
-rw-r--r--nixpkgs/nixos/modules/programs/nix-index.nix7
-rw-r--r--nixpkgs/nixos/modules/programs/nix-ld.nix2
-rw-r--r--nixpkgs/nixos/modules/programs/nncp.nix7
-rw-r--r--nixpkgs/nixos/modules/programs/noisetorch.nix9
-rw-r--r--nixpkgs/nixos/modules/programs/npm.nix8
-rw-r--r--nixpkgs/nixos/modules/programs/oddjobd.nix7
-rw-r--r--nixpkgs/nixos/modules/programs/projecteur.nix2
-rw-r--r--nixpkgs/nixos/modules/programs/proxychains.nix4
-rw-r--r--nixpkgs/nixos/modules/programs/qdmr.nix2
-rw-r--r--nixpkgs/nixos/modules/programs/regreet.nix2
-rw-r--r--nixpkgs/nixos/modules/programs/shadow.nix2
-rw-r--r--nixpkgs/nixos/modules/programs/singularity.nix32
-rw-r--r--nixpkgs/nixos/modules/programs/skim.nix4
-rw-r--r--nixpkgs/nixos/modules/programs/ssh.nix9
-rw-r--r--nixpkgs/nixos/modules/programs/streamdeck-ui.nix2
-rw-r--r--nixpkgs/nixos/modules/programs/tsm-client.nix13
-rw-r--r--nixpkgs/nixos/modules/programs/vim.nix10
-rw-r--r--nixpkgs/nixos/modules/programs/wayland/cardboard.nix2
-rw-r--r--nixpkgs/nixos/modules/programs/wayland/river.nix9
-rw-r--r--nixpkgs/nixos/modules/programs/wayland/sway.nix2
-rw-r--r--nixpkgs/nixos/modules/programs/wayland/waybar.nix2
-rw-r--r--nixpkgs/nixos/modules/programs/wayland/wayfire.nix4
-rw-r--r--nixpkgs/nixos/modules/programs/weylus.nix7
-rw-r--r--nixpkgs/nixos/modules/programs/wireshark.nix9
-rw-r--r--nixpkgs/nixos/modules/programs/xonsh.nix10
-rw-r--r--nixpkgs/nixos/modules/programs/yazi.nix2
-rw-r--r--nixpkgs/nixos/modules/programs/zsh/oh-my-zsh.nix10
-rw-r--r--nixpkgs/nixos/modules/programs/zsh/zsh-autoenv.nix10
-rw-r--r--nixpkgs/nixos/modules/security/lock-kernel-modules.nix4
-rw-r--r--nixpkgs/nixos/modules/security/pam.nix13
-rw-r--r--nixpkgs/nixos/modules/security/please.nix9
-rw-r--r--nixpkgs/nixos/modules/security/sudo-rs.nix77
-rw-r--r--nixpkgs/nixos/modules/services/admin/meshcentral.nix7
-rw-r--r--nixpkgs/nixos/modules/services/amqp/rabbitmq.nix9
-rw-r--r--nixpkgs/nixos/modules/services/audio/botamusique.nix7
-rw-r--r--nixpkgs/nixos/modules/services/audio/gmediarender.nix2
-rw-r--r--nixpkgs/nixos/modules/services/audio/goxlr-utility.nix2
-rw-r--r--nixpkgs/nixos/modules/services/audio/jack.nix11
-rw-r--r--nixpkgs/nixos/modules/services/audio/jmusicbot.nix7
-rw-r--r--nixpkgs/nixos/modules/services/audio/navidrome.nix2
-rw-r--r--nixpkgs/nixos/modules/services/audio/slimserver.nix7
-rw-r--r--nixpkgs/nixos/modules/services/audio/wyoming/faster-whisper.nix4
-rw-r--r--nixpkgs/nixos/modules/services/audio/wyoming/openwakeword.nix4
-rw-r--r--nixpkgs/nixos/modules/services/audio/wyoming/piper.nix6
-rw-r--r--nixpkgs/nixos/modules/services/backup/borgbackup.nix2
-rw-r--r--nixpkgs/nixos/modules/services/backup/btrbk.nix35
-rw-r--r--nixpkgs/nixos/modules/services/backup/duplicati.nix2
-rw-r--r--nixpkgs/nixos/modules/services/backup/postgresql-wal-receiver.nix8
-rw-r--r--nixpkgs/nixos/modules/services/backup/restic-rest-server.nix7
-rw-r--r--nixpkgs/nixos/modules/services/backup/restic.nix9
-rw-r--r--nixpkgs/nixos/modules/services/backup/sanoid.nix2
-rw-r--r--nixpkgs/nixos/modules/services/backup/syncoid.nix10
-rw-r--r--nixpkgs/nixos/modules/services/backup/zrepl.nix7
-rw-r--r--nixpkgs/nixos/modules/services/blockchain/ethereum/erigon.nix2
-rw-r--r--nixpkgs/nixos/modules/services/blockchain/ethereum/geth.nix7
-rw-r--r--nixpkgs/nixos/modules/services/cluster/corosync/default.nix7
-rw-r--r--nixpkgs/nixos/modules/services/cluster/hadoop/default.nix7
-rw-r--r--nixpkgs/nixos/modules/services/cluster/hadoop/hbase.nix7
-rw-r--r--nixpkgs/nixos/modules/services/cluster/k3s/default.nix7
-rw-r--r--nixpkgs/nixos/modules/services/cluster/kubernetes/default.nix7
-rw-r--r--nixpkgs/nixos/modules/services/cluster/pacemaker/default.nix7
-rw-r--r--nixpkgs/nixos/modules/services/cluster/spark/default.nix24
-rw-r--r--nixpkgs/nixos/modules/services/computing/boinc/client.nix10
-rw-r--r--nixpkgs/nixos/modules/services/computing/foldingathome/client.nix13
-rw-r--r--nixpkgs/nixos/modules/services/computing/slurm/slurm.nix10
-rw-r--r--nixpkgs/nixos/modules/services/continuous-integration/buildbot/master.nix8
-rw-r--r--nixpkgs/nixos/modules/services/continuous-integration/buildbot/worker.nix8
-rw-r--r--nixpkgs/nixos/modules/services/continuous-integration/gitea-actions-runner.nix4
-rw-r--r--nixpkgs/nixos/modules/services/continuous-integration/github-runner/options.nix9
-rw-r--r--nixpkgs/nixos/modules/services/continuous-integration/gitlab-runner.nix8
-rw-r--r--nixpkgs/nixos/modules/services/continuous-integration/hercules-ci-agent/common.nix11
-rw-r--r--nixpkgs/nixos/modules/services/continuous-integration/hydra/default.nix7
-rw-r--r--nixpkgs/nixos/modules/services/continuous-integration/jenkins/default.nix7
-rw-r--r--nixpkgs/nixos/modules/services/continuous-integration/jenkins/slave.nix9
-rw-r--r--nixpkgs/nixos/modules/services/continuous-integration/woodpecker/agents.nix2
-rw-r--r--nixpkgs/nixos/modules/services/continuous-integration/woodpecker/server.nix2
-rw-r--r--nixpkgs/nixos/modules/services/databases/aerospike.nix7
-rw-r--r--nixpkgs/nixos/modules/services/databases/cassandra.nix11
-rw-r--r--nixpkgs/nixos/modules/services/databases/clickhouse.nix9
-rw-r--r--nixpkgs/nixos/modules/services/databases/cockroachdb.nix9
-rw-r--r--nixpkgs/nixos/modules/services/databases/couchdb.nix9
-rw-r--r--nixpkgs/nixos/modules/services/databases/dgraph.nix2
-rw-r--r--nixpkgs/nixos/modules/services/databases/firebird.nix10
-rw-r--r--nixpkgs/nixos/modules/services/databases/hbase-standalone.nix10
-rw-r--r--nixpkgs/nixos/modules/services/databases/influxdb.nix7
-rw-r--r--nixpkgs/nixos/modules/services/databases/influxdb2.nix8
-rw-r--r--nixpkgs/nixos/modules/services/databases/lldap.nix2
-rw-r--r--nixpkgs/nixos/modules/services/databases/monetdb.nix7
-rw-r--r--nixpkgs/nixos/modules/services/databases/mongodb.nix9
-rw-r--r--nixpkgs/nixos/modules/services/databases/neo4j.nix9
-rw-r--r--nixpkgs/nixos/modules/services/databases/openldap.nix9
-rw-r--r--nixpkgs/nixos/modules/services/databases/opentsdb.nix9
-rw-r--r--nixpkgs/nixos/modules/services/databases/pgbouncer.nix9
-rw-r--r--nixpkgs/nixos/modules/services/databases/pgmanage.nix9
-rw-r--r--nixpkgs/nixos/modules/services/databases/postgresql.nix12
-rw-r--r--nixpkgs/nixos/modules/services/databases/redis.nix11
-rw-r--r--nixpkgs/nixos/modules/services/databases/surrealdb.nix9
-rw-r--r--nixpkgs/nixos/modules/services/databases/victoriametrics.nix9
-rw-r--r--nixpkgs/nixos/modules/services/desktops/deepin/app-services.nix11
-rw-r--r--nixpkgs/nixos/modules/services/desktops/flatpak.md1
-rw-r--r--nixpkgs/nixos/modules/services/desktops/gnome/gnome-initial-setup.nix3
-rw-r--r--nixpkgs/nixos/modules/services/desktops/gvfs.nix7
-rw-r--r--nixpkgs/nixos/modules/services/desktops/pipewire/pipewire.nix9
-rw-r--r--nixpkgs/nixos/modules/services/desktops/seatd.nix51
-rw-r--r--nixpkgs/nixos/modules/services/development/athens.md52
-rw-r--r--nixpkgs/nixos/modules/services/development/athens.nix936
-rw-r--r--nixpkgs/nixos/modules/services/development/distccd.nix9
-rw-r--r--nixpkgs/nixos/modules/services/development/jupyter/default.nix15
-rw-r--r--nixpkgs/nixos/modules/services/development/rstudio-server/default.nix10
-rw-r--r--nixpkgs/nixos/modules/services/development/zammad.nix7
-rw-r--r--nixpkgs/nixos/modules/services/display-managers/greetd.nix7
-rw-r--r--nixpkgs/nixos/modules/services/editors/emacs.md15
-rw-r--r--nixpkgs/nixos/modules/services/editors/emacs.nix9
-rw-r--r--nixpkgs/nixos/modules/services/editors/infinoted.nix9
-rw-r--r--nixpkgs/nixos/modules/services/finance/odoo.nix7
-rw-r--r--nixpkgs/nixos/modules/services/games/asf.nix25
-rw-r--r--nixpkgs/nixos/modules/services/games/crossfire-server.nix12
-rw-r--r--nixpkgs/nixos/modules/services/games/deliantra-server.nix12
-rw-r--r--nixpkgs/nixos/modules/services/games/factorio.nix56
-rw-r--r--nixpkgs/nixos/modules/services/games/mchprs.nix7
-rw-r--r--nixpkgs/nixos/modules/services/games/minecraft-server.nix8
-rw-r--r--nixpkgs/nixos/modules/services/games/openarena.nix2
-rw-r--r--nixpkgs/nixos/modules/services/games/quake3-server.nix2
-rw-r--r--nixpkgs/nixos/modules/services/hardware/auto-epp.nix80
-rw-r--r--nixpkgs/nixos/modules/services/hardware/bluetooth.nix11
-rw-r--r--nixpkgs/nixos/modules/services/hardware/freefall.nix9
-rw-r--r--nixpkgs/nixos/modules/services/hardware/fwupd.nix9
-rw-r--r--nixpkgs/nixos/modules/services/hardware/joycond.nix9
-rw-r--r--nixpkgs/nixos/modules/services/hardware/kanata.nix13
-rw-r--r--nixpkgs/nixos/modules/services/hardware/openrgb.nix7
-rw-r--r--nixpkgs/nixos/modules/services/hardware/sane.nix11
-rw-r--r--nixpkgs/nixos/modules/services/hardware/thermald.nix7
-rw-r--r--nixpkgs/nixos/modules/services/hardware/undervolt.nix9
-rw-r--r--nixpkgs/nixos/modules/services/hardware/upower.nix9
-rw-r--r--nixpkgs/nixos/modules/services/hardware/usbmuxd.nix2
-rw-r--r--nixpkgs/nixos/modules/services/hardware/vdr.nix8
-rw-r--r--nixpkgs/nixos/modules/services/home-automation/esphome.nix13
-rw-r--r--nixpkgs/nixos/modules/services/home-automation/homeassistant-satellite.nix4
-rw-r--r--nixpkgs/nixos/modules/services/home-automation/zigbee2mqtt.nix9
-rw-r--r--nixpkgs/nixos/modules/services/home-automation/zwave-js.nix2
-rw-r--r--nixpkgs/nixos/modules/services/logging/SystemdJournal2Gelf.nix9
-rw-r--r--nixpkgs/nixos/modules/services/logging/filebeat.nix11
-rw-r--r--nixpkgs/nixos/modules/services/logging/fluentd.nix7
-rw-r--r--nixpkgs/nixos/modules/services/logging/heartbeat.nix10
-rw-r--r--nixpkgs/nixos/modules/services/logging/journalbeat.nix9
-rw-r--r--nixpkgs/nixos/modules/services/logging/logstash.nix7
-rw-r--r--nixpkgs/nixos/modules/services/logging/syslog-ng.nix9
-rw-r--r--nixpkgs/nixos/modules/services/logging/vector.nix2
-rw-r--r--nixpkgs/nixos/modules/services/mail/exim.nix10
-rw-r--r--nixpkgs/nixos/modules/services/mail/listmonk.nix2
-rw-r--r--nixpkgs/nixos/modules/services/mail/offlineimap.nix7
-rw-r--r--nixpkgs/nixos/modules/services/mail/opensmtpd.nix7
-rw-r--r--nixpkgs/nixos/modules/services/mail/public-inbox.nix7
-rw-r--r--nixpkgs/nixos/modules/services/mail/roundcube.nix17
-rw-r--r--nixpkgs/nixos/modules/services/mail/stalwart-mail.nix2
-rw-r--r--nixpkgs/nixos/modules/services/matrix/appservice-discord.nix9
-rw-r--r--nixpkgs/nixos/modules/services/matrix/conduit.nix9
-rw-r--r--nixpkgs/nixos/modules/services/matrix/matrix-sliding-sync.nix2
-rw-r--r--nixpkgs/nixos/modules/services/matrix/maubot.md103
-rw-r--r--nixpkgs/nixos/modules/services/matrix/maubot.nix459
-rw-r--r--nixpkgs/nixos/modules/services/misc/airsonic.nix11
-rw-r--r--nixpkgs/nixos/modules/services/misc/amazon-ssm-agent.nix19
-rw-r--r--nixpkgs/nixos/modules/services/misc/ananicy.nix18
-rw-r--r--nixpkgs/nixos/modules/services/misc/anki-sync-server.md68
-rw-r--r--nixpkgs/nixos/modules/services/misc/anki-sync-server.nix140
-rw-r--r--nixpkgs/nixos/modules/services/misc/ankisyncd.nix7
-rw-r--r--nixpkgs/nixos/modules/services/misc/apache-kafka.nix197
-rw-r--r--nixpkgs/nixos/modules/services/misc/autosuspend.nix4
-rw-r--r--nixpkgs/nixos/modules/services/misc/bcg.nix7
-rw-r--r--nixpkgs/nixos/modules/services/misc/calibre-server.nix2
-rw-r--r--nixpkgs/nixos/modules/services/misc/cgminer.nix7
-rw-r--r--nixpkgs/nixos/modules/services/misc/clipcat.nix7
-rw-r--r--nixpkgs/nixos/modules/services/misc/clipmenu.nix7
-rw-r--r--nixpkgs/nixos/modules/services/misc/confd.nix7
-rw-r--r--nixpkgs/nixos/modules/services/misc/disnix.nix7
-rw-r--r--nixpkgs/nixos/modules/services/misc/docker-registry.nix8
-rw-r--r--nixpkgs/nixos/modules/services/misc/dwm-status.nix10
-rw-r--r--nixpkgs/nixos/modules/services/misc/etcd.nix2
-rw-r--r--nixpkgs/nixos/modules/services/misc/forgejo.md2
-rw-r--r--nixpkgs/nixos/modules/services/misc/forgejo.nix4
-rw-r--r--nixpkgs/nixos/modules/services/misc/freeswitch.nix9
-rw-r--r--nixpkgs/nixos/modules/services/misc/gitea.nix7
-rw-r--r--nixpkgs/nixos/modules/services/misc/gitlab.nix36
-rw-r--r--nixpkgs/nixos/modules/services/misc/gollum.nix9
-rw-r--r--nixpkgs/nixos/modules/services/misc/greenclip.nix7
-rw-r--r--nixpkgs/nixos/modules/services/misc/heisenbridge.nix9
-rw-r--r--nixpkgs/nixos/modules/services/misc/homepage-dashboard.nix2
-rw-r--r--nixpkgs/nixos/modules/services/misc/input-remapper.nix2
-rw-r--r--nixpkgs/nixos/modules/services/misc/jackett.nix7
-rw-r--r--nixpkgs/nixos/modules/services/misc/jellyfin.nix9
-rw-r--r--nixpkgs/nixos/modules/services/misc/kafka.md63
-rw-r--r--nixpkgs/nixos/modules/services/misc/klipper.nix7
-rw-r--r--nixpkgs/nixos/modules/services/misc/libreddit.nix7
-rw-r--r--nixpkgs/nixos/modules/services/misc/lidarr.nix7
-rw-r--r--nixpkgs/nixos/modules/services/misc/mbpfan.nix7
-rw-r--r--nixpkgs/nixos/modules/services/misc/mediatomb.nix9
-rw-r--r--nixpkgs/nixos/modules/services/misc/moonraker.nix9
-rw-r--r--nixpkgs/nixos/modules/services/misc/nitter.nix7
-rw-r--r--nixpkgs/nixos/modules/services/misc/ntfy-sh.nix7
-rw-r--r--nixpkgs/nixos/modules/services/misc/nzbhydra2.nix7
-rw-r--r--nixpkgs/nixos/modules/services/misc/paperless.nix7
-rw-r--r--nixpkgs/nixos/modules/services/misc/plex.nix11
-rw-r--r--nixpkgs/nixos/modules/services/misc/polaris.nix2
-rw-r--r--nixpkgs/nixos/modules/services/misc/portunus.nix7
-rw-r--r--nixpkgs/nixos/modules/services/misc/preload.nix31
-rw-r--r--nixpkgs/nixos/modules/services/misc/prowlarr.nix2
-rw-r--r--nixpkgs/nixos/modules/services/misc/pufferpanel.nix2
-rw-r--r--nixpkgs/nixos/modules/services/misc/radarr.nix8
-rw-r--r--nixpkgs/nixos/modules/services/misc/readarr.nix7
-rw-r--r--nixpkgs/nixos/modules/services/misc/redmine.nix11
-rw-r--r--nixpkgs/nixos/modules/services/misc/rippled.nix7
-rw-r--r--nixpkgs/nixos/modules/services/misc/rmfakecloud.nix11
-rw-r--r--nixpkgs/nixos/modules/services/misc/rshim.nix2
-rw-r--r--nixpkgs/nixos/modules/services/misc/sickbeard.nix9
-rw-r--r--nixpkgs/nixos/modules/services/misc/sonarr.nix9
-rw-r--r--nixpkgs/nixos/modules/services/misc/sourcehut/default.nix37
-rw-r--r--nixpkgs/nixos/modules/services/misc/sourcehut/service.nix615
-rw-r--r--nixpkgs/nixos/modules/services/misc/spice-autorandr.nix2
-rw-r--r--nixpkgs/nixos/modules/services/misc/spice-webdavd.nix7
-rw-r--r--nixpkgs/nixos/modules/services/misc/tandoor-recipes.nix7
-rw-r--r--nixpkgs/nixos/modules/services/misc/tautulli.nix9
-rw-r--r--nixpkgs/nixos/modules/services/misc/tp-auto-kbbl.nix7
-rw-r--r--nixpkgs/nixos/modules/services/misc/xmrig.nix8
-rw-r--r--nixpkgs/nixos/modules/services/misc/zookeeper.nix7
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/arbtt.nix9
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/bosun.nix9
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/certspotter.nix2
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/cockpit.nix4
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/collectd.nix9
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/datadog-agent.nix15
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/goss.nix2
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/grafana-agent.nix2
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/grafana.nix7
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/heapster.nix7
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/karma.nix9
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/kthxbye.nix9
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/loki.nix2
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/metricbeat.nix11
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/mimir.nix9
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/netdata.nix7
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/ocsinventory-agent.nix2
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/opentelemetry-collector.nix9
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/prometheus/alertmanager-irc-relay.nix7
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/prometheus/alertmanager.nix9
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/prometheus/default.nix9
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/prometheus/exporters.nix1
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/exportarr.nix2
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/mongodb.nix68
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/php-fpm.nix2
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/pve.nix10
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/prometheus/pushgateway.nix9
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/scollector.nix9
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/telegraf.nix12
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/thanos.nix4
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/uptime-kuma.nix7
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/vmagent.nix9
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/vmalert.nix9
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/zabbix-agent.nix9
-rw-r--r--nixpkgs/nixos/modules/services/network-filesystems/ceph.nix10
-rw-r--r--nixpkgs/nixos/modules/services/network-filesystems/kubo.nix7
-rw-r--r--nixpkgs/nixos/modules/services/network-filesystems/litestream/default.nix7
-rw-r--r--nixpkgs/nixos/modules/services/network-filesystems/openafs/server.nix9
-rw-r--r--nixpkgs/nixos/modules/services/network-filesystems/samba.nix10
-rw-r--r--nixpkgs/nixos/modules/services/network-filesystems/tahoe.nix18
-rw-r--r--nixpkgs/nixos/modules/services/networking/acme-dns.nix4
-rw-r--r--nixpkgs/nixos/modules/services/networking/alice-lg.nix2
-rw-r--r--nixpkgs/nixos/modules/services/networking/asterisk.nix7
-rw-r--r--nixpkgs/nixos/modules/services/networking/avahi-daemon.nix9
-rw-r--r--nixpkgs/nixos/modules/services/networking/bee.nix8
-rw-r--r--nixpkgs/nixos/modules/services/networking/bind.nix7
-rw-r--r--nixpkgs/nixos/modules/services/networking/bird-lg.nix7
-rw-r--r--nixpkgs/nixos/modules/services/networking/birdwatcher.nix7
-rw-r--r--nixpkgs/nixos/modules/services/networking/bitcoind.nix7
-rw-r--r--nixpkgs/nixos/modules/services/networking/blockbook-frontend.nix7
-rw-r--r--nixpkgs/nixos/modules/services/networking/centrifugo.nix123
-rw-r--r--nixpkgs/nixos/modules/services/networking/cgit.nix2
-rw-r--r--nixpkgs/nixos/modules/services/networking/cloudflared.nix7
-rw-r--r--nixpkgs/nixos/modules/services/networking/consul.nix17
-rw-r--r--nixpkgs/nixos/modules/services/networking/coredns.nix7
-rw-r--r--nixpkgs/nixos/modules/services/networking/corerad.nix7
-rw-r--r--nixpkgs/nixos/modules/services/networking/dae.nix2
-rw-r--r--nixpkgs/nixos/modules/services/networking/dnsmasq.nix2
-rw-r--r--nixpkgs/nixos/modules/services/networking/ejabberd.nix7
-rw-r--r--nixpkgs/nixos/modules/services/networking/envoy.nix2
-rw-r--r--nixpkgs/nixos/modules/services/networking/epmd.nix10
-rw-r--r--nixpkgs/nixos/modules/services/networking/ferm.nix7
-rw-r--r--nixpkgs/nixos/modules/services/networking/firewall-iptables.nix1
-rw-r--r--nixpkgs/nixos/modules/services/networking/flannel.nix7
-rw-r--r--nixpkgs/nixos/modules/services/networking/frp.nix2
-rw-r--r--nixpkgs/nixos/modules/services/networking/ghostunnel.nix8
-rw-r--r--nixpkgs/nixos/modules/services/networking/gnunet.nix8
-rw-r--r--nixpkgs/nixos/modules/services/networking/haproxy.nix2
-rw-r--r--nixpkgs/nixos/modules/services/networking/harmonia.nix2
-rw-r--r--nixpkgs/nixos/modules/services/networking/headscale.nix9
-rw-r--r--nixpkgs/nixos/modules/services/networking/i2pd.nix9
-rw-r--r--nixpkgs/nixos/modules/services/networking/icecream/daemon.nix7
-rw-r--r--nixpkgs/nixos/modules/services/networking/icecream/scheduler.nix7
-rw-r--r--nixpkgs/nixos/modules/services/networking/iscsi/initiator.nix7
-rw-r--r--nixpkgs/nixos/modules/services/networking/iwd.nix11
-rw-r--r--nixpkgs/nixos/modules/services/networking/knot.nix9
-rw-r--r--nixpkgs/nixos/modules/services/networking/kresd.nix10
-rw-r--r--nixpkgs/nixos/modules/services/networking/lambdabot.nix7
-rw-r--r--nixpkgs/nixos/modules/services/networking/legit.nix4
-rw-r--r--nixpkgs/nixos/modules/services/networking/lokinet.nix7
-rw-r--r--nixpkgs/nixos/modules/services/networking/miredo.nix9
-rw-r--r--nixpkgs/nixos/modules/services/networking/morty.nix7
-rw-r--r--nixpkgs/nixos/modules/services/networking/mosquitto.nix9
-rw-r--r--nixpkgs/nixos/modules/services/networking/mtr-exporter.nix16
-rw-r--r--nixpkgs/nixos/modules/services/networking/mullvad-vpn.nix10
-rw-r--r--nixpkgs/nixos/modules/services/networking/multipath.nix7
-rw-r--r--nixpkgs/nixos/modules/services/networking/murmur.nix7
-rw-r--r--nixpkgs/nixos/modules/services/networking/mxisd.nix7
-rw-r--r--nixpkgs/nixos/modules/services/networking/nar-serve.nix2
-rw-r--r--nixpkgs/nixos/modules/services/networking/nat-nftables.nix31
-rw-r--r--nixpkgs/nixos/modules/services/networking/nebula.nix7
-rw-r--r--nixpkgs/nixos/modules/services/networking/netbird.nix7
-rw-r--r--nixpkgs/nixos/modules/services/networking/netclient.nix2
-rw-r--r--nixpkgs/nixos/modules/services/networking/ngircd.nix9
-rw-r--r--nixpkgs/nixos/modules/services/networking/nix-serve.nix13
-rw-r--r--nixpkgs/nixos/modules/services/networking/nomad.nix9
-rw-r--r--nixpkgs/nixos/modules/services/networking/ntp/chrony.nix9
-rw-r--r--nixpkgs/nixos/modules/services/networking/openconnect.nix2
-rw-r--r--nixpkgs/nixos/modules/services/networking/peroxide.nix2
-rw-r--r--nixpkgs/nixos/modules/services/networking/pleroma.nix7
-rw-r--r--nixpkgs/nixos/modules/services/networking/pppd.nix7
-rw-r--r--nixpkgs/nixos/modules/services/networking/prosody.nix8
-rw-r--r--nixpkgs/nixos/modules/services/networking/quassel.nix9
-rw-r--r--nixpkgs/nixos/modules/services/networking/radvd.nix9
-rw-r--r--nixpkgs/nixos/modules/services/networking/routedns.nix7
-rw-r--r--nixpkgs/nixos/modules/services/networking/sabnzbd.nix7
-rw-r--r--nixpkgs/nixos/modules/services/networking/seafile.nix7
-rw-r--r--nixpkgs/nixos/modules/services/networking/searx.nix7
-rw-r--r--nixpkgs/nixos/modules/services/networking/shellhub-agent.nix2
-rw-r--r--nixpkgs/nixos/modules/services/networking/sing-box.nix2
-rw-r--r--nixpkgs/nixos/modules/services/networking/skydns.nix7
-rw-r--r--nixpkgs/nixos/modules/services/networking/smokeping.nix7
-rw-r--r--nixpkgs/nixos/modules/services/networking/softether.nix9
-rw-r--r--nixpkgs/nixos/modules/services/networking/spacecookie.nix11
-rw-r--r--nixpkgs/nixos/modules/services/networking/squid.nix7
-rw-r--r--nixpkgs/nixos/modules/services/networking/strongswan-swanctl/module.nix9
-rw-r--r--nixpkgs/nixos/modules/services/networking/syncthing.nix9
-rw-r--r--nixpkgs/nixos/modules/services/networking/tailscale.nix2
-rw-r--r--nixpkgs/nixos/modules/services/networking/tayga.nix7
-rw-r--r--nixpkgs/nixos/modules/services/networking/teleport.nix8
-rw-r--r--nixpkgs/nixos/modules/services/networking/thelounge.nix2
-rw-r--r--nixpkgs/nixos/modules/services/networking/tinc.nix9
-rw-r--r--nixpkgs/nixos/modules/services/networking/tinyproxy.nix2
-rw-r--r--nixpkgs/nixos/modules/services/networking/tmate-ssh-server.nix13
-rw-r--r--nixpkgs/nixos/modules/services/networking/trickster.nix9
-rw-r--r--nixpkgs/nixos/modules/services/networking/trust-dns.nix12
-rw-r--r--nixpkgs/nixos/modules/services/networking/twingate.nix2
-rw-r--r--nixpkgs/nixos/modules/services/networking/ucarp.nix9
-rw-r--r--nixpkgs/nixos/modules/services/networking/unbound.nix7
-rw-r--r--nixpkgs/nixos/modules/services/networking/unifi.nix23
-rw-r--r--nixpkgs/nixos/modules/services/networking/v2ray.nix9
-rw-r--r--nixpkgs/nixos/modules/services/networking/vdirsyncer.nix2
-rw-r--r--nixpkgs/nixos/modules/services/networking/webhook.nix2
-rw-r--r--nixpkgs/nixos/modules/services/networking/wstunnel.nix2
-rw-r--r--nixpkgs/nixos/modules/services/networking/x2goserver.nix3
-rw-r--r--nixpkgs/nixos/modules/services/networking/xandikos.nix7
-rw-r--r--nixpkgs/nixos/modules/services/networking/xray.nix9
-rw-r--r--nixpkgs/nixos/modules/services/networking/xrdp.nix9
-rw-r--r--nixpkgs/nixos/modules/services/networking/yggdrasil.nix7
-rw-r--r--nixpkgs/nixos/modules/services/networking/zeronet.nix10
-rw-r--r--nixpkgs/nixos/modules/services/networking/zerotierone.nix9
-rw-r--r--nixpkgs/nixos/modules/services/search/elasticsearch.nix7
-rw-r--r--nixpkgs/nixos/modules/services/search/hound.nix9
-rw-r--r--nixpkgs/nixos/modules/services/search/meilisearch.nix9
-rw-r--r--nixpkgs/nixos/modules/services/search/opensearch.nix4
-rw-r--r--nixpkgs/nixos/modules/services/search/sonic-server.nix77
-rw-r--r--nixpkgs/nixos/modules/services/security/authelia.nix7
-rw-r--r--nixpkgs/nixos/modules/services/security/certmgr.nix7
-rw-r--r--nixpkgs/nixos/modules/services/security/clamav.nix110
-rw-r--r--nixpkgs/nixos/modules/services/security/esdm.nix2
-rw-r--r--nixpkgs/nixos/modules/services/security/fail2ban.nix12
-rw-r--r--nixpkgs/nixos/modules/services/security/haka.nix9
-rw-r--r--nixpkgs/nixos/modules/services/security/jitterentropy-rngd.nix2
-rw-r--r--nixpkgs/nixos/modules/services/security/kanidm.nix2
-rw-r--r--nixpkgs/nixos/modules/services/security/nginx-sso.nix9
-rw-r--r--nixpkgs/nixos/modules/services/security/oauth2_proxy.nix9
-rw-r--r--nixpkgs/nixos/modules/services/security/pass-secret-service.nix8
-rw-r--r--nixpkgs/nixos/modules/services/security/sks.nix7
-rw-r--r--nixpkgs/nixos/modules/services/security/tor.nix7
-rw-r--r--nixpkgs/nixos/modules/services/security/usbguard.nix10
-rw-r--r--nixpkgs/nixos/modules/services/security/vault-agent.nix2
-rw-r--r--nixpkgs/nixos/modules/services/security/vault.nix7
-rw-r--r--nixpkgs/nixos/modules/services/security/vaultwarden/default.nix7
-rw-r--r--nixpkgs/nixos/modules/services/security/yubikey-agent.nix9
-rw-r--r--nixpkgs/nixos/modules/services/system/automatic-timezoned.nix9
-rw-r--r--nixpkgs/nixos/modules/services/system/bpftune.nix2
-rw-r--r--nixpkgs/nixos/modules/services/system/cachix-agent/default.nix7
-rw-r--r--nixpkgs/nixos/modules/services/system/cachix-watch-store.nix8
-rw-r--r--nixpkgs/nixos/modules/services/system/saslauthd.nix7
-rw-r--r--nixpkgs/nixos/modules/services/system/zram-generator.nix2
-rw-r--r--nixpkgs/nixos/modules/services/torrent/deluge.nix8
-rw-r--r--nixpkgs/nixos/modules/services/torrent/flexget.nix2
-rw-r--r--nixpkgs/nixos/modules/services/torrent/opentracker.nix9
-rw-r--r--nixpkgs/nixos/modules/services/torrent/rtorrent.nix9
-rw-r--r--nixpkgs/nixos/modules/services/torrent/torrentstream.nix53
-rw-r--r--nixpkgs/nixos/modules/services/torrent/transmission.nix2
-rw-r--r--nixpkgs/nixos/modules/services/video/epgstation/default.nix8
-rw-r--r--nixpkgs/nixos/modules/services/video/frigate.nix9
-rw-r--r--nixpkgs/nixos/modules/services/video/go2rtc/default.nix4
-rw-r--r--nixpkgs/nixos/modules/services/video/mediamtx.nix2
-rw-r--r--nixpkgs/nixos/modules/services/video/unifi-video.nix27
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/akkoma.nix7
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/anuko-time-tracker.nix2
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/atlassian/confluence.nix20
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/atlassian/crowd.nix20
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/atlassian/jira.nix20
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/coder.nix9
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/documize.nix9
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/dokuwiki.nix18
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/dolibarr.nix6
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/engelsystem.nix9
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/ethercalc.nix7
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/fluidd.nix7
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/freshrss.nix7
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/galene.nix9
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/gerrit.nix14
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/gotosocial.nix2
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/grocy.nix2
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/guacamole-client.nix2
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/guacamole-server.nix2
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/healthchecks.nix7
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/hedgedoc.nix2
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/honk.nix2
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/invidious.nix7
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/invoiceplane.nix48
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/jirafeau.nix7
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/jitsi-meet.nix2
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/kavita.nix2
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/keycloak.nix10
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/lanraragi.nix15
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/lemmy.nix4
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/mainsail.nix7
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/matomo.nix11
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/mattermost.nix14
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/mediawiki.nix47
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/meme-bingo-web.nix9
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/miniflux.nix7
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/mobilizon.nix2
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/moodle.nix9
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/nextcloud.nix16
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/node-red.nix7
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/onlyoffice.nix7
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/openvscode-server.nix2
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/openwebrx.nix7
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/peertube.nix8
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/pgpkeyserver-lite.nix9
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/photoprism.nix2
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/phylactery.nix7
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/pict-rs.nix8
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/pixelfed.nix4
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/plantuml-server.nix12
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/plausible.nix2
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/sftpgo.nix9
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/shiori.nix7
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/slskd.nix2
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/vikunja.nix14
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/whitebophir.nix7
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/wordpress.nix7
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/youtrack.nix9
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/zabbix.nix9
-rw-r--r--nixpkgs/nixos/modules/services/web-servers/agate.nix7
-rw-r--r--nixpkgs/nixos/modules/services/web-servers/apache-httpd/default.nix18
-rw-r--r--nixpkgs/nixos/modules/services/web-servers/caddy/default.nix11
-rw-r--r--nixpkgs/nixos/modules/services/web-servers/lighttpd/default.nix9
-rw-r--r--nixpkgs/nixos/modules/services/web-servers/minio.nix7
-rw-r--r--nixpkgs/nixos/modules/services/web-servers/phpfpm/default.nix9
-rw-r--r--nixpkgs/nixos/modules/services/web-servers/tomcat.nix8
-rw-r--r--nixpkgs/nixos/modules/services/web-servers/traefik.nix7
-rw-r--r--nixpkgs/nixos/modules/services/web-servers/unit/default.nix7
-rw-r--r--nixpkgs/nixos/modules/services/web-servers/varnish/default.nix9
-rw-r--r--nixpkgs/nixos/modules/services/x11/desktop-managers/budgie.nix1
-rw-r--r--nixpkgs/nixos/modules/services/x11/desktop-managers/cinnamon.nix3
-rw-r--r--nixpkgs/nixos/modules/services/x11/desktop-managers/deepin.nix39
-rw-r--r--nixpkgs/nixos/modules/services/x11/desktop-managers/gnome.md2
-rw-r--r--nixpkgs/nixos/modules/services/x11/desktop-managers/gnome.nix10
-rw-r--r--nixpkgs/nixos/modules/services/x11/desktop-managers/kodi.nix10
-rw-r--r--nixpkgs/nixos/modules/services/x11/desktop-managers/lxqt.nix3
-rw-r--r--nixpkgs/nixos/modules/services/x11/desktop-managers/mate.nix2
-rw-r--r--nixpkgs/nixos/modules/services/x11/desktop-managers/pantheon.nix5
-rw-r--r--nixpkgs/nixos/modules/services/x11/desktop-managers/phosh.nix10
-rw-r--r--nixpkgs/nixos/modules/services/x11/desktop-managers/plasma5.nix5
-rw-r--r--nixpkgs/nixos/modules/services/x11/desktop-managers/retroarch.nix8
-rw-r--r--nixpkgs/nixos/modules/services/x11/desktop-managers/xfce.nix2
-rw-r--r--nixpkgs/nixos/modules/services/x11/picom.nix2
-rw-r--r--nixpkgs/nixos/modules/services/x11/redshift.nix9
-rw-r--r--nixpkgs/nixos/modules/services/x11/touchegg.nix7
-rw-r--r--nixpkgs/nixos/modules/services/x11/unclutter-xfixes.nix7
-rw-r--r--nixpkgs/nixos/modules/services/x11/unclutter.nix7
-rw-r--r--nixpkgs/nixos/modules/services/x11/urxvtd.nix9
-rw-r--r--nixpkgs/nixos/modules/services/x11/window-managers/awesome.nix7
-rw-r--r--nixpkgs/nixos/modules/services/x11/window-managers/bspwm.nix20
-rw-r--r--nixpkgs/nixos/modules/services/x11/window-managers/clfswm.nix9
-rw-r--r--nixpkgs/nixos/modules/services/x11/window-managers/dk.nix2
-rw-r--r--nixpkgs/nixos/modules/services/x11/window-managers/dwm.nix10
-rw-r--r--nixpkgs/nixos/modules/services/x11/window-managers/herbstluftwm.nix9
-rw-r--r--nixpkgs/nixos/modules/services/x11/window-managers/i3.nix24
-rw-r--r--nixpkgs/nixos/modules/services/x11/window-managers/katriawm.nix4
-rw-r--r--nixpkgs/nixos/modules/services/x11/window-managers/qtile.nix2
-rw-r--r--nixpkgs/nixos/modules/services/x11/window-managers/ragnarwm.nix9
-rw-r--r--nixpkgs/nixos/modules/services/x11/xscreensaver.nix40
-rw-r--r--nixpkgs/nixos/modules/system/boot/systemd.nix190
-rw-r--r--nixpkgs/nixos/modules/system/boot/unl0kr.nix89
-rw-r--r--nixpkgs/nixos/modules/tasks/filesystems/bcachefs.nix3
-rw-r--r--nixpkgs/nixos/modules/tasks/filesystems/zfs.nix31
-rw-r--r--nixpkgs/nixos/modules/tasks/snapraid.nix6
-rw-r--r--nixpkgs/nixos/modules/virtualisation/docker-rootless.nix9
-rw-r--r--nixpkgs/nixos/modules/virtualisation/docker.nix9
-rw-r--r--nixpkgs/nixos/modules/virtualisation/ecs-agent.nix7
-rw-r--r--nixpkgs/nixos/modules/virtualisation/incus.nix4
-rw-r--r--nixpkgs/nixos/modules/virtualisation/libvirtd.nix67
-rw-r--r--nixpkgs/nixos/modules/virtualisation/lxc-container.nix56
-rw-r--r--nixpkgs/nixos/modules/virtualisation/multipass.nix2
-rw-r--r--nixpkgs/nixos/modules/virtualisation/nixos-containers.nix248
-rw-r--r--nixpkgs/nixos/modules/virtualisation/openvswitch.nix9
-rw-r--r--nixpkgs/nixos/modules/virtualisation/qemu-guest-agent.nix7
-rw-r--r--nixpkgs/nixos/modules/virtualisation/qemu-vm.nix2
-rw-r--r--nixpkgs/nixos/modules/virtualisation/virtualbox-host.nix9
-rw-r--r--nixpkgs/nixos/modules/virtualisation/vmware-host.nix7
-rw-r--r--nixpkgs/nixos/modules/virtualisation/waydroid.nix20
-rw-r--r--nixpkgs/nixos/tests/all-tests.nix9
-rw-r--r--nixpkgs/nixos/tests/anki-sync-server.nix71
-rw-r--r--nixpkgs/nixos/tests/centrifugo.nix80
-rw-r--r--nixpkgs/nixos/tests/containers-ip.nix5
-rw-r--r--nixpkgs/nixos/tests/convos.nix1
-rw-r--r--nixpkgs/nixos/tests/deepin.nix6
-rw-r--r--nixpkgs/nixos/tests/dublin-traceroute.nix63
-rw-r--r--nixpkgs/nixos/tests/eris-server.nix2
-rw-r--r--nixpkgs/nixos/tests/geoserver.nix24
-rw-r--r--nixpkgs/nixos/tests/gnome-extensions.nix151
-rw-r--r--nixpkgs/nixos/tests/gnome-xorg.nix16
-rw-r--r--nixpkgs/nixos/tests/gnome.nix14
-rw-r--r--nixpkgs/nixos/tests/gvisor.nix36
-rw-r--r--nixpkgs/nixos/tests/incus/container.nix28
-rw-r--r--nixpkgs/nixos/tests/jitsi-meet.nix26
-rw-r--r--nixpkgs/nixos/tests/kafka.nix85
-rw-r--r--nixpkgs/nixos/tests/lanraragi.nix8
-rw-r--r--nixpkgs/nixos/tests/libvirtd.nix2
-rw-r--r--nixpkgs/nixos/tests/lxd/ui.nix33
-rw-r--r--nixpkgs/nixos/tests/matrix/synapse.nix44
-rw-r--r--nixpkgs/nixos/tests/nextcloud/with-declarative-redis-and-secrets.nix12
-rw-r--r--nixpkgs/nixos/tests/nixops/default.nix6
-rw-r--r--nixpkgs/nixos/tests/seatd.nix51
-rw-r--r--nixpkgs/nixos/tests/sonic-server.nix22
-rw-r--r--nixpkgs/nixos/tests/sudo-rs.nix6
-rw-r--r--nixpkgs/nixos/tests/systemd-initrd-luks-unl0kr.nix75
-rw-r--r--nixpkgs/nixos/tests/systemd-timesyncd.nix15
-rw-r--r--nixpkgs/nixos/tests/telegraf.nix1
-rw-r--r--nixpkgs/nixos/tests/terminal-emulators.nix2
-rw-r--r--nixpkgs/nixos/tests/tomcat.nix1
-rw-r--r--nixpkgs/nixos/tests/web-servers/stargazer.nix2
-rw-r--r--nixpkgs/nixos/tests/xscreensaver.nix64
-rw-r--r--nixpkgs/nixos/tests/zfs.nix10
606 files changed, 6733 insertions, 4462 deletions
diff --git a/nixpkgs/nixos/doc/manual/configuration/linux-kernel.chapter.md b/nixpkgs/nixos/doc/manual/configuration/linux-kernel.chapter.md
index f5bce99dd1bb..9d1b2bc2f9b8 100644
--- a/nixpkgs/nixos/doc/manual/configuration/linux-kernel.chapter.md
+++ b/nixpkgs/nixos/doc/manual/configuration/linux-kernel.chapter.md
@@ -84,26 +84,7 @@ available parameters, run `sysctl -a`.
 
 ## Building a custom kernel {#sec-linux-config-customizing}
 
-You can customize the default kernel configuration by overriding the arguments for your kernel package:
-
-```nix
-pkgs.linux_latest.override {
-  ignoreConfigErrors = true;
-  autoModules = false;
-  kernelPreferBuiltin = true;
-  extraStructuredConfig = with lib.kernel; {
-    DEBUG_KERNEL = yes;
-    FRAME_POINTER = yes;
-    KGDB = yes;
-    KGDB_SERIAL_CONSOLE = yes;
-    DEBUG_INFO = yes;
-  };
-}
-```
-
-See `pkgs/os-specific/linux/kernel/generic.nix` for details on how these arguments
-affect the generated configuration. You can also build a custom version of Linux by calling
-`pkgs.buildLinux` directly, which requires the `src` and `version` arguments to be specified.
+Please refer to the Nixpkgs manual for the various ways of [building a custom kernel](https://nixos.org/nixpkgs/manual#sec-linux-kernel).
 
 To use your custom kernel package in your NixOS configuration, set
 
@@ -111,50 +92,9 @@ To use your custom kernel package in your NixOS configuration, set
 boot.kernelPackages = pkgs.linuxPackagesFor yourCustomKernel;
 ```
 
-Note that this method will use the common configuration defined in `pkgs/os-specific/linux/kernel/common-config.nix`,
-which is suitable for a NixOS system.
-
-If you already have a generated configuration file, you can build a kernel that uses it with `pkgs.linuxManualConfig`:
-
-```nix
-let
-  baseKernel = pkgs.linux_latest;
-in pkgs.linuxManualConfig {
-  inherit (baseKernel) src modDirVersion;
-  version = "${baseKernel.version}-custom";
-  configfile = ./my_kernel_config;
-  allowImportFromDerivation = true;
-}
-```
-
-::: {.note}
-The build will fail if `modDirVersion` does not match the source's `kernel.release` file,
-so `modDirVersion` should remain tied to `src`.
-:::
-
-To edit the `.config` file for Linux X.Y, proceed as follows:
-
-```ShellSession
-$ nix-shell '<nixpkgs>' -A linuxKernel.kernels.linux_X_Y.configEnv
-$ unpackPhase
-$ cd linux-*
-$ make nconfig
-```
-
 ## Developing kernel modules {#sec-linux-config-developing-modules}
 
-When developing kernel modules it's often convenient to run
-edit-compile-run loop as quickly as possible. See below snippet as an
-example of developing `mellanox` drivers.
-
-```ShellSession
-$ nix-build '<nixpkgs>' -A linuxPackages.kernel.dev
-$ nix-shell '<nixpkgs>' -A linuxPackages.kernel
-$ unpackPhase
-$ cd linux-*
-$ make -C $dev/lib/modules/*/build M=$(pwd)/drivers/net/ethernet/mellanox modules
-# insmod ./drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.ko
-```
+This section was moved to the [Nixpkgs manual](https://nixos.org/nixpkgs/manual#sec-linux-kernel-developing-modules).
 
 ## ZFS {#sec-linux-zfs}
 
@@ -163,7 +103,7 @@ available Linux kernel. It is recommended to use the latest available LTS that's
 with ZFS. Usually this is the default kernel provided by nixpkgs (i.e. `pkgs.linuxPackages`).
 
 Alternatively, it's possible to pin the system to the latest available kernel
-version *that is supported by ZFS* like this:
+version _that is supported by ZFS_ like this:
 
 ```nix
 {
diff --git a/nixpkgs/nixos/doc/manual/installation/upgrading.chapter.md b/nixpkgs/nixos/doc/manual/installation/upgrading.chapter.md
index d39e1b786d83..79cd4e55be5c 100644
--- a/nixpkgs/nixos/doc/manual/installation/upgrading.chapter.md
+++ b/nixpkgs/nixos/doc/manual/installation/upgrading.chapter.md
@@ -6,7 +6,7 @@ expressions and associated binaries. The NixOS channels are updated
 automatically from NixOS's Git repository after certain tests have
 passed and all packages have been built. These channels are:
 
--   *Stable channels*, such as [`nixos-23.05`](https://channels.nixos.org/nixos-23.05).
+-   *Stable channels*, such as [`nixos-23.11`](https://channels.nixos.org/nixos-23.11).
     These only get conservative bug fixes and package upgrades. For
     instance, a channel update may cause the Linux kernel on your system
     to be upgraded from 4.19.34 to 4.19.38 (a minor bug fix), but not
@@ -19,7 +19,7 @@ passed and all packages have been built. These channels are:
     radical changes between channel updates. It's not recommended for
     production systems.
 
--   *Small channels*, such as [`nixos-23.05-small`](https://channels.nixos.org/nixos-23.05-small)
+-   *Small channels*, such as [`nixos-23.11-small`](https://channels.nixos.org/nixos-23.11-small)
     or [`nixos-unstable-small`](https://channels.nixos.org/nixos-unstable-small).
     These are identical to the stable and unstable channels described above,
     except that they contain fewer binary packages. This means they get updated
@@ -38,8 +38,8 @@ newest supported stable release.
 
 When you first install NixOS, you're automatically subscribed to the
 NixOS channel that corresponds to your installation source. For
-instance, if you installed from a 23.05 ISO, you will be subscribed to
-the `nixos-23.05` channel. To see which NixOS channel you're subscribed
+instance, if you installed from a 23.11 ISO, you will be subscribed to
+the `nixos-23.11` channel. To see which NixOS channel you're subscribed
 to, run the following as root:
 
 ```ShellSession
@@ -54,16 +54,16 @@ To switch to a different NixOS channel, do
 ```
 
 (Be sure to include the `nixos` parameter at the end.) For instance, to
-use the NixOS 23.05 stable channel:
+use the NixOS 23.11 stable channel:
 
 ```ShellSession
-# nix-channel --add https://channels.nixos.org/nixos-23.05 nixos
+# nix-channel --add https://channels.nixos.org/nixos-23.11 nixos
 ```
 
 If you have a server, you may want to use the "small" channel instead:
 
 ```ShellSession
-# nix-channel --add https://channels.nixos.org/nixos-23.05-small nixos
+# nix-channel --add https://channels.nixos.org/nixos-23.11-small nixos
 ```
 
 And if you want to live on the bleeding edge:
@@ -114,5 +114,5 @@ the new generation contains a different kernel, initrd or kernel
 modules. You can also specify a channel explicitly, e.g.
 
 ```nix
-system.autoUpgrade.channel = "https://channels.nixos.org/nixos-23.05";
+system.autoUpgrade.channel = "https://channels.nixos.org/nixos-23.11";
 ```
diff --git a/nixpkgs/nixos/doc/manual/release-notes/rl-2311.section.md b/nixpkgs/nixos/doc/manual/release-notes/rl-2311.section.md
index e2853569423d..760c58d5050e 100644
--- a/nixpkgs/nixos/doc/manual/release-notes/rl-2311.section.md
+++ b/nixpkgs/nixos/doc/manual/release-notes/rl-2311.section.md
@@ -1,244 +1,254 @@
-# Release 23.11 (“Tapir”, 2023.11/??) {#sec-release-23.11}
-
-## Highlights {#sec-release-23.11-highlights}
-
-- FoundationDB now defaults to major version 7.
-
-- PostgreSQL now defaults to major version 15.
-
-- Support for WiFi6 (IEEE 802.11ax) and WPA3-SAE-PK was enabled in the `hostapd` package, along with a significant rework of the hostapd module.
-
-- LXD now supports virtual machine instances to complement the existing container support
-
-- The `nixos-rebuild` command has been given a `list-generations` subcommand. See `man nixos-rebuild` for more details.
-
-- [systemd](https://systemd.io) has been updated from v253 to v254, see [the release notes](https://github.com/systemd/systemd/blob/v254/NEWS#L3-L659) for more information on the changes.
-    - `boot.resumeDevice` **must be specified** when hibernating if not in EFI mode.
-    - systemd may warn your system about the permissions of your ESP partition (often `/boot`), this warning can be ignored for now, we are looking
-      into a satisfying solution regarding this problem.
-    - Updating with `nixos-rebuild boot` and rebooting is recommended, since in some rare cases the `nixos-rebuild switch` into the new generation on a live system might fail due to missing mount units.
-
-- [`sudo-rs`], a reimplementation of `sudo` in Rust, is now supported.
-  An experimental new module `security.sudo-rs` was added.
-  Switching to it (via `security.sudo.enable = false; security.sudo-rs.enable = true;`) introduces
-  slight changes in sudo behaviour, due to `sudo-rs`' current limitations:
-  - terminfo-related environment variables aren't preserved for `root` and `wheel`;
-  - `root` and `wheel` are not given the ability to set (or preserve)
-    arbitrary environment variables.
-
-- [glibc](https://www.gnu.org/software/libc/) has been updated from version 2.37 to 2.38, see [the release notes](https://sourceware.org/glibc/wiki/Release/2.38) for what was changed.
-
-[`sudo-rs`]: https://github.com/memorysafety/sudo-rs/
-
-- `linuxPackages_testing_bcachefs` is now soft-deprecated by `linuxPackages_testing`.
-  - Please consider changing your NixOS configuration's `boot.kernelPackages` to `linuxPackages_testing` until a stable kernel with bcachefs support is released.
-
-- All [ROCm](https://rocm.docs.amd.com/en/latest/) packages have been updated to 5.7.0.
-  - [ROCm](https://rocm.docs.amd.com/en/latest/) package attribute sets are versioned: `rocmPackages` -> `rocmPackages_5`.
-
-- `yarn-berry` has been updated to 4.0.1. This means that NodeJS versions less than `18.12` are no longer supported by it. More details at the [upstream changelog](https://github.com/yarnpkg/berry/blob/master/CHANGELOG.md).
-
-- If the user has a custom shell enabled via `users.users.${USERNAME}.shell = ${CUSTOMSHELL}`, the
-  assertion will require them to also set `programs.${CUSTOMSHELL}.enable =
-  true`. This is generally safe behavior, but for anyone needing to opt out from
-  the check `users.users.${USERNAME}.ignoreShellProgramCheck = true` will do the job.
-
-- Cassandra now defaults to 4.x, updated from 3.11.x.
-
-## New Services {#sec-release-23.11-new-services}
-
-- [MCHPRS](https://github.com/MCHPR/MCHPRS), a multithreaded Minecraft server built for redstone. Available as [services.mchprs](#opt-services.mchprs.enable).
-
-- [acme-dns](https://github.com/joohoi/acme-dns), a limited DNS server to handle ACME DNS challenges easily and securely. Available as [services.acme-dns](#opt-services.acme-dns.enable).
-
-- [frp](https://github.com/fatedier/frp), a fast reverse proxy to help you expose a local server behind a NAT or firewall to the Internet. Available as [services.frp](#opt-services.frp.enable).
-
-<!-- To avoid merge conflicts, consider adding your item at an arbitrary place in the list instead. -->
-
-- [river](https://github.com/riverwm/river), A dynamic tiling wayland compositor. Available as [programs.river](#opt-programs.river.enable).
-
-- [wayfire](https://wayfire.org), A modular and extensible wayland compositor. Available as [programs.wayfire](#opt-programs.wayfire.enable).
-
-- [mautrix-whatsapp](https://docs.mau.fi/bridges/go/whatsapp/index.html) A Matrix-WhatsApp puppeting bridge
-
-- [hddfancontrol](https://github.com/desbma/hddfancontrol), a service to regulate fan speeds based on hard drive temperature. Available as [services.hddfancontrol](#opt-services.hddfancontrol.enable).
-
-- [GoToSocial](https://gotosocial.org/), an ActivityPub social network server, written in Golang. Available as [services.gotosocial](#opt-services.gotosocial.enable).
-
-- [Castopod](https://castopod.org/), an open-source hosting platform made for podcasters who want to engage and interact with their audience. Available as [services.castopod](#opt-services.castopod.enable).
-
-- [Typesense](https://github.com/typesense/typesense), a fast, typo-tolerant search engine for building delightful search experiences. Available as [services.typesense](#opt-services.typesense.enable).
-
-* [NS-USBLoader](https://github.com/developersu/ns-usbloader/), an all-in-one tool for managing Nintendo Switch homebrew. Available as [programs.ns-usbloader](#opt-programs.ns-usbloader.enable).
-
-- [Mobilizon](https://joinmobilizon.org/), a Fediverse platform for publishing events.
-
-- [Anuko Time Tracker](https://github.com/anuko/timetracker), a simple, easy to use, open source time tracking system. Available as [services.anuko-time-tracker](#opt-services.anuko-time-tracker.enable).
-
-- [Prometheus MySQL exporter](https://github.com/prometheus/mysqld_exporter), a MySQL server exporter for Prometheus. Available as [services.prometheus.exporters.mysqld](#opt-services.prometheus.exporters.mysqld.enable).
-
-- [LibreNMS](https://www.librenms.org), a auto-discovering PHP/MySQL/SNMP based network monitoring. Available as [services.librenms](#opt-services.librenms.enable).
-
-- [Livebook](https://livebook.dev/), an interactive notebook with support for Elixir, graphs, machine learning, and more.
-
-- [sitespeed-io](https://sitespeed.io), a tool that can generate metrics (timings, diagnostics) for websites. Available as [services.sitespeed-io](#opt-services.sitespeed-io.enable).
-
-- [stalwart-mail](https://stalw.art), an all-in-one email server (SMTP, IMAP, JMAP). Available as [services.stalwart-mail](#opt-services.stalwart-mail.enable).
-
-- [tang](https://github.com/latchset/tang), a server for binding data to network presence. Available as [services.tang](#opt-services.tang.enable).
-
-- [Jool](https://nicmx.github.io/Jool/en/index.html), a kernelspace NAT64 and SIIT implementation, providing translation between IPv4 and IPv6. Available as [networking.jool.enable](#opt-networking.jool.enable).
-
-- [Home Assistant Satellite], a streaming audio satellite for Home Assistant voice pipelines, where you can reuse existing mic/speaker hardware. Available as [services.homeassistant-satellite](#opt-services.homeassistant-satellite.enable).
-
-- [Apache Guacamole](https://guacamole.apache.org/), a cross-platform, clientless remote desktop gateway. Available as [services.guacamole-server](#opt-services.guacamole-server.enable) and [services.guacamole-client](#opt-services.guacamole-client.enable) services.
-
-- [pgBouncer](https://www.pgbouncer.org), a PostgreSQL connection pooler. Available as [services.pgbouncer](#opt-services.pgbouncer.enable).
-
-- [Goss](https://goss.rocks/), a YAML based serverspec alternative tool for validating a server's configuration. Available as [services.goss](#opt-services.goss.enable).
-
-- [trust-dns](https://trust-dns.org/), a Rust based DNS server built to be safe and secure from the ground up. Available as [services.trust-dns](#opt-services.trust-dns.enable).
-
-- [osquery](https://www.osquery.io/), a SQL powered operating system instrumentation, monitoring, and analytics.
-
-- [ebusd](https://ebusd.eu), a daemon for handling communication with eBUS devices connected to a 2-wire bus system (“energy bus” used by numerous heating systems). Available as [services.ebusd](#opt-services.ebusd.enable).
-
-- [systemd-sysupdate](https://www.freedesktop.org/software/systemd/man/systemd-sysupdate.html), atomically updates the host OS, container images, portable service images or other sources. Available as [systemd.sysupdate](opt-systemd.sysupdate).
-
-- [eris-server](https://codeberg.org/eris/eris-go). [ERIS](https://eris.codeberg.page/) is an encoding for immutable storage and this server provides block exchange as well as content decoding over HTTP and through a FUSE file-system. Available as [services.eris-server](#opt-services.eris-server.enable).
-
-- [forgejo](https://forgejo.org/), a git forge. Previously deployed as a drop-in replacement package in the [gitea module](#opt-services.gitea.package). Available as [services.forgejo](#opt-services.forgejo.enable). See migration instructions in the [NixOS manual](#module-forgejo) on how to migrate your forgejo instance using [`services.gitea.package = pkgs.forgejo`](#opt-services.gitea.package) to [`services.forgejo`](#opt-services.forgejo.enable).
-
-- hardware/infiniband.nix adds infiniband subnet manager support using an [opensm](https://github.com/linux-rdma/opensm) systemd-template service, instantiated on card guids. The module also adds kernel modules and cli tooling to help administrators debug and measure performance. Available as [hardware.infiniband.enable](#opt-hardware.infiniband.enable).
-
-- [zwave-js](https://github.com/zwave-js/zwave-js-server), a small server wrapper around Z-Wave JS to access it via a WebSocket. Available as [services.zwave-js](#opt-services.zwave-js.enable).
-
-- [Honk](https://humungus.tedunangst.com/r/honk), a complete ActivityPub server with minimal setup and support costs.
-  Available as [services.honk](#opt-services.honk.enable).
-
-- [ferretdb](https://www.ferretdb.io/), an open-source proxy, converting the MongoDB 6.0+ wire protocol queries to PostgreSQL or SQLite. Available as [services.ferretdb](options.html#opt-services.ferretdb.enable).
-
-- [MicroBin](https://microbin.eu/), a feature rich, performant and secure text and file sharing web application, a "paste bin". Available as [services.microbin](#opt-services.microbin.enable).
-
-- [NNCP](http://www.nncpgo.org/). Added nncp-daemon and nncp-caller services. Configuration is set with [programs.nncp.settings](#opt-programs.nncp.settings) and the daemons are enabled at [services.nncp](#opt-services.nncp.caller.enable).
-
-- [FastNetMon Advanced](https://fastnetmon.com/product-overview/), a commercial high performance DDoS detector / sensor. Available as [services.fastnetmon-advanced](#opt-services.fastnetmon-advanced.enable).
-
-- [tuxedo-rs](https://github.com/AaronErhardt/tuxedo-rs), Rust utilities for interacting with hardware from TUXEDO Computers.
-
-- [certspotter](https://github.com/SSLMate/certspotter), a certificate transparency log monitor. Available as [services.certspotter](#opt-services.certspotter.enable).
-
-- [audiobookshelf](https://github.com/advplyr/audiobookshelf/), a self-hosted audiobook and podcast server. Available as [services.audiobookshelf](#opt-services.audiobookshelf.enable).
-
-- [ZITADEL](https://zitadel.com), a turnkey identity and access management platform. Available as [services.zitadel](#opt-services.zitadel.enable).
-
-- [exportarr](https://github.com/onedr0p/exportarr), Prometheus Exporters for Bazarr, Lidarr, Prowlarr, Radarr, Readarr, and Sonarr. Available as [services.prometheus.exporters.exportarr-bazarr](#opt-services.prometheus.exporters.exportarr-bazarr.enable)/[services.prometheus.exporters.exportarr-lidarr](#opt-services.prometheus.exporters.exportarr-lidarr.enable)/[services.prometheus.exporters.exportarr-prowlarr](#opt-services.prometheus.exporters.exportarr-prowlarr.enable)/[services.prometheus.exporters.exportarr-radarr](#opt-services.prometheus.exporters.exportarr-radarr.enable)/[services.prometheus.exporters.exportarr-readarr](#opt-services.prometheus.exporters.exportarr-readarr.enable)/[services.prometheus.exporters.exportarr-sonarr](#opt-services.prometheus.exporters.exportarr-sonarr.enable).
-
-- [netclient](https://github.com/gravitl/netclient), an automated WireGuard® Management Client. Available as [services.netclient](#opt-services.netclient.enable).
-
-- [trunk-ng](https://github.com/ctron/trunk), A fork of `trunk`: Build, bundle & ship your Rust WASM application to the web
-
-- [virt-manager](https://virt-manager.org/), an UI for managing virtual machines in libvirt, is now available as `programs.virt-manager`.
-
-- [Soft Serve](https://github.com/charmbracelet/soft-serve), a tasty, self-hostable Git server for the command line. Available as [services.soft-serve](#opt-services.soft-serve.enable).
-
-- [Rosenpass](https://rosenpass.eu/), a service for post-quantum-secure VPNs with WireGuard. Available as [services.rosenpass](#opt-services.rosenpass.enable).
-
-- [c2FmZQ](https://github.com/c2FmZQ/c2FmZQ/), an application that can securely encrypt, store, and share files, including but not limited to pictures and videos. Available as [services.c2fmzq-server](#opt-services.c2fmzq-server.enable).
-
-## Backward Incompatibilities {#sec-release-23.11-incompatibilities}
-
-- `services.postgresql.ensurePermissions` has been deprecated in favor of `services.postgresql.ensureUsers.*.ensureDBOwnership` which simplifies the setup of database owned by a certain system user
-  in local database contexts (which make use of peer authentication via UNIX sockets), migration guidelines were provided in the NixOS manual, please refer to them if you are affected by a PostgreSQL 15 changing the way `GRANT ALL PRIVILEGES` is working. `services.postgresql.ensurePermissions` will be removed in 24.05. All NixOS modules were migrated using one of the strategy, e.g. `ensureDBOwnership` or `postStart`. More about this situation can be learnt in https://github.com/NixOS/nixpkgs/pull/266270.
-
-- `network-online.target` has been fixed to no longer time out for systems with `networking.useDHCP = true` and `networking.useNetworkd = true`.
-  Workarounds for this can be removed.
-
-- The `boot.loader.raspberryPi` options have been marked deprecated, with intent for removal for NixOS 24.11. They had a limited use-case, and do not work like people expect. They required either very old installs ([before mid-2019](https://github.com/NixOS/nixpkgs/pull/62462)) or customized builds out of scope of the standard and generic AArch64 support. That option set never supported the Raspberry Pi 4 family of devices.
-
-- `python3.pkgs.sequoia` was removed in favor of `python3.pkgs.pysequoia`. The latter package is based on upstream's dedicated repository for sequoia's Python bindings, where the Python bindings from [gitlab:sequoia-pgp/sequoia](https://gitlab.com/sequoia-pgp/sequoia) were removed long ago.
-
-- `writeTextFile` now requires `executable` to be boolean, values like `null` or `""` will now fail to evaluate.
-
-- The latest version of `clonehero` now stores custom content in `~/.clonehero`. See the [migration instructions](https://clonehero.net/2022/11/29/v23-to-v1-migration-instructions.html). Typically, these content files would exist along side the binary, but the previous build used a wrapper script that would store them in `~/.config/unity3d/srylain Inc_/Clone Hero`.
-
-- `services.mastodon` doesn't support providing a TCP port to its `streaming` component anymore, as upstream implemented parallelization by running multiple instances instead of running multiple processes in one instance. Please create a PR if you are interested in this feature.
-
-- The `services.hostapd` module was rewritten to support `passwordFile` like options, WPA3-SAE, and management of multiple interfaces. This breaks compatibility with older configurations.
-  - `hostapd` is now started with additional systemd sandbox/hardening options for better security.
-  - `services.hostapd.interface` was replaced with a per-radio and per-bss configuration scheme using [services.hostapd.radios](#opt-services.hostapd.radios).
-  - `services.hostapd.wpa` has been replaced by [services.hostapd.radios.&lt;name&gt;.networks.&lt;name&gt;.authentication.wpaPassword](#opt-services.hostapd.radios._name_.networks._name_.authentication.wpaPassword) and [services.hostapd.radios.&lt;name&gt;.networks.&lt;name&gt;.authentication.saePasswords](#opt-services.hostapd.radios._name_.networks._name_.authentication.saePasswords) which configure WPA2-PSK and WP3-SAE respectively.
-  - The default authentication has been changed to WPA3-SAE. Options for other (legacy) schemes are still available.
-
-- `python3.pkgs.fetchPypi` (and `python3Packages.fetchPypi`) has been deprecated in favor of top-level `fetchPypi`.
-
-- `pass` now does not contain `password-store.el`.  Users should get `password-store.el` from Emacs lisp package set `emacs.pkgs.password-store`.
-
-- `services.knot` now supports `.settings` from RFC42.  The previous `.extraConfig` still works the same, but it displays a warning now.
-
-- `mu` now does not install `mu4e` files by default.  Users should get `mu4e` from Emacs lisp package set `emacs.pkgs.mu4e`.
-
-- `mariadb` now defaults to `mariadb_1011` instead of `mariadb_106`, meaning the default version was upgraded from 10.6.x to 10.11.x. See the [upgrade notes](https://mariadb.com/kb/en/upgrading-from-mariadb-10-6-to-mariadb-10-11/) for potential issues.
-
-- `getent` has been moved from `glibc`'s `bin` output to its own dedicated output, reducing closure size for many dependents. Dependents using the `getent` alias should not be affected; others should move from using `glibc.bin` or `getBin glibc` to `getent` (which also improves compatibility with non-glibc platforms).
+# Release 23.11 (“Tapir”, 2023.11/29) {#sec-release-23.11}
+
+The NixOS release team is happy to announce a new version of NixOS. The release is called NixOS 23.11 ("Tapir").
+
+NixOS is a Linux distribution, whose set of packages can also be used on other Linux systems and macOS.
+
+Support is planned until the end of June 2024, handing over to NixOS 24.05.
+
+To upgrade to the latest release, follow the upgrade chapter and check the [Breaking Changes](#sec-release-23.11-nixos-breaking-changes)
+section for packages and services used in your configuration.
+
+The team is excited about the many software updates and improvements in this release. Just to name a few, do check the updates
+for `GNOME` packages, `systemd`, `glibc`, the `ROCM` package set, and `hostapd` (which brings support for WiFi6 (IEEE 802.11ax) and WPA3-SAE-PK).
+
+Make sure to also check the many updates in the [Nixpkgs library](#sec-release-23.11-nixpkgs-lib) when developing your own packages.
+
+## Table of Contents {#sec-release-23.11-toc}
+
+- [NixOS](#sec-release-23.11-nixos)
+  - [Breaking Changes](#sec-release-23.11-nixos-breaking-changes)
+  - [New Services](#sec-release-23.11-nixos-new-services)
+  - [Other Notable Changes](#sec-release-23.11-nixos-notable-changes)
+- [Nixpkgs Library Changes](#sec-release-23.11-nixpkgs-lib)
+  - [Breaking Changes](#sec-release-23.11-lib-breaking)
+  - [Additions and Improvements](#sec-release-23.11-lib-additions-improvements)
+  - [Deprecations](#sec-release-23.11-lib-deprecations)
+
+## NixOS {#sec-release-23.11-nixos}
+
+
+### Breaking Changes {#sec-release-23.11-nixos-breaking-changes}
+
+- `services.postgresql.ensurePermissions` has been deprecated in favor of
+  `services.postgresql.ensureUsers.*.ensureDBOwnership` which simplifies the
+  setup of database owned by a certain system user in local database contexts
+  (which make use of peer authentication via UNIX sockets), migration
+  guidelines were provided in the NixOS manual, please refer to them if you are
+  affected by a PostgreSQL 15 changing the way `GRANT ALL PRIVILEGES` is
+  working. `services.postgresql.ensurePermissions` will be removed in 24.05.
+  All NixOS modules were migrated using one of the strategy, e.g.
+  `ensureDBOwnership` or `postStart`. Refer to the [PR
+  #266270](https://github.com/NixOS/nixpkgs/pull/266270) for more details.
+
+- `network-online.target` has been fixed to no longer time out for systems with
+  `networking.useDHCP = true` and `networking.useNetworkd = true`. Workarounds
+  for this can be removed.
+
+- The `boot.loader.raspberryPi` options have been marked deprecated, with
+  intent of removal for NixOS 24.11. They had a limited use-case, and do not
+  work like people expect. They required either very old installs from ([before
+  mid-2019](https://github.com/NixOS/nixpkgs/pull/62462)) or customized builds
+  out of scope of the standard and generic AArch64 support. That option set
+  never supported the Raspberry Pi 4 family of devices.
+
+- `python3.pkgs.sequoia` was removed in favor of `python3.pkgs.pysequoia`. The
+  latter package is based on upstream's dedicated repository for sequoia's
+  Python bindings, where the Python bindings from
+  [gitlab:sequoia-pgp/sequoia](https://gitlab.com/sequoia-pgp/sequoia) were
+  removed long ago.
+
+- `writeTextFile` requires `executable` to be boolean now, values like `null`
+  or `""` will fail to evaluate now.
+
+- The latest version of `clonehero` now stores custom content in
+  `~/.clonehero`. Refer to the [migration
+  instructions](https://clonehero.net/2022/11/29/v23-to-v1-migration-instructions.html)
+  for more details. Typically, these content files would exist along side the
+  binary, but the previous build used a wrapper script that would store them in
+  `~/.config/unity3d/srylain Inc_/Clone Hero`.
+
+- `services.mastodon` doesn't support providing a TCP port to its `streaming`
+  component anymore, as upstream implemented parallelization by running
+  multiple instances instead of running multiple processes in one instance.
+  Please create a PR if you are interested in this feature.
+
+- The `services.hostapd` module was rewritten to support `passwordFile` like
+  options, WPA3-SAE, and management of multiple interfaces. This breaks
+  compatibility with older configurations.
+  - `hostapd` is now started with additional systemd sandbox/hardening options
+    for better security.
+  - `services.hostapd.interface` was replaced with a per-radio and per-bss
+    configuration scheme using
+    [services.hostapd.radios](#opt-services.hostapd.radios).
+  - `services.hostapd.wpa` has been replaced by
+    [services.hostapd.radios.&lt;name&gt;.networks.&lt;name&gt;.authentication.wpaPassword](#opt-services.hostapd.radios._name_.networks._name_.authentication.wpaPassword)
+    and
+    [services.hostapd.radios.&lt;name&gt;.networks.&lt;name&gt;.authentication.saePasswords](#opt-services.hostapd.radios._name_.networks._name_.authentication.saePasswords)
+    which configure WPA2-PSK and WP3-SAE respectively.
+  - The default authentication has been changed to WPA3-SAE. Options for other
+    (legacy) schemes are still available.
+
+- `python3.pkgs.fetchPypi` and `python3Packages.fetchPypi` have been
+  deprecated in favor of top-level `fetchPypi`.
+
+- xdg-desktop-portal has been updated to 1.18, which reworked how portal
+  implementations are selected. If you roll your own desktop environment, you
+  should either set `xdg.portal.config` or `xdg.portal.configPackages`, which
+  allow fine-grained control over which portal backend to use for specific
+  interfaces, as described in {manpage}`portals.conf(5)`.
+
+  If you don't provide configurations, a portal backend will only be considered
+  when the desktop you use matches its deprecated `UseIn` key. While some NixOS
+  desktop modules should already ship one for you, it is suggested to test
+  portal availability by trying [Door
+  Knocker](https://flathub.org/apps/xyz.tytanium.DoorKnocker) and [ASHPD
+  Demo](https://flathub.org/apps/com.belmoussaoui.ashpd.demo). If things
+  regressed, you may run `G_MESSAGES_DEBUG=all
+  /path/to/xdg-desktop-portal/libexec/xdg-desktop-portal` for ideas on which
+  config file and which portals are chosen.
+
+- `pass` now does not contain `password-store.el`. Users should get
+  `password-store.el` from Emacs lisp package set `emacs.pkgs.password-store`.
+
+- `services.knot` now supports `.settings` from RFC42.  The previous
+  `.extraConfig` still works the same, but it displays a warning now.
+
+- `services.invoiceplane` now supports `.settings` from RFC42. The previous
+  `.extraConfig` still works the same way, but it displays a warning now.
+
+- `mu` does not install `mu4e` files by default now. Users should get `mu4e`
+  from Emacs lisp package set `emacs.pkgs.mu4e`.
+
+- `mariadb` now defaults to `mariadb_1011` instead of `mariadb_106`, meaning
+  the default version was upgraded from v10.6.x to v10.11.x. Refer to the
+  [upgrade
+  notes](https://mariadb.com/kb/en/upgrading-from-mariadb-10-6-to-mariadb-10-11/)
+  for potential issues.
+
+- `getent` has been moved from `glibc`'s `bin` output to its own dedicated
+  output, reducing closure size for many dependents. Dependents using the
+  `getent` alias should not be affected; others should move from using
+  `glibc.bin` or `getBin glibc` to `getent` (which also improves compatibility
+  with non-glibc platforms).
 
 - `maintainers/scripts/update-luarocks-packages` is now a proper package
   `luarocks-packages-updater` that can be run to maintain out-of-tree luarocks
-  packages
+  packages.
 
-- The `users.users.<name>.passwordFile` has been renamed to `users.users.<name>.hashedPasswordFile` to avoid possible confusions. The option is in fact the file-based version of `hashedPassword`, not `password`, and expects a file containing the {manpage}`crypt(3)` hash of the user password.
+- The `users.users.<name>.passwordFile` has been renamed to
+  `users.users.<name>.hashedPasswordFile` to avoid possible confusions. The
+  option is in fact the file-based version of `hashedPassword`, not `password`,
+  and expects a file containing the {manpage}`crypt(3)` hash of the user
+  password.
 
-- `chromiumBeta` and `chromiumDev` have been removed due to the lack of maintenance in nixpkgs. Consider using `chromium` instead.
+- `chromiumBeta` and `chromiumDev` have been removed due to the lack of
+  maintenance in nixpkgs. Consider using `chromium` instead.
 
-- `google-chrome-beta` and `google-chrome-dev` have been removed due to the lack of maintenance in nixpkgs. Consider using `google-chrome` instead.
+- `google-chrome-beta` and `google-chrome-dev` have been removed due to the
+  lack of maintenance in nixpkgs. Consider using `google-chrome` instead.
 
-- The `services.ananicy.extraRules` option now has the type of `listOf attrs` instead of `string`.
+- The `services.ananicy.extraRules` option now has the type of `listOf attrs`
+  instead of `string`.
 
 - `buildVimPluginFrom2Nix` has been renamed to `buildVimPlugin`, which now
-  now skips `configurePhase` and `buildPhase`
-
-- JACK tools (`jack_*` except `jack_control`) have moved from the `jack2` package to `jack-example-tools`
-
-- The `waagent` service does provisioning now
-
-- The `matrix-synapse` package & module have undergone some significant internal changes, for most setups no intervention is needed, though:
-  - The option [`services.matrix-synapse.package`](#opt-services.matrix-synapse.package) is now read-only. For modifying the package, use an overlay which modifies `matrix-synapse-unwrapped` instead. More on that below.
-  - The `enableSystemd` & `enableRedis` arguments have been removed and `matrix-synapse` has been renamed to `matrix-synapse-unwrapped`. Also, several optional dependencies (such as `psycopg2` or `authlib`) have been removed.
-  - These optional dependencies are automatically added via a wrapper (`pkgs.matrix-synapse.override { extras = ["redis"]; }` for `hiredis` & `txredisapi` for instance) if the relevant config section is declared in `services.matrix-synapse.settings`. For instance, if `services.matrix-synapse.settings.redis.enabled` is set to `true`, `"redis"` will be automatically added to the `extras` list of `pkgs.matrix-synapse`.
-  - A list of all extras (and the extras enabled by default) can be found at the [option's reference for `services.matrix-synapse.extras`](#opt-services.matrix-synapse.extras).
-  - In some cases (e.g. for running synapse workers) it was necessary to re-use the `PYTHONPATH` of `matrix-synapse.service`'s environment to have all plugins available. This isn't necessary anymore, instead `config.services.matrix-synapse.package` can be used as it points to the wrapper with properly configured `extras` and also all plugins defined via [`services.matrix-synapse.plugins`](#opt-services.matrix-synapse.plugins) available. This is also the reason for why the option is read-only now, it's supposed to be set by the module only.
-
-- `netbox` was updated to 3.6. NixOS' `services.netbox.package` still defaults to 3.5 if `stateVersion` is earlier than 23.11. Please review upstream's breaking changes [for 3.6.0](https://github.com/netbox-community/netbox/releases/tag/v3.6.0) and upgrade NetBox by changing `services.netbox.package`. Database migrations will be run automatically.
-
-- `etcd` has been updated to 3.5, you will want to read the [3.3 to 3.4](https://etcd.io/docs/v3.5/upgrades/upgrade_3_4/) and [3.4 to 3.5](https://etcd.io/docs/v3.5/upgrades/upgrade_3_5/) upgrade guides
-
-- `gitlab` installations created or updated between versions \[15.11.0, 15.11.2] have an incorrect database schema. This will become a problem when upgrading to `gitlab` >=16.2.0. A workaround for affected users can be found in the [GitLab docs](https://docs.gitlab.com/ee/update/versions/gitlab_16_changes.html#undefined-column-error-upgrading-to-162-or-later).
-
-- `consul` has been updated to `1.16.0`. See the [release note](https://github.com/hashicorp/consul/releases/tag/v1.16.0) for more details. Once a new Consul version has started and upgraded its data directory, it generally cannot be downgraded to the previous version.
+  now skips `configurePhase` and `buildPhase`.
+
+- JACK tools (`jack_*` except `jack_control`) have moved from the `jack2`
+  package to `jack-example-tools`.
+
+- The `waagent` service does provisioning now.
+
+- The `matrix-synapse` package & module have undergone some significant
+  internal changes, for most setups no intervention is needed, though:
+  - The option
+    [`services.matrix-synapse.package`](#opt-services.matrix-synapse.package)
+    is read-only now. For modifying the package, use an overlay which modifies
+    `matrix-synapse-unwrapped` instead. More on that below.
+  - The `enableSystemd` & `enableRedis` arguments have been removed and
+    `matrix-synapse` has been renamed to `matrix-synapse-unwrapped`. Also,
+    several optional dependencies (such as `psycopg2` or `authlib`) have been
+    removed.
+  - These optional dependencies are automatically added via a wrapper
+    (`pkgs.matrix-synapse.override { extras = ["redis"]; }` for `hiredis` &
+    `txredisapi` for instance) if the relevant config section is declared in
+    `services.matrix-synapse.settings`. For instance, if
+    `services.matrix-synapse.settings.redis.enabled` is set to `true`,
+    `"redis"` will be automatically added to the `extras` list of
+    `pkgs.matrix-synapse`.
+  - A list of all extras (and the extras enabled by default) can be found at
+    the [option's reference for
+    `services.matrix-synapse.extras`](#opt-services.matrix-synapse.extras).
+  - In some cases (e.g. for running synapse workers) it was necessary to re-use
+    the `PYTHONPATH` of `matrix-synapse.service`'s environment to have all
+    plugins available. This isn't necessary anymore, instead
+    `config.services.matrix-synapse.package` can be used as it points to the
+    wrapper with properly configured `extras` and also all plugins defined via
+    [`services.matrix-synapse.plugins`](#opt-services.matrix-synapse.plugins)
+    available. This is also the reason for why the option is read-only now,
+    it's supposed to be set by the module only.
+
+- `netbox` was updated to v3.6. `services.netbox.package` still defaults
+  to v3.5 if `stateVersion` is earlier than 23.11. Refer to upstream's breaking
+  changes [for
+  v3.6.0](https://github.com/netbox-community/netbox/releases/tag/v3.6.0) and
+  upgrade NetBox by changing `services.netbox.package`. Database migrations
+  will be run automatically.
+
+- `etcd` has been updated to v3.5. Refer to upgrade guides for [v3.3 to
+  v3.4](https://etcd.io/docs/v3.5/upgrades/upgrade_3_4/) and [v3.4 to
+  v3.5](https://etcd.io/docs/v3.5/upgrades/upgrade_3_5/) for more details.
+
+- `gitlab` installations created or updated between versions \[15.11.0,
+  15.11.2] have an incorrect database schema. This will become a problem when
+  upgrading to `gitlab` >=16.2.0. A workaround for affected users can be found
+  in the [GitLab
+  docs](https://docs.gitlab.com/ee/update/versions/gitlab_16_changes.html#undefined-column-error-upgrading-to-162-or-later).
+
+
+- `consul` has been updated to v1.16.0. Refer to the [release
+  note](https://github.com/hashicorp/consul/releases/tag/v1.16.0) for more
+  details. Once a new Consul version has started and upgraded it's data
+  directory, it generally cannot be downgraded to the previous version.
 
 - `llvmPackages_rocm` has been moved to `rocmPackages.llvm`.
 
-- `hip`, `rocm-opencl-runtime`, `rocm-opencl-icd`, and `rocclr` have been combined into `rocmPackages.clr`.
+- `hip`, `rocm-opencl-runtime`, `rocm-opencl-icd`, and `rocclr` have been
+  combined into `rocmPackages.clr`.
 
 - `clang-ocl`, `clr`, `composable_kernel`, `hipblas`, `hipcc`, `hip-common`, `hipcub`,
   `hipfft`, `hipfort`, `hipify`, `hipsolver`, `hipsparse`, `migraphx`, `miopen`, `miopengemm`,
   `rccl`, `rdc`, `rocalution`, `rocblas`, `rocdgbapi`, `rocfft`, `rocgdb`, `rocm-cmake`,
   `rocm-comgr`, `rocm-core`, `rocm-device-libs`, `rocminfo`, `rocmlir`, `rocm-runtime`,
   `rocm-smi`, `rocm-thunk`, `rocprim`, `rocprofiler`, `rocrand`, `rocr-debug-agent`,
-  `rocsolver`, `rocsparse`, `rocthrust`, `roctracer`, `rocwmma`, and `tensile` have been moved to `rocmPackages`.
-
-- `himalaya` has been updated to `0.8.0`, which drops the native TLS support (in favor of Rustls) and add OAuth 2.0 support. See the [release note](https://github.com/soywod/himalaya/releases/tag/v0.8.0) for more details.
-
-- `nix-prefetch-git` now ignores global and user git config, to improve reproducibility.
-
-- The [services.caddy.acmeCA](#opt-services.caddy.acmeCA) option now defaults to `null` instead of `"https://acme-v02.api.letsencrypt.org/directory"`, to use all of Caddy's default ACME CAs and enable Caddy's automatic issuer fallback feature by default, as recommended by upstream.
-
-- The default priorities of [`services.nextcloud.phpOptions`](#opt-services.nextcloud.phpOptions) have changed. This means that e.g.
-  `services.nextcloud.phpOptions."opcache.interned_strings_buffer" = "23";` doesn't discard all of the other defaults from this option
-  anymore. The attribute values of `phpOptions` are still defaults, these can be overridden as shown here.
-
-  To override all of the options (including including `upload_max_filesize`, `post_max_size`
-  and `memory_limit` which all point to [`services.nextcloud.maxUploadSize`](#opt-services.nextcloud.maxUploadSize)
+  `rocsolver`, `rocsparse`, `rocthrust`, `roctracer`, `rocwmma`, and `tensile`
+  have been moved to `rocmPackages`.
+
+- `himalaya` has been updated to v0.8.0, which drops the native TLS support
+  (in favor of Rustls) and add OAuth 2.0 support. Refer to the [release
+  note](https://github.com/soywod/himalaya/releases/tag/v0.8.0) for more
+  details.
+
+
+- `nix-prefetch-git` now ignores global and user git config, to improve
+  reproducibility.
+
+- The [services.caddy.acmeCA](#opt-services.caddy.acmeCA) option defaults
+  to `null` instead of `"https://acme-v02.api.letsencrypt.org/directory"` now.
+  To use all of Caddy's default ACME CAs and enable Caddy's automatic issuer
+  fallback feature by default, as recommended by upstream.
+
+- The default priorities of
+  [`services.nextcloud.phpOptions`](#opt-services.nextcloud.phpOptions) have
+  changed. This means that e.g.
+  `services.nextcloud.phpOptions."opcache.interned_strings_buffer" = "23";`
+  doesn't discard all of the other defaults from this option anymore. The
+  attribute values of `phpOptions` are still defaults, these can be overridden
+  as shown here.
+
+  To override all of the options (including including `upload_max_filesize`,
+  `post_max_size` and `memory_limit` which all point to
+  [`services.nextcloud.maxUploadSize`](#opt-services.nextcloud.maxUploadSize)
   by default) can be done like this:
 
   ```nix
@@ -249,279 +259,972 @@
   }
   ```
 
-- `php80` is no longer supported due to upstream not supporting this version anymore.
+- `php80` is no longer supported due to upstream not supporting this version
+  anymore.
 
-- PHP now defaults to PHP 8.2, updated from 8.1.
+- PHP defaults to PHP 8.2 now, updated from v8.1.
 
-- GraalVM has been updated to the latest version, and this brings significant changes. Upstream don't release multiple versions targeting different JVMs anymore, so now we only have one GraalVM derivation (`graalvm-ce`). While at first glance the version may seem a downgrade (22.3.1 -> 21.0.0), the major version is now following the JVM it targets (so this latest version targets JVM 21). Also some products like `llvm-installable-svm` and `native-image-svm` were incorporate to the main GraalVM derivation, so they're included by default.
+- GraalVM has been updated to the latest version, and this brings significant
+  changes. Upstream don't release multiple versions targeting different JVMs
+  anymore, so now we only have one GraalVM derivation (`graalvm-ce`). While at
+  first glance the version may seem a downgrade (v22.3.1 -> v21.0.0), the major
+  version is now following the JVM it targets (so this latest version targets
+  JVM 21). Also some products like `llvm-installable-svm` and
+  `native-image-svm` were incorporate to the main GraalVM derivation, so
+  they're included by default.
 
-- GraalPy (`graalCEPackages.graalpy`), TruffleRuby (`graalCEPackages.truffleruby`), GraalJS (`graalCEPackages.graaljs`) and GraalNodeJS (`grallCEPackages.graalnodejs`) are now indepedent from the main GraalVM derivation.
+- GraalPy (`graalCEPackages.graalpy`), TruffleRuby
+  (`graalCEPackages.truffleruby`), GraalJS (`graalCEPackages.graaljs`) and
+  GraalNodeJS (`grallCEPackages.graalnodejs`) are now independent from the main
+  GraalVM derivation.
 
-- The ISC DHCP package and corresponding module have been removed, because they are end of life upstream. See https://www.isc.org/blogs/isc-dhcp-eol/ for details and switch to a different DHCP implementation like kea or dnsmasq.
+- The ISC DHCP package and corresponding module have been removed, because they
+  are EOL upstream. Refer [to this
+  post](https://www.isc.org/blogs/isc-dhcp-eol/) for details and switch to a
+  different DHCP implementation like kea or dnsmasq.
 
-- `prometheus-unbound-exporter` has been replaced by the Let's Encrypt maintained version, since the previous version was archived. This requires some changes to the module configuration, most notable `controlInterface` needs migration
-   towards `unbound.host` and requires either the `tcp://` or `unix://` URI scheme.
+- `prometheus-unbound-exporter` has been replaced by the Let's Encrypt
+  maintained version, since the previous version was archived. This requires
+  some changes to the module configuration, most notable `controlInterface`
+  needs migration towards `unbound.host` and requires either the `tcp://` or
+  `unix://` URI scheme.
 
-- `odoo` now defaults to 16, updated from 15.
+- `odoo` defaults to v16 now, updated from v15.
 
-- `varnish` was upgraded from 7.2.x to 7.4.x, see https://varnish-cache.org/docs/7.3/whats-new/upgrading-7.3.html and https://varnish-cache.org/docs/7.4/whats-new/upgrading-7.4.html for upgrade notes. The current LTS version is still offered as `varnish60`.
+- `varnish` was upgraded from v7.2.x to v7.4.x. Refer to upgrade guides vor
+  [v7.3](https://varnish-cache.org/docs/7.3/whats-new/upgrading-7.3.html) and
+  [v7.4](https://varnish-cache.org/docs/7.4/whats-new/upgrading-7.4.html). The
+  current LTS version is still offered as `varnish60`.
 
-- `util-linux` is now supported on Darwin and is no longer an alias to `unixtools`. Use the `unixtools.util-linux` package for access to the Apple variants of the utilities.
+- `util-linux` is now supported on Darwin and is no longer an alias to
+  `unixtools`. Use the `unixtools.util-linux` package for access to the Apple
+  variants of the utilities.
 
 - `services.keyd` changed API. Now you can create multiple configuration files.
 
-- `baloo`, the file indexer/search engine used by KDE now has a patch to prevent files from constantly being reindexed when the device ids of the their underlying storage changes. This happens frequently when using btrfs or LVM. The patch has not yet been accepted upstream but it provides a significantly improved experience. When upgrading, reset baloo to get a clean index: `balooctl disable ; balooctl purge ; balooctl enable`.
-
-- The `vlock` program from the `kbd` package has been moved into its own package output and should now be referenced explicitly as `kbd.vlock` or replaced with an alternative such as the standalone `vlock` package or `physlock`.
-
-- `fileSystems.<name>.autoFormat` now uses `systemd-makefs`, which does not accept formatting options. Therefore, `fileSystems.<name>.formatOptions` has been removed.
-
-- `fileSystems.<name>.autoResize` now uses `systemd-growfs` to resize the file system online in stage 2. This means that `f2fs` and `ext2` can no longer be auto resized, while `xfs` and `btrfs` now can be.
-
-- `fuse3` has been updated from 3.11.0 to 3.16.2; see [ChangeLog.rst](https://github.com/libfuse/libfuse/blob/fuse-3.16.2/ChangeLog.rst#libfuse-3162-2023-10-10) for an overview of the changes.
-
-  Unsupported mount options are no longer silently accepted [(since 3.15.0)](https://github.com/libfuse/libfuse/blob/fuse-3.16.2/ChangeLog.rst#libfuse-3150-2023-06-09). The [affected mount options](https://github.com/libfuse/libfuse/commit/dba6b3983af34f30de01cf532dff0b66f0ed6045) are: `atime`, `diratime`, `lazytime`, `nolazytime`, `relatime`, `norelatime`, `strictatime`.
+- `baloo`, the file indexer and search engine used by KDE now has a patch to
+  prevent files from constantly being reindexed when the device IDs of the
+  their underlying storage change. This happens frequently when using btrfs or
+  LVM. The patch has not yet been accepted upstream but it provides a
+  significantly improved experience. When upgrading, reset baloo to get a clean
+  index: `balooctl disable ; balooctl purge ; balooctl enable`.
+
+- The `vlock` program from the `kbd` package has been moved into its own
+  package output and should now be referenced explicitly as `kbd.vlock` or
+  replaced with an alternative such as the standalone `vlock` package or
+  `physlock`.
+
+- `fileSystems.<name>.autoFormat` now uses `systemd-makefs`, which does not
+  accept formatting options. Therefore, `fileSystems.<name>.formatOptions` has
+  been removed.
+
+- `fileSystems.<name>.autoResize` uses `systemd-growfs` to resize the file
+  system online in Stage 2 now. This means that `f2fs` and `ext2` can no longer
+  be auto resized, while `xfs` and `btrfs` now can be.
+
+- `fuse3` has been updated from v3.11.0 to v3.16.2. Refer to the
+  [changelog](https://github.com/libfuse/libfuse/blob/fuse-3.16.2/ChangeLog.rst#libfuse-3162-2023-10-10)
+  for an overview of the changes.
+
+  Unsupported mount options are no longer silently accepted [(since
+  3.15.0)](https://github.com/libfuse/libfuse/blob/fuse-3.16.2/ChangeLog.rst#libfuse-3150-2023-06-09).
+  The [affected mount
+  options](https://github.com/libfuse/libfuse/commit/dba6b3983af34f30de01cf532dff0b66f0ed6045)
+  are: `atime`, `diratime`, `lazytime`, `nolazytime`, `relatime`, `norelatime`,
+  `strictatime`.
 
   For example,
 
   ```bash
-  $ sshfs 127.0.0.1:/home/test/testdir /home/test/sshfs_mnt -o atime`
+  $ sshfs 127.0.0.1:/home/test/testdir /home/test/sshfs_mnt -o atime
   ```
 
-  would previously terminate successfully with the mount point established, now it outputs the error message ``fuse: unknown option(s): `-o atime'`` and terminates with exit status 1.
-
-- `nixos-rebuild {switch,boot,test,dry-activate}` now runs the system activation inside `systemd-run`, creating an ephemeral systemd service and protecting the system switch against issues like network disconnections during remote (e.g. SSH) sessions. This has the side effect of running the switch in an isolated environment, that could possible break post-switch scripts that depends on things like environment variables being set. If you want to opt-out from this behavior for now, you may set the `NIXOS_SWITCH_USE_DIRTY_ENV` environment variable before running `nixos-rebuild`. However, keep in mind that this option will be removed in the future.
-
-- The `services.vaultwarden.config` option default value was changed to make Vaultwarden only listen on localhost, following the [secure defaults for most NixOS services](https://github.com/NixOS/nixpkgs/issues/100192).
-
-- `services.lemmy.settings.federation` was removed in 0.17.0 and no longer has any effect. To enable federation, the hostname must be set in the configuration file and then federation must be enabled in the admin web UI. See the [release notes](https://github.com/LemmyNet/lemmy/blob/c32585b03429f0f76d1e4ff738786321a0a9df98/RELEASES.md#upgrade-instructions) for more details.
-
-- `pict-rs` was upgraded from 0.3 to 0.4 and contains an incompatible database & configuration change. To upgrade on systems with `stateVersion = "23.05";` or older follow the migration steps from https://git.asonix.dog/asonix/pict-rs#user-content-0-3-to-0-4-migration-guide and set `services.pict-rs.package = pkgs.pict-rs;`.
-
-- The following packages in `haskellPackages` have now a separate bin output: `cabal-fmt`, `calligraphy`, `eventlog2html`, `ghc-debug-brick`, `hindent`, `nixfmt`, `releaser`. This means you need to replace e.g. `"${pkgs.haskellPackages.nixfmt}/bin/nixfmt"` with `"${lib.getBin pkgs.haskellPackages.nixfmt}/bin/nixfmt"` or `"${lib.getExe pkgs.haskellPackages.nixfmt}"`. The binaries also won’t be in scope if you rely on them being installed e.g. via `ghcWithPackages`. `environment.packages` picks the `bin` output automatically, so for normal installation no intervention is required. Also, toplevel attributes like `pkgs.nixfmt` are not impacted negatively by this change.
-
-- `spamassassin` no longer supports the `Hashcash` module. The module needs to be removed from the `loadplugin` list if it was copied over from the default `initPreConf` option.
-
-- `nano` was removed from `environment.defaultPackages`. To not leave systems without a editor, now `programs.nano.enable` is enabled by default.
-
-- `programs.nano.nanorc` and `programs.nano.syntaxHighlight` no longer have an effect unless `programs.nano.enable` is set to true which is the default.
+  would previously terminate successfully with the mount point established, now
+  it outputs the error message ``fuse: unknown option(s): `-o atime'`` and
+  terminates with exit status 1.
+
+- `nixos-rebuild {switch,boot,test,dry-activate}` runs the system
+  activation inside `systemd-run` now, creating an ephemeral systemd service
+  and protecting the system switch against issues like network disconnections
+  during remote (e.g. SSH) sessions. This has the side effect of running the
+  switch in an isolated environment, that could possible break post-switch
+  scripts that depends on things like environment variables being set. If you
+  want to opt-out from this behavior for now, you may set the
+  `NIXOS_SWITCH_USE_DIRTY_ENV` environment variable before running
+  `nixos-rebuild`. However, keep in mind that this option will be removed in
+  the future.
+
+- The `services.vaultwarden.config` option default value was changed to make
+  Vaultwarden only listen on localhost, following the [secure defaults for most
+  NixOS services](https://github.com/NixOS/nixpkgs/issues/100192).
+
+- `services.lemmy.settings.federation` was removed in v0.17.0 and no longer has
+  any effect. To enable federation, the hostname must be set in the
+  configuration file and then federation must be enabled in the admin web UI.
+  Refer to the [release
+  notes](https://github.com/LemmyNet/lemmy/blob/c32585b03429f0f76d1e4ff738786321a0a9df98/RELEASES.md#upgrade-instructions)
+  for more details.
+
+- `pict-rs` was upgraded from v0.3 to v0.4 and contains an incompatible database
+  & configuration change. To upgrade on systems with `stateVersion = "23.05";`
+  or older follow the migration steps from
+  https://git.asonix.dog/asonix/pict-rs#user-content-0-3-to-0-4-migration-guide
+  and set `services.pict-rs.package = pkgs.pict-rs;`.
+
+- The following packages in `haskellPackages` have a separate bin output now:
+  `cabal-fmt`, `calligraphy`, `eventlog2html`, `ghc-debug-brick`, `hindent`,
+  `nixfmt`, `releaser`. This means you need to replace e.g.
+  `"${pkgs.haskellPackages.nixfmt}/bin/nixfmt"` with `"${lib.getBin
+  pkgs.haskellPackages.nixfmt}/bin/nixfmt"` or `"${lib.getExe
+  pkgs.haskellPackages.nixfmt}"`. The binaries also won’t be in scope if you
+  rely on them being installed e.g. via `ghcWithPackages`.
+  `environment.packages` picks the `bin` output automatically, so for normal
+  installation no intervention is required. Also, toplevel attributes like
+  `pkgs.nixfmt` are not impacted negatively by this change.
+
+- `spamassassin` no longer supports the `Hashcash` module. The module needs to
+  be removed from the `loadplugin` list if it was copied over from the default
+  `initPreConf` option.
+
+- `nano` was removed from `environment.defaultPackages`. To not leave systems
+  without a editor, now `programs.nano.enable` is enabled by default.
+
+- `programs.nano.nanorc` and `programs.nano.syntaxHighlight` no longer have an
+  effect unless `programs.nano.enable` is set to true which is the default.
+
+- `services.outline.sequelizeArguments` has been removed, as `outline` no
+  longer executes database migrations via the `sequelize` cli.
+
+- The binary of the package `cloud-sql-proxy` has changed from
+  `cloud_sql_proxy` to `cloud-sql-proxy`.
+
+- The module `services.apache-kafka` was largely rewritten and has certain
+  breaking changes. To be precise, this means that the following things have
+  changed:
+  - Most settings have been migrated to
+    [services.apache-kafka.settings](#opt-services.apache-kafka.settings).
+    - Care must be taken when adapting an existing cluster to these changes,
+      see [](#module-services-apache-kafka-migrating-to-settings).
+  - By virtue of being less opinionated, it is now possible to use the module
+    to run Apache Kafka in KRaft mode instead of Zookeeper mode.
+    - [A few options](#module-services-apache-kafka-kraft) have been added to
+      assist in this mode.
+
+- Garage has been upgraded to v0.9.x. `services.garage.package` needs to be
+  explicitly set now, so version upgrades can be done in a controlled fashion.
+  For this, we expose `garage_x_y` attributes which can be set here.
+
+- `voms` and `xrootd` now moves the `$out/etc` content to the `$etc` output
+  instead of `$out/etc.orig`, when input argument `externalEtc` is not `null`.
+
+- The `woodpecker-*` CI packages have been updated to v1.0.0. This release is
+  wildly incompatible with the v0.15.x versions that were previously packaged.
+  Refer to [upstream's
+  documentation](https://woodpecker-ci.org/docs/next/migrations#100) to learn
+  how to update your CI configurations.
+
+- Meilisearch was updated from v1.3.1 to v1.5.0. The update has breaking
+  changes about backslashes and filtering. Refer to the [release
+  announcement](https://blog.meilisearch.com/v1-4-release/) for more
+  details.
+
+- The Caddy module gained a new option named `services.caddy.enableReload`
+  which is enabled by default. It allows reloading the service instead of
+  restarting it, if only a config file has changed. This option must be
+  disabled if you have turned off the [Caddy admin
+  API](https://caddyserver.com/docs/caddyfile/options#admin). If you keep this
+  option enabled, you should consider setting
+  [`grace_period`](https://caddyserver.com/docs/caddyfile/options#grace-period)
+  to a non-infinite value to prevent Caddy from delaying the reload
+  indefinitely.
+
+- mdraid support is optional now. This reduces initramfs size and prevents the
+  potentially undesired automatic detection and activation of software RAID
+  pools. It is disabled by default in new configurations (determined by
+  `stateVersion`), but the appropriate settings will be generated by
+  `nixos-generate-config` when installing to a software RAID device, so the
+  standard installation procedure should be unaffected. If you have custom
+  configs relying on mdraid, ensure that you use `stateVersion` correctly or
+  set `boot.swraid.enable` manually. On systems with an updated `stateVersion`
+  we now also emit warnings if `mdadm.conf` does not contain the minimum
+  required configuration necessary to run the dynamically enabled monitoring
+  daemons.
+
+- The `go-ethereum` package has been updated to v1.12.0. This drops support for
+  proof-of-work. Its GraphQL API now encodes all numeric values as hex strings
+  and the GraphQL UI is updated to v2.0. The default database has changed from
+  `leveldb` to `pebble` but `leveldb` can be forced with the
+  --db.engine=leveldb flag. The `checkpoint-admin` command was [removed along
+  with trusted
+  checkpoints](https://github.com/ethereum/go-ethereum/pull/27147).
+
+- The `aseprite-unfree` package has been upgraded from v1.2.16.3 to v1.2.40.
+  The free version of aseprite has been dropped because it is EOL and the
+  package attribute now points to the unfree version. A maintained fork of the
+  last free version of Aseprite, named 'LibreSprite', is available in the
+  `libresprite` package.
+
+- The default `kops` version is v1.28.0 now and support for v1.25 and older have
+  been dropped.
+
+- `pharo` has been updated to latest stable v10.0.8, which is compatible with
+  the latest stable and oldstable images (Pharo 10 and 11). The VM in question
+  is the 64bit Spur. The 32bit version has been dropped due to lack of
+  maintenance. The Cog VM has been deleted because it is severily outdated.
+  Finally, the `pharo-launcher` package has been deleted because it was not
+  compatible with the newer VM, and due to lack of maintenance.
+
+- Emacs mainline v29 was introduced. This new version includes many major
+  additions, most notably `tree-sitter` support (enabled by default) and
+  the pgtk variant (useful for Wayland users), which is available under the
+  attribute `emacs29-pgtk`.
 
-- `services.outline.sequelizeArguments` has been removed, as `outline` no longer executes database migrations via the `sequelize` cli.
+- Emacs macport version 29 was introduced.
 
-- The binary of the package `cloud-sql-proxy` has changed from `cloud_sql_proxy` to `cloud-sql-proxy`.
+- The option `services.networking.networkmanager.enableFccUnlock` was removed
+  in favor of `networking.networkmanager.fccUnlockScripts`, which allows
+  specifying unlock scripts explicitly. The previous option enabled all unlock
+  scripts bundled with ModemManager, which is risky, and didn't allow using
+  vendor-provided unlock scripts at all.
 
-- Garage has been upgraded to 0.9.x. `services.garage.package` now needs to be explicitly set, so version upgrades can be done in a controlled fashion. For this, we expose `garage_x_y` attributes which can be set here.
+- The `html-proofer` package has been updated from major version 3 to major
+  version 5, which includes [breaking
+  changes](https://github.com/gjtorikian/html-proofer/blob/v5.0.8/UPGRADING.md).
 
-- `voms` and `xrootd` now moves the `$out/etc` content to the `$etc` output instead of `$out/etc.orig`, when input argument `externalEtc` is not `null`.
+- `kratos` has been updated from v0.10.1 to the first stable v1.0.0, please
+  read the [v0.10.1 to
+  v0.11.0](https://github.com/ory/kratos/releases/tag/v0.11.0), [v0.11.0 to
+  v0.11.1](https://github.com/ory/kratos/releases/tag/v0.11.1), [v0.11.1 to
+  v0.13.0](https://github.com/ory/kratos/releases/tag/v0.13.0) and [v0.13.0 to
+  v1.0.0](https://github.com/ory/kratos/releases/tag/v1.0.0) upgrade guides.
+  The most notable breaking change is the introduction of one-time passwords
+  (`code`) and update of the default recovery strategy from `link` to `code`.
 
-- The `woodpecker-*` CI packages have been updated to 1.0.0. This release is wildly incompatible with the 0.15.X versions that were previously packaged. Please read [upstream's documentation](https://woodpecker-ci.org/docs/next/migrations#100) to learn how to update your CI configurations.
+- The `hail` module was removed, as `hail` was unmaintained since 2017.
 
-- The Caddy module gained a new option named `services.caddy.enableReload` which is enabled by default. It allows reloading the service instead of restarting it, if only a config file has changed. This option must be disabled if you have turned off the [Caddy admin API](https://caddyserver.com/docs/caddyfile/options#admin). If you keep this option enabled, you should consider setting [`grace_period`](https://caddyserver.com/docs/caddyfile/options#grace-period) to a non-infinite value to prevent Caddy from delaying the reload indefinitely.
+- Package `noto-fonts-emoji` was renamed to `noto-fonts-color-emoji`. Refer to
+  [PR #221181](https://github.com/NixOS/nixpkgs/issues/221181) for more
+  details.
 
-- mdraid support is now optional. This reduces initramfs size and prevents the potentially undesired automatic detection and activation of software RAID pools. It is disabled by default in new configurations (determined by `stateVersion`), but the appropriate settings will be generated by `nixos-generate-config` when installing to a software RAID device, so the standard installation procedure should be unaffected. If you have custom configs relying on mdraid, ensure that you use `stateVersion` correctly or set `boot.swraid.enable` manually. On systems with an updated `stateVersion` we now also emit warnings if `mdadm.conf` does not contain the minimum required configuration necessary to run the dynamically enabled monitoring daemons.
+- Package `cloud-sql-proxy` was renamed to `google-cloud-sql-proxy` as it
+  cannot be used with other cloud providers.
 
-- The `go-ethereum` package has been updated to v1.12.0. This drops support for proof-of-work. Its GraphQL API now encodes all numeric values as hex strings and the GraphQL UI is updated to version 2.0. The default database has changed from `leveldb` to `pebble` but `leveldb` can be forced with the --db.engine=leveldb flag. The `checkpoint-admin` command was [removed along with trusted checkpoints](https://github.com/ethereum/go-ethereum/pull/27147).
+- Package `pash` was removed due to being archived upstream. Use `powershell`
+  as an alternative.
 
-- The `aseprite-unfree` package has been upgraded from 1.2.16.3 to 1.2.40. The free version of aseprite has been dropped because it is EOL and the package attribute now points to the unfree version. A maintained fork of the last free version of Aseprite, named 'LibreSprite', is available in the `libresprite` package.
+- The option `services.plausible.releaseCookiePath` has been removed. Plausible
+  does not use any distributed Erlang features, and does not plan to (refer to
+  [discussion](https://github.com/NixOS/nixpkgs/pull/130297#issuecomment-1805851333)),
+  Thus NixOS disables them now , and the Erlang cookie becomes unnecessary. You
+  may delete the file that `releaseCookiePath` was set to.
 
-- The default `kops` version is now 1.28.0 and support for 1.25 and older has been dropped.
+- `security.sudo.extraRules` includes `root`'s default rule now, with ordering
+  priority 400. This is functionally identical for users not specifying rule
+  order, or relying on `mkBefore` and `mkAfter`, but may impact users calling
+  `mkOrder n` with n ≤ 400.
 
-- `pharo` has been updated to latest stable (PharoVM 10.0.8), which is compatible with the latest stable and oldstable images (Pharo 10 and 11). The VM in question is the 64bit Spur. The 32bit version has been dropped due to lack of maintenance. The Cog VM has been deleted because it is severily outdated. Finally, the `pharo-launcher` package has been deleted because it was not compatible with the newer VM, and due to lack of maintenance.
+- X keyboard extension (XKB) options have been reorganized into a single
+  attribute set, `services.xserver.xkb`. Specifically,
+  `services.xserver.layout` is `services.xserver.xkb.layout` now,
+  `services.xserver.extraLayouts` is `services.xserver.xkb.extraLayouts` now,
+  `services.xserver.xkbModel` is `services.xserver.xkb.model` now,
+  `services.xserver.xkbOptions` is `services.xserver.xkb.options` now ,
+  `services.xserver.xkbVariant` is `services.xserver.xkb.variant` now, and
+  `services.xserver.xkbDir` is `services.xserver.xkb.dir` now.
+
+- `networking.networkmanager.firewallBackend` was removed as NixOS is now using
+  iptables-nftables-compat even when using iptables, therefore Networkmanager
+  uses the nftables backend unconditionally now.
+
+- `rome` was removed because it is no longer maintained and is succeeded by
+  `biome`.
+
+- The `prometheus-knot-exporter` was migrated to a version maintained by
+  CZ.NIC. Various metric names have changed, so checking existing rules is
+  recommended.
+
+- The `services.mtr-exporter.target` has been removed in favor of
+  `services.mtr-exporter.jobs` which allows specifying multiple targets.
+
+- `blender-with-packages` has been deprecated in favor of
+  `blender.withPackages`, for example `blender.withPackages (ps: [ps.bpycv])`.
+  It behaves similarly to `python3.withPackages`.
+
+- Setting `nixpkgs.config` options while providing an external `pkgs` instance
+  will now raise an error instead of silently ignoring the options. NixOS
+  modules no longer set `nixpkgs.config` to accommodate this. This specifically
+  affects `services.locate`,
+  `services.xserver.displayManager.lightdm.greeters.tiny` and
+  `programs.firefox` NixOS modules. No manual intervention should be required
+  in most cases, however, configurations relying on those modules affecting
+  packages outside the system environment should switch to explicit overlays.
+
+- `privacyidea` (and the corresponding `privacyidea-ldap-proxy`) has been
+  removed from nixpkgs because it has severely outdated dependencies that
+  became unmaintainable with nixpkgs' python package-set.
+
+- `dagger` was removed because using a package called `dagger` and packaging it
+  from source violates their trademark policy.
 
-- Emacs mainline version 29 was introduced. This new version includes many major additions, most notably `tree-sitter` support (enabled by default) and the pgtk variant (useful for Wayland users), which is available under the attribute `emacs29-pgtk`.
+- `win-virtio` package was renamed to `virtio-win` to be consistent with the upstream package name.
 
-- Emacs macport version 29 was introduced.
+- `ps3netsrv` has been replaced with the webman-mod fork, the executable has
+  been renamed from `ps3netsrv++` to `ps3netsrv` and cli parameters have
+  changed.
 
-- The option `services.networking.networkmanager.enableFccUnlock` was removed in favor of `networking.networkmanager.fccUnlockScripts`, which allows specifying unlock scripts explicitly. The previous option enabled all unlock scripts bundled with ModemManager, which is risky, and didn't allow using vendor-provided unlock scripts at all.
+- `ssm-agent` package and module were renamed to `amazon-ssm-agent` to be
+  consistent with the upstream package name.
 
-- The `html-proofer` package has been updated from major version 3 to major version 5, which includes [breaking changes](https://github.com/gjtorikian/html-proofer/blob/v5.0.8/UPGRADING.md).
+- `services.kea.{ctrl-agent,dhcp-ddns,dhcp,dhcp6}` now use separate runtime
+  directories instead of `/run/kea` to work around the runtime directory being
+  cleared on service start.
 
-- `kratos` has been updated from 0.10.1 to the first stable version 1.0.0, please read the [0.10.1 to 0.11.0](https://github.com/ory/kratos/releases/tag/v0.11.0), [0.11.0 to 0.11.1](https://github.com/ory/kratos/releases/tag/v0.11.1), [0.11.1 to 0.13.0](https://github.com/ory/kratos/releases/tag/v0.13.0) and [0.13.0 to 1.0.0](https://github.com/ory/kratos/releases/tag/v1.0.0) upgrade guides. The most notable breaking change is the introduction of one-time passwords (`code`) and update of the default recovery strategy from `link` to `code`.
+- `mkDerivation` rejects MD5 hashes now.
 
-- The `hail` NixOS module was removed, as `hail` was unmaintained since 2017.
+- The `junicode` font package has been updated to [major
+  v2](https://github.com/psb1558/Junicode-font/releases/tag/v2.001), which is
+  a font family now. In particular, plain `Junicode.ttf` no longer exists. In
+  addition, TrueType font files are now placed in `font/truetype` instead of
+  `font/junicode-ttf`; this change does not affect use via `fonts.packages`
+  option.
 
-- Package `noto-fonts-emoji` was renamed to `noto-fonts-color-emoji`;
-  see [#221181](https://github.com/NixOS/nixpkgs/issues/221181).
+- The `prayer` package as well as `services.prayer` have been removed because
+  it's been unmaintained for several years and the author's website has
+  vanished.
 
-- Package `cloud-sql-proxy` was renamed to `google-cloud-sql-proxy` as it cannot be used with other cloud providers.;
+- The `chrony` NixOS module now tracks the real-time clock drift from the
+  system clock with `rtcfile` and automatically adjusts it with `rtcautotrim`
+  when it exceeds the maximum error specified in
+  `services.chrony.autotrimThreshold` (defaults to 30 seconds). If you enabled
+  `rtcsync` in `extraConfig`, you should remove RTC related options from
+  `extraConfig`. If you do not want chrony configured to keep the RTC in check,
+  you can set `services.chrony.enableRTCTrimming = false;`.
 
-- Package `pash` was removed due to being archived upstream. Use `powershell` as an alternative.
+- `trilium-desktop` and `trilium-server` have been updated to
+  [v0.61](https://github.com/zadam/trilium/releases/tag/v0.61.12). For existing
+  installations, upgrading to this version is supported only after running
+  v0.60.x at least once. If you are still on an older version, make sure to
+  update to v0.60 (available in NixOS 23.05) first and only then to v0.61
+  (available in NixOS 23.11).
 
-- The option `services.plausible.releaseCookiePath` has been removed: Plausible does not use any distributed Erlang features, and does not plan to (see [discussion](https://github.com/NixOS/nixpkgs/pull/130297#issuecomment-1805851333)), so NixOS now disables them, and the Erlang cookie becomes unnecessary. You may delete the file that `releaseCookiePath` was set to.
+- Cassandra now defaults to v4.x, updated from v3.11.x.
 
-- `security.sudo.extraRules` now includes `root`'s default rule, with ordering
-  priority 400. This is functionally identical for users not specifying rule
-  order, or relying on `mkBefore` and `mkAfter`, but may impact users calling
-  `mkOrder n` with n ≤ 400.
 
-- X keyboard extension (XKB) options have been reorganized into a single attribute set, `services.xserver.xkb`. Specifically, `services.xserver.layout` is now `services.xserver.xkb.layout`, `services.xserver.extraLayouts` is now `services.xserver.xkb.extraLayouts`, `services.xserver.xkbModel` is now `services.xserver.xkb.model`, `services.xserver.xkbOptions` is now `services.xserver.xkb.options`, `services.xserver.xkbVariant` is now `services.xserver.xkb.variant`, and `services.xserver.xkbDir` is now `services.xserver.xkb.dir`.
+- FoundationDB now defaults to major version 7.
 
-- `networking.networkmanager.firewallBackend` was removed as NixOS is now using iptables-nftables-compat even when using iptables, therefore Networkmanager now uses the nftables backend unconditionally.
+- [glibc](https://www.gnu.org/software/libc/) has been updated from v2.37 to
+  v2.38. Refer to the [the release
+  notes](https://sourceware.org/glibc/wiki/Release/2.38) for more details.
 
-- [`lib.lists.foldl'`](https://nixos.org/manual/nixpkgs/stable#function-library-lib.lists.foldl-prime) now always evaluates the initial accumulator argument first.
-  If you depend on the lazier behavior, consider using [`lib.lists.foldl`](https://nixos.org/manual/nixpkgs/stable#function-library-lib.lists.foldl) or [`builtins.foldl'`](https://nixos.org/manual/nix/stable/language/builtins.html#builtins-foldl') instead.
+- `linuxPackages_testing_bcachefs` is now soft-deprecated by
+  `linuxPackages_testing`.
+  - Please consider changing your NixOS configuration's `boot.kernelPackages`
+    to `linuxPackages_testing` until a stable kernel with bcachefs support is
+    released.
 
-- [`lib.attrsets.foldlAttrs`](https://nixos.org/manual/nixpkgs/stable#function-library-lib.attrsets.foldlAttrs) now always evaluates the initial accumulator argument first.
+- PostgreSQL now defaults to major version 15.
 
-- `rome` was removed because it is no longer maintained and is succeeded by `biome`.
+- All [ROCm](https://rocm.docs.amd.com/en/latest/) packages have been updated
+  to v5.7.0.
+  - [ROCm](https://rocm.docs.amd.com/en/latest/) package attribute sets are
+    versioned: `rocmPackages` -> `rocmPackages_5`.
+
+- [systemd](https://systemd.io) has been updated from v253 to v254, refer to
+  [the release
+  notes](https://github.com/systemd/systemd/blob/v254/NEWS#L3-L659) for more
+  details.
+    - `boot.resumeDevice` **must be specified** when hibernating if not in EFI
+      mode.
+    - systemd may warn your system about the permissions of your ESP partition
+      (often `/boot`), this warning can be ignored for now, we are looking into
+      a satisfying solution regarding this problem.
+    - Updating with `nixos-rebuild boot` and rebooting is recommended, since in
+      some rare cases the `nixos-rebuild switch` into the new generation on a
+      live system might fail due to missing mount units.
+
+- If the user has a custom shell enabled via `users.users.${USERNAME}.shell =
+  ${CUSTOMSHELL}`, the assertion will require them to also set
+  `programs.${CUSTOMSHELL}.enable = true`. This is generally safe behavior, but
+  for anyone needing to opt out from the check
+  `users.users.${USERNAME}.ignoreShellProgramCheck = true` will do the job.
+
+- `yarn-berry` has been updated to v4.0.1. This means that NodeJS versions less
+  v18.12 are no longer supported by it. Refer to the [upstream
+  changelog](https://github.com/yarnpkg/berry/blob/master/CHANGELOG.md) for
+  more details.
+
+- GNOME has been updated to v45. Refer to the [release
+  notes](https://release.gnome.org/45/) for more details. Notably, Loupe has
+  replaced Eye of GNOME as the default image viewer, Snapshot has replaced
+  Cheese as the default camera application, and Photos will no longer be
+  installed.
+
+- The module [services.ankisyncd](#opt-services.ankisyncd.package) has been
+  switched to
+  [anki-sync-server-rs](https://github.com/ankicommunity/anki-sync-server-rs).
+  The former version written in Python was difficult to update, did not receive
+  updates in a while, and did not support recent versions of Anki.
+
+  Unfortunately all servers supporting new clients do not support the older
+  sync protocol that was used in the old server. This includes newer version of
+  anki-sync-server, Anki's built in sync server and this new Rust package. Thus
+  old clients will also need updating. In particular nixpkgs's Anki package is
+  also being updated in this release.
+
+  The module update takes care of the new config syntax. The data itself (i.e.
+  user login and card information) is compatible. Thus users of the module will
+  be able to simply log in again after updating both client and server without
+  any extra action needed to be taken.
+
+- The argument `vendorSha256` of `buildGoModule` is deprecated. Use
+  `vendorHash` instead. Refer to [PR
+  \#259999](https://github.com/NixOS/nixpkgs/pull/259999)) for more details.
+
+- `go-modules` in `buildGoModule` attrs has been renamed to `goModules`.
+
+- The package `cawbird` is dropped from nixpkgs. It broke by the Twitter API
+  closing down and has been abandoned upstream.
+
+- The Cinnamon module now enables XDG desktop integration by default. If you
+  are experiencing collisions related to xdg-desktop-portal-gtk you can safely
+  remove `xdg.portal.extraPortals = [ pkgs.xdg-desktop-portal-gtk ];` from your
+  NixOS configuration.
+
+- GNOME, Pantheon, Cinnamon modules no longer force Qt applications to use
+  Adwaita style. This implemantion  was buggy and is no longer maintained
+  upstream. Specifically, Cinnamon defaults to the gtk2 style instead now,
+  following the default in Linux Mint). If you still want Adwaita used, you may
+  add the following options to your configuration. Please be aware, that it
+  will probably be removed eventually.
 
-- The `prometheus-knot-exporter` was migrated to a version maintained by CZ.NIC. Various metric names have changed, so checking existing rules is recommended.
+  ```nix
+  qt = {
+    enable = true;
+    platformTheme = "gnome";
+    style = "adwaita";
+  };
+  ```
 
-- The `services.mtr-exporter.target` has been removed in favor of `services.mtr-exporter.jobs` which allows specifying multiple targets.
+- DocBook option documentation is no longer supported, all module documentation
+  now uses Markdown.
 
-- `blender-with-packages` has been deprecated in favor of `blender.withPackages`, for example `blender.withPackages (ps: [ps.bpycv])`. It behaves similarly to `python3.withPackages`.
+- Docker defaults to v24 now, as 20.10 is stopping to receive security updates
+  and bug fixes after [December 10,
+  2023](https://github.com/moby/moby/discussions/45104).
 
-- Setting `nixpkgs.config` options while providing an external `pkgs` instance will now raise an error instead of silently ignoring the options. NixOS modules no longer set `nixpkgs.config` to accomodate this. This specifically affects `services.locate`, `services.xserver.displayManager.lightdm.greeters.tiny` and `programs.firefox` NixOS modules. No manual intervention should be required in most cases, however, configurations relying on those modules affecting packages outside the system environment should switch to explicit overlays.
+- Elixir defaults to v1.15 now. Refer to their
+  [changelog](https://elixir-lang.org/blog/2023/06/19/elixir-v1-15-0-released/)
+  for more details.
 
-- `service.borgmatic.settings.location` and `services.borgmatic.configurations.<name>.location` are deprecated, please move your options out of sections to the global scope.
+- The `extend` function of `llvmPackages` has been removed due it coming from
+  the `tools` attrset thus only extending the `tool` attrset. A possible
+  replacement is to construct the set from `libraries` and `tools`, or patch
+  nixpkgs.
 
-- `privacyidea` (and the corresponding `privacyidea-ldap-proxy`) has been removed from nixpkgs because it has severely outdated dependencies that became unmaintainable with nixpkgs' python package-set.
+- `ffmpeg` defaults to `ffmpeg_6` now, upgrading from `ffmpeg_5`.
 
-- `dagger` was removed because using a package called `dagger` and packaging it from source violates their trademark policy.
+- `fontconfig` defaults to using greyscale antialiasing now. Previously
+  subpixel antialiasing was used because of a [recommendation from one of the
+  downstreams](https://gitlab.freedesktop.org/fontconfig/fontconfig/-/issues/337).
+  You can change this value by configuring
+  [](#opt-fonts.fontconfig.subpixel.rgba) accordingly.
 
-- `win-virtio` package was renamed to `virtio-win` to be consistent with the upstream package name.
+- The `fonts.fonts` and `fonts.enableDefaultFonts` options have been renamed to
+  `fonts.packages` and `fonts.enableDefaultPackages` respectively.
 
-- `ps3netsrv` has been replaced with the webman-mod fork, the executable has been renamed from `ps3netsrv++` to `ps3netsrv` and cli parameters have changed.
+- `services.hedgedoc` has been heavily refactored, reducing the amount of
+  declared options in the module. Most of the options should still work without
+  any changes to the configuration. Some options have been deprecated, as they
+  no longer have any effect. Refer to [PR
+  #244941](https://github.com/NixOS/nixpkgs/pull/244941) for more details.
 
-- `ssm-agent` package and module were renamed to `amazon-ssm-agent` to be consistent with the upstream package name.
+- `jq` was updated to v1.7. This is its [first release in 5
+  years](https://github.com/jqlang/jq/releases/tag/jq-1.7).
 
-- `services.kea.{ctrl-agent,dhcp-ddns,dhcp,dhcp6}` now use separate runtime directories instead of `/run/kea` to work around the runtime directory being cleared on service start.
+- [`lib.attrsets.foldlAttrs`](https://nixos.org/manual/nixpkgs/stable#function-library-lib.attrsets.foldlAttrs)
+  now always evaluates the initial accumulator argument first.
 
-- `mkDerivation` now rejects MD5 hashes.
+- [`lib.lists.foldl'`](https://nixos.org/manual/nixpkgs/stable#function-library-lib.lists.foldl-prime)
+  now always evaluates the initial accumulator argument first. If you depend on
+  the lazier behavior, consider using
+  [`lib.lists.foldl`](https://nixos.org/manual/nixpkgs/stable#function-library-lib.lists.foldl)
+  or
+  [`builtins.foldl'`](https://nixos.org/manual/nix/stable/language/builtins.html#builtins-foldl')
+  instead.
 
-- The `junicode` font package has been updated to [major version 2](https://github.com/psb1558/Junicode-font/releases/tag/v2.001), which is now a font family. In particular, plain `Junicode.ttf` no longer exists. In addition, TrueType font files are now placed in `font/truetype` instead of `font/junicode-ttf`; this change does not affect use via `fonts.packages` NixOS option.
+-  Now `magma` defaults to `magma-hip` instead of `magma-cuda`. It also
+   respects the `config.cudaSupport` and `config.rocmSupport` options.
 
-- The `prayer` package as well as `services.prayer` have been removed because it's been unmaintained for several years and the author's website has vanished.
+- The MariaDB C client library was upgraded from v3.2.x to v3.3.x. Refer to the
+  [upstream release
+  notes](https://mariadb.com/kb/en/mariadb-connector-c-33-release-notes/) for
+  more details.
 
-- The `chrony` NixOS module now tracks the Real-Time Clock drift from the System Clock with `rtcfile` and automatically adjusts it with `rtcautotrim` when it exceeds the maximum error specified in `services.chrony.autotrimThreshold` (default 30 seconds). If you enabled `rtcsync` in `extraConfig`, you should remove RTC related options from `extraConfig`. If you do not want chrony configured to keep the RTC in check, you can set `services.chrony.enableRTCTrimming = false;`
+- Mattermost has been upgraded to extended support version 8.1 as the previously
+  packaged extended support version 7.8 is [reaching end-of-life](https://docs.mattermost.com/upgrade/extended-support-release.html).
+  Migration may take some time, refer to the [changelog](https://docs.mattermost.com/install/self-managed-changelog.html#release-v8-1-extended-support-release)
+  and [important upgrade notes](https://docs.mattermost.com/upgrade/important-upgrade-notes.html).
 
-## Other Notable Changes {#sec-release-23.11-notable-changes}
+- The `netdata` package disables cloud support by default now. To enable it use the `netdataCloud` package.
 
-- A new option `system.switch.enable` was added. By default, this is option is
-  enabled. Disabling it makes the system unable to be reconfigured via
-  `nixos-rebuild`. This is good for image based appliances where updates are
-  handled outside the image.
+- `networking.nftables` is no longer flushing all rulesets on every reload.
+  Use `networking.nftables.flushRuleset = true;` to enable the previous behaviour.
 
-- The Cinnamon module now enables XDG desktop integration by default. If you are experiencing collisions related to xdg-desktop-portal-gtk you can safely remove `xdg.portal.extraPortals = [ pkgs.xdg-desktop-portal-gtk ];` from your NixOS configuration.
+- Node.js v14, v16 has been removed as they were end of life. Any dependent packages that contributors were not able to reasonably upgrade were dropped after a month of notice to their maintainers, were **removed**.
+  - This includes VSCode Server.
+  - This includes Kibana 7 as the ELK stack is unmaintained in nixpkgs and is marked for slow removal.
 
-- GNOME, Pantheon, Cinnamon module no longer forces Qt applications to use Adwaita style since it was buggy and is no longer maintained upstream (specifically, Cinnamon now defaults to the gtk2 style instead, following the default in Linux Mint). If you still want it, you can add the following options to your configuration but it will probably be eventually removed:
+- The application firewall `opensnitch` uses the process monitor method eBPF as
+  default now. This is recommended by upstream. The method may be changed with
+  the setting
+  [services.opensnitch.settings.ProcMonitorMethod](#opt-services.opensnitch.settings.ProcMonitorMethod).
+
+- `paperwork` is updated to v2.2. Documents scanned with this version will not
+  be visible to previous versions if you downgrade. Refer to the [upstream
+  announcement](https://forum.openpaper.work/t/paperwork-2-2-testing-phase/316#important-switch-from-jpeg-to-png-for-new-pages-2)
+  for details and workarounds.
+
+- The latest available version of Nextcloud is v27 (available as
+  `pkgs.nextcloud27`). The installation logic is as follows:
+  - If [`services.nextcloud.package`](#opt-services.nextcloud.package) is
+    specified explicitly, this package will be installed (**recommended**)
+  - If [`system.stateVersion`](#opt-system.stateVersion) is >=23.11,
+    `pkgs.nextcloud27` will be installed by default.
+  - If [`system.stateVersion`](#opt-system.stateVersion) is >=23.05,
+    `pkgs.nextcloud26` will be installed by default.
+  - Please note that an upgrade from v25 (or older) to v27 is not possible
+    directly. Please upgrade to `nextcloud26` (or earlier) first. Nextcloud
+    prohibits skipping major versions while upgrading. You may upgrade by
+    declaring [`services.nextcloud.package =
+    pkgs.nextcloud26;`](options.html#opt-services.nextcloud.package) inbetween.
+
+- `postgresql_11` has been removed since it'll stop receiving fixes on November
+  9th 2023.
+
+- `programs.gnupg.agent.pinentryFlavor` is set in `/etc/gnupg/gpg-agent.conf`
+  now. It will no longer take precedence over a `pinentry-program` set in
+  `~/.gnupg/gpg-agent.conf`.
+
+- `python3.pkgs.flitBuildHook` has been removed. Use `flit-core` and `format =
+  "pyproject"` instead.
+
+- Certificate generation via the `security.acme` limits the concurrent number
+  of running certificate renewals and generation jobs now. This is to avoid
+  spiking resource usage when processing many certificates at once. The limit
+  defaults to *5* and can be adjusted via `maxConcurrentRenewals`. Setting the
+  value to *0* disables the limits altogether.
+
+- `services.borgmatic.settings.location` and
+  `services.borgmatic.configurations.<name>.location` are deprecated, please
+  move your options out of sections to the global scope.
+
+- `services.fail2ban.jails` can be configured with attribute sets now, defining
+  settings and filters instead of lines. The stringed options `daemonConfig`
+  and `extraSettings` have respectively been replaced by `daemonSettings` and
+  `jails.DEFAULT.settings`. Those  use attribute sets.
+
+- The `services.mbpfan` module has the option `aggressive` enabled by default
+  now. This is for better heat moderation. To get the upstream defaults you may
+  disable this.
+
+- Apptainer/Singularity defaults to using `"$out/var/lib"` for the
+  `LOCALSTATEDIR` configuration option instead of the top-level `"/var/lib"`
+  now. This change impacts the `SESSIONDIR` (container-run-time mount point)
+  configuration, which is set to `$LOCALSTATEDIR/<apptainer or
+  singularity>/mnt/session`. This detaches the packages from the top-level
+  directory, rendering the NixOS module optional.
+
+  The default behavior of the NixOS module `programs.singularity` stays
+  unchanged. We add a new option
+  `programs.singularity.enableExternalSysConfDir` (default to `true`) to
+  specify whether to set the top-level `"/var/lib"` as `LOCALSTATEDIR` or not.
+
+- The `services.sslh` module has been updated to follow [RFC
+  0042](https://github.com/NixOS/rfcs/blob/master/rfcs/0042-config-option.md).
+  As such, several options have been moved to the freeform attribute set
+  [services.sslh.settings](#opt-services.sslh.settings), which allows to change
+  any of the settings in {manpage}`sslh(8)`.
+
+  In addition, the newly added option
+  [services.sslh.method](#opt-services.sslh.method) allows to switch between
+  the {manpage}`fork(2)`, {manpage}`select(2)` and `libev`-based connection
+  handling method. Refer to the [sslh
+  docs](https://github.com/yrutschle/sslh/blob/master/doc/INSTALL.md#binaries)
+  for a comparison.
+
+- Suricata was upgraded from v6.0 to v7.0 and no longer considers HTTP/2
+  support as experimental. Refer to [upstream release
+  notes](https://forum.suricata.io/t/suricata-7-0-0-released/3715) for more
+  details.
+
+- `teleport` has been upgraded from major version 12 to major version 14.
+  Refer to upstream [upgrade
+  instructions](https://goteleport.com/docs/management/operations/upgrading/)
+  and release notes for
+  [v13](https://goteleport.com/docs/changelog/#1300-050823) and
+  [v14](https://goteleport.com/docs/changelog/#1400-092023). Note that Teleport
+  does not officially support upgrades across more than one major version at a
+  time. If you're running Teleport server components, it is recommended to
+  first upgrade to an intermediate v13.x version by setting
+  `services.teleport.package = pkgs.teleport_13`. Afterwards, this option can
+  be removed to upgrade to the default version (14).
+
+- `zfs` was updated from v2.1.x to v2.2.0, [enabling newer kernel support and
+  adding new features](https://github.com/openzfs/zfs/releases/tag/zfs-2.2.0).
+
+- The use of `sourceRoot = "source";`, `sourceRoot = "source/subdir";`, and
+  similar lines in package derivations using the default `unpackPhase` is
+  deprecated as it requires `unpackPhase` to always produce a directory named
+  "source". Use `sourceRoot = src.name`, `sourceRoot = "${src.name}/subdir";`,
+  or `setSourceRoot = "sourceRoot=$(echo */subdir)";` or similar instead.
+
+- The `django` alias in the python package set was upgraded to Django v4.x.
+  Applications that consume Django should always pin their python environment
+  to a compatible major version, so they can move at their own pace.
 
   ```nix
-  qt = {
-    enable = true;
-    platformTheme = "gnome";
-    style = "adwaita";
+  python = python3.override {
+    packageOverrides = self: super: {
+      django = super.django_3;
+    };
   };
   ```
 
-- `fontconfig` now defaults to using greyscale antialiasing instead of subpixel antialiasing because of a [recommendation from one of the downstreams](https://gitlab.freedesktop.org/fontconfig/fontconfig/-/issues/337). You can change this value by configuring [](#opt-fonts.fontconfig.subpixel.rgba) accordingly.
+- The `qemu-vm.nix` module by default now identifies block devices via
+  persistent names available in `/dev/disk/by-*`. Because the rootDevice is
+  identified by its filesystem label, it needs to be formatted before the VM is
+  started. The functionality of automatically formatting the rootDevice in the
+  initrd is removed from the QEMU module. However, for tests that depend on
+  this functionality, a test utility for the scripted initrd is added
+  (`nixos/tests/common/auto-format-root-device.nix`). To use this in a NixOS
+  test, import the module, e.g. `imports = [
+  ./common/auto-format-root-device.nix ];` When you use the systemd initrd, you
+  can automatically format the root device by setting
+  `virtualisation.fileSystems."/".autoFormat = true;`.
+
+- The `electron` packages places its application files in
+  `$out/libexec/electron` instead of `$out/lib/electron` now. Packages using
+  electron-builder will fail to build and need to be adjusted by changing `lib`
+  to `libexec`.
 
-- The latest available version of Nextcloud is v27 (available as `pkgs.nextcloud27`). The installation logic is as follows:
-  - If [`services.nextcloud.package`](#opt-services.nextcloud.package) is specified explicitly, this package will be installed (**recommended**)
-  - If [`system.stateVersion`](#opt-system.stateVersion) is >=23.11, `pkgs.nextcloud27` will be installed by default.
-  - If [`system.stateVersion`](#opt-system.stateVersion) is >=23.05, `pkgs.nextcloud26` will be installed by default.
-  - Please note that an upgrade from v25 (or older) to v27 directly is not possible. Please upgrade to `nextcloud26` (or earlier) first. Nextcloud prohibits skipping major versions while upgrading. You can upgrade by declaring [`services.nextcloud.package = pkgs.nextcloud26;`](options.html#opt-services.nextcloud.package).
+### New Services {#sec-release-23.11-nixos-new-services}
 
-- New options were added to `services.searx` for better SearXNG support, including options for the built-in rate limiter and bot protection and automatically configuring a local redis server.
+- [MCHPRS](https://github.com/MCHPR/MCHPRS), a multithreaded Minecraft server
+  built for redstone. Available as
+  [services.mchprs](#opt-services.mchprs.enable).
 
-- `jq` was updated to 1.7, its [first release in 5 years](https://github.com/jqlang/jq/releases/tag/jq-1.7).
+- [acme-dns](https://github.com/joohoi/acme-dns), a limited DNS server to
+  handle ACME DNS challenges easily and securely. Available as
+  [services.acme-dns](#opt-services.acme-dns.enable).
 
-- `zfs` was updated from 2.1.x to 2.2.0, [enabling newer kernel support and adding new features](https://github.com/openzfs/zfs/releases/tag/zfs-2.2.0).
+- [frp](https://github.com/fatedier/frp), a fast reverse proxy to help you
+  expose a local server behind a NAT or firewall to the Internet. Available as
+  [services.frp](#opt-services.frp.enable).
 
-- Elixir now defaults to version
-  [v1.15](https://elixir-lang.org/blog/2023/06/19/elixir-v1-15-0-released/).
+- [river](https://github.com/riverwm/river), A dynamic tiling wayland
+  compositor. Available as [programs.river](#opt-programs.river.enable).
 
-- A new option was added to the virtualisation module that enables specifying explicitly named network interfaces in QEMU VMs. The existing `virtualisation.vlans` is still supported for cases where the name of the network interface is irrelevant.
+- [wayfire](https://wayfire.org), a modular and extensible wayland compositor.
+  Available as [programs.wayfire](#opt-programs.wayfire.enable).
 
-- DocBook option documentation is no longer supported, all module documentation now uses markdown.
+- [mautrix-whatsapp](https://docs.mau.fi/bridges/go/whatsapp/index.html), a
+  Matrix-WhatsApp puppeting bridge. Available as
+  [services.mautrix-whatsapp](#opt-services.mautrix-whatsapp.enable).
 
-- `services.outline` can now be configured to use local filesystem storage instead of S3 storage using [services.outline.storage.storageType](#opt-services.outline.storage.storageType).
+- [hddfancontrol](https://github.com/desbma/hddfancontrol), a service to
+  regulate fan speeds based on hard drive temperature. Available as
+  [services.hddfancontrol](#opt-services.hddfancontrol.enable).
 
-- `paperwork` was updated to version 2.2. Documents scanned with this version will not be visible to previous versions if you downgrade. See the [upstream announcement](https://forum.openpaper.work/t/paperwork-2-2-testing-phase/316#important-switch-from-jpeg-to-png-for-new-pages-2) for details and workarounds.
+- [seatd](https://sr.ht/~kennylevinsen/seatd/), A minimal seat management
+  daemon. Available as [services.seatd](#opt-services.seatd.enable).
 
-- `buildGoModule` `go-modules` attrs have been renamed to `goModules`.
+- [GoToSocial](https://gotosocial.org/), an ActivityPub social network server
+  written in Golang. Available as
+  [services.gotosocial](#opt-services.gotosocial.enable).
 
-- The `fonts.fonts` and `fonts.enableDefaultFonts` options have been renamed to `fonts.packages` and `fonts.enableDefaultPackages` respectively.
+- [Castopod](https://castopod.org/), an open-source hosting platform made for
+  podcasters who want to engage and interact with their audience. Available as
+  [services.castopod](#opt-services.castopod.enable).
 
-- The `services.sslh` module has been updated to follow [RFC 0042](https://github.com/NixOS/rfcs/blob/master/rfcs/0042-config-option.md). As such, several options have been moved to the freeform attribute set [services.sslh.settings](#opt-services.sslh.settings), which allows to change any of the settings in {manpage}`sslh(8)`.
-  In addition, the newly added option [services.sslh.method](#opt-services.sslh.method) allows to switch between the {manpage}`fork(2)`, {manpage}`select(2)` and `libev`-based connection handling method; see the [sslh docs](https://github.com/yrutschle/sslh/blob/master/doc/INSTALL.md#binaries) for a comparison.
+- [Typesense](https://github.com/typesense/typesense), a fast, typo-tolerant
+  search engine for building delightful search experiences. Available as
+  [services.typesense](#opt-services.typesense.enable).
 
-- `pkgs.openvpn3` now optionally supports systemd-resolved. `programs.openvpn3` will automatically enable systemd-resolved support if `config.services.resolved.enable` is enabled.
+* [NS-USBLoader](https://github.com/developersu/ns-usbloader/), an all-in-one
+  tool for managing Nintendo Switch homebrew. Available as
+  [programs.ns-usbloader](#opt-programs.ns-usbloader.enable).
 
-- `services.fail2ban.jails` can now be configured with attribute sets defining settings and filters instead of lines. The stringed options `daemonConfig` and `extraSettings` have respectively been replaced by `daemonSettings` and `jails.DEFAULT.settings` which use attribute sets.
+- [athens](https://github.com/gomods/athens), a Go module datastore and proxy. Available as [services.athens](#opt-services.athens.enable).
 
-- The application firewall `opensnitch` now uses the process monitor method eBPF as default as recommended by upstream. The method can be changed with the setting [services.opensnitch.settings.ProcMonitorMethod](#opt-services.opensnitch.settings.ProcMonitorMethod).
+- [Mobilizon](https://joinmobilizon.org/), a Fediverse platform for publishing
+  events. Available as [services.mobilizon](#opt-services.mobilizon.enable).
 
-- `services.hedgedoc` has been heavily refactored, reducing the amount of declared options in the module. Most of the options should still work without any changes. Some options have been deprecated, as they no longer have any effect. See [#244941](https://github.com/NixOS/nixpkgs/pull/244941) for more details.
+- [Anuko Time Tracker](https://github.com/anuko/timetracker), a simple, easy to
+  use, open source time tracking system. Available as
+  [services.anuko-time-tracker](#opt-services.anuko-time-tracker.enable).
 
-- The [services.woodpecker-server](#opt-services.woodpecker-server.environmentFile) type was changed to list of paths to be more consistent to the woodpecker-agent module
+- [Prometheus MySQL exporter](https://github.com/prometheus/mysqld_exporter), a
+  MySQL server exporter for Prometheus. Available as
+  [services.prometheus.exporters.mysqld](#opt-services.prometheus.exporters.mysqld.enable).
 
-- The module [services.ankisyncd](#opt-services.ankisyncd.package) has been switched to [anki-sync-server-rs](https://github.com/ankicommunity/anki-sync-server-rs) from the old python version, which was difficult to update, had not been updated in a while, and did not support recent versions of anki.
-Unfortunately all servers supporting new clients (newer version of anki-sync-server, anki's built in sync server and this new rust package) do not support the older sync protocol that was used in the old server, so such old clients will also need updating and in particular the anki package in nixpkgs is also being updated in this release.
-The module update takes care of the new config syntax and the data itself (user login and cards) are compatible, so users of the module will be able to just log in again after updating both client and server without any extra action.
+- [LibreNMS](https://www.librenms.org), a auto-discovering PHP/MySQL/SNMP based
+  network monitoring. Available as
+  [services.librenms](#opt-services.librenms.enable).
 
-- `services.matrix-synapse` has new options to configure worker processes for matrix-synapse using [`services.matrix-synapse.workers`](#opt-services.matrix-synapse.workers). It's also now possible to configure a local redis server using [`services.matrix-synapse.configureRedisLocally`](#opt-services.matrix-synapse.configureRedisLocally).
+- [Livebook](https://livebook.dev/), an interactive notebook with support for
+  Elixir, graphs, machine learning, and more. Available as
+  [services.livebook](#opt-services.livebook.enableUserService).
 
-- `services.nginx` gained a `defaultListen` option at server-level with support for PROXY protocol listeners, also `proxyProtocol` is now exposed in `services.nginx.virtualHosts.<name>.listen` option. It is now possible to run PROXY listeners and non-PROXY listeners at a server-level, see [#213510](https://github.com/NixOS/nixpkgs/pull/213510/) for more details.
+- [sitespeed-io](https://sitespeed.io), a tool that can generate metrics such
+  as timings and diagnostics for websites. Available as
+  [services.sitespeed-io](#opt-services.sitespeed-io.enable).
 
-- `services.restic.backups` now adds wrapper scripts to your system path, which set the same environment variables as the service, so restic operations can easily be run from the command line. This behavior can be disabled by setting `createWrapper` to `false`, per backup configuration.
+- [stalwart-mail](https://stalw.art), an all-in-one email server (SMTP, IMAP,
+  JMAP). Available as
+  [services.stalwart-mail](#opt-services.stalwart-mail.enable).
 
-- `services.prometheus.exporters` has a new exporter to monitor electrical power consumption based on PowercapRAPL sensor called [Scaphandre](https://github.com/hubblo-org/scaphandre), see [#239803](https://github.com/NixOS/nixpkgs/pull/239803) for more details.
 
-- The MariaDB C client library was upgraded from 3.2.x to 3.3.x. It is recommended to review the [upstream release notes](https://mariadb.com/kb/en/mariadb-connector-c-33-release-notes/).
+- [tang](https://github.com/latchset/tang), a server for binding data to
+  network presence. Available as [services.tang](#opt-services.tang.enable).
 
-- The module `services.calibre-server` has new options to configure the `host`, `port`, `auth.enable`, `auth.mode` and `auth.userDb` path, see [#216497](https://github.com/NixOS/nixpkgs/pull/216497/) for more details.
+- [Jool](https://nicmx.github.io/Jool/en/index.html), a kernelspace NAT64 and
+  SIIT implementation providing translation between IPv4 and IPv6. Available as
+  [networking.jool.enable](#opt-networking.jool.enable).
 
-- Mattermost has been upgraded to extended support version 8.1 as the previously
-  packaged extended support version 7.8 is [reaching end of life](https://docs.mattermost.com/upgrade/extended-support-release.html).
-  Migration may take some time, see the [changelog](https://docs.mattermost.com/install/self-managed-changelog.html#release-v8-1-extended-support-release)
-  and [important upgrade notes](https://docs.mattermost.com/upgrade/important-upgrade-notes.html).
+- [Home Assistant
+  Satellite](https://github.com/synesthesiam/homeassistant-satellite), a
+  streaming audio satellite for Home Assistant voice pipelines, where you can
+  reuse existing mic and speaker hardware. Available as
+  [services.homeassistant-satellite](#opt-services.homeassistant-satellite.enable).
 
-- `services.prometheus.exporters` has a new [exporter](https://github.com/hipages/php-fpm_exporter) to monitor PHP-FPM processes, see [#240394](https://github.com/NixOS/nixpkgs/pull/240394) for more details.
+- [Apache Guacamole](https://guacamole.apache.org/), a cross-platform,
+  clientless remote desktop gateway. Available as
+  [services.guacamole-server](#opt-services.guacamole-server.enable) and
+  [services.guacamole-client](#opt-services.guacamole-client.enable) services.
 
-- `services.github-runner` / `services.github-runners.<name>` gained the option `nodeRuntimes`. The option defaults to `[ "node20" ]`, i.e., the service supports Node.js 20 GitHub Actions only. The list of Node.js versions accepted by `nodeRuntimes` tracks the versions the upstream GitHub Actions runner supports. See [#249103](https://github.com/NixOS/nixpkgs/pull/249103) for details.
+- [pgBouncer](https://www.pgbouncer.org), a PostgreSQL connection pooler.
+  Available as [services.pgbouncer](#opt-services.pgbouncer.enable).
 
-- `programs.gnupg.agent.pinentryFlavor` is now set in `/etc/gnupg/gpg-agent.conf`, and will no longer take precedence over a `pinentry-program` set in `~/.gnupg/gpg-agent.conf`.
+- [Goss](https://goss.rocks/), a YAML based serverspec alternative tool for
+  validating a server's configuration. Available as
+  [services.goss](#opt-services.goss.enable).
 
-- `programs.gnupg` now has the option `agent.settings` to set verbatim config values in `/etc/gnupg/gpg-agent.conf`.
+- [trust-dns](https://trust-dns.org/), a Rust based DNS server built to be safe
+  and secure from the ground up. Available as
+  [services.trust-dns](#opt-services.trust-dns.enable).
 
-- `dockerTools.buildImage`, `dockerTools.buildLayeredImage` and `dockerTools.streamLayeredImage` now use `lib.makeOverridable` to allow `dockerTools`-based images to be customized more efficiently at the nix-level.
+- [osquery](https://www.osquery.io/), a SQL powered operating system
+  instrumentation, monitoring, and analytics. Available as
+  [services.osquery](#opt-services.osquery.enable).
 
-- `services.influxdb2` now supports doing an automatic initial setup and provisioning of users, organizations, buckets and authentication tokens, see [#249502](https://github.com/NixOS/nixpkgs/pull/249502) for more details.
+- [ebusd](https://ebusd.eu), a daemon for handling communication with eBUS
+  devices connected to a 2-wire bus system ("energy bus" used by numerous
+  heating systems). Available as [services.ebusd](#opt-services.ebusd.enable).
 
-- `wrapHelm` now exposes `passthru.pluginsDir` which can be passed to `helmfile`. For convenience, a top-level package `helmfile-wrapped` has been added, which inherits `passthru.pluginsDir` from `kubernetes-helm-wrapped`. See [#217768](https://github.com/NixOS/nixpkgs/issues/217768) for details.
+- [systemd-sysupdate](https://www.freedesktop.org/software/systemd/man/systemd-sysupdate.html),
+  atomically updates the host OS, container images, portable service images or
+  other sources. Available as [systemd.sysupdate](opt-systemd.sysupdate).
 
-- `boot.initrd.network.udhcp.enable` allows control over dhcp during stage 1 regardless of what `networking.useDHCP` is set to.
+- [eris-server](https://codeberg.org/eris/eris-go), an implementation of the
+  Encoding for Robust Immutable Storage (ERIS). Available as
+  [services.eris-server](#opt-services.eris-server.enable).
 
-- Suricata was upgraded from 6.0 to 7.0 and no longer considers HTTP/2 support as experimental, see [upstream release notes](https://forum.suricata.io/t/suricata-7-0-0-released/3715) for more details.
+- [forgejo](https://forgejo.org/), a git forge and drop-in replacement for
+  Gitea. Available as [services.forgejo](#opt-services.forgejo.enable).
 
-- Cloud support in the `netdata` package is now disabled by default. To enable it use the `netdataCloud` package.
+- `hardware/infiniband.nix` adds infiniband subnet manager support using an
+  [opensm](https://github.com/linux-rdma/opensm) systemd-template service,
+  instantiated on card guids. The module also adds kernel modules and cli
+  tooling to help administrators debug and measure performance. Available as
+  [hardware.infiniband.enable](#opt-hardware.infiniband.enable).
 
-- `networking.nftables` now has the option `networking.nftables.table.<table>` to create tables
-  and have them be updated atomically, instead of flushing the ruleset.
+- [zwave-js](https://github.com/zwave-js/zwave-js-server), a small server
+  wrapper around Z-Wave JS to access it via a WebSocket. Available as
+  [services.zwave-js](#opt-services.zwave-js.enable).
 
-- `networking.nftables` is no longer flushing all rulesets on every reload.
-  Use `networking.nftables.flushRuleset = true;` to get back the old behaviour.
+- [Honk](https://humungus.tedunangst.com/r/honk), a complete ActivityPub server
+  with minimal setup and support costs. Available as
+  [services.honk](#opt-services.honk.enable).
 
-- The `cawbird` package is dropped from nixpkgs, as it got broken by the Twitter API closing down and has been abandoned upstream.
+- [ferretdb](https://www.ferretdb.io/), an open-source proxy, converting the
+  MongoDB 6.0+ wire protocol queries to PostgreSQL or SQLite. Available as
+  [services.ferretdb](options.html#opt-services.ferretdb.enable).
 
-- `hardware.nvidia` gained `datacenter` options for enabling NVIDIA Data Center drivers and configuration of NVLink/NVSwitch topologies through `nv-fabricmanager`.
+- [MicroBin](https://microbin.eu/), a feature rich, performant and secure text
+  and file sharing web application, a "paste bin". Available as
+  [services.microbin](#opt-services.microbin.enable).
 
-- Certificate generation via the `security.acme` now limits the concurrent number of running certificate renewals and generation jobs, to avoid spiking resource usage when processing many certificates at once. The limit defaults to *5* and can be adjusted via `maxConcurrentRenewals`. Setting it to *0* disables the limits altogether.
+- [NNCP](http://www.nncpgo.org/), nncp-daemon and nncp-caller services.
+  Available as [programs.nncp.settings](#opt-programs.nncp.settings) and
+  [services.nncp](#opt-services.nncp.caller.enable).
+
+- [FastNetMon Advanced](https://fastnetmon.com/product-overview/), a commercial
+  high performance DDoS detector and sensor. Available as
+  [services.fastnetmon-advanced](#opt-services.fastnetmon-advanced.enable).
+
+- [tuxedo-rs](https://github.com/AaronErhardt/tuxedo-rs), Rust utilities for
+  interacting with hardware from TUXEDO Computers. Available as
+  [hardware.tuxedo-rs](#opt-hardware.tuxedo-rs.enable).
+
+- [certspotter](https://github.com/SSLMate/certspotter), a certificate
+  transparency log monitor. Available as
+  [services.certspotter](#opt-services.certspotter.enable).
+
+- [audiobookshelf](https://github.com/advplyr/audiobookshelf/), a self-hosted
+  audiobook and podcast server. Available as
+  [services.audiobookshelf](#opt-services.audiobookshelf.enable).
+
+- [ZITADEL](https://zitadel.com), a turnkey identity and access management
+  platform. Available as [services.zitadel](#opt-services.zitadel.enable).
+
+- [exportarr](https://github.com/onedr0p/exportarr), Prometheus Exporters for
+  Bazarr, Lidarr, Prowlarr, Radarr, Readarr, and Sonarr. Available as
+  [services.prometheus.exporters.exportarr-bazarr](#opt-services.prometheus.exporters.exportarr-bazarr.enable)/[services.prometheus.exporters.exportarr-lidarr](#opt-services.prometheus.exporters.exportarr-lidarr.enable)/[services.prometheus.exporters.exportarr-prowlarr](#opt-services.prometheus.exporters.exportarr-prowlarr.enable)/[services.prometheus.exporters.exportarr-radarr](#opt-services.prometheus.exporters.exportarr-radarr.enable)/[services.prometheus.exporters.exportarr-readarr](#opt-services.prometheus.exporters.exportarr-readarr.enable)/[services.prometheus.exporters.exportarr-sonarr](#opt-services.prometheus.exporters.exportarr-sonarr.enable).
+
+- [netclient](https://github.com/gravitl/netclient), an automated WireGuard
+  Management Client. Available as
+  [services.netclient](#opt-services.netclient.enable).
+
+- [trunk-ng](https://github.com/ctron/trunk), A fork of `trunk`: Build, bundle
+  & ship your Rust WASM application to the web
+
+- [virt-manager](https://virt-manager.org/), an UI for managing virtual
+  machines in libvirt. Available as
+  [programs.virt-manager](#opt-programs.virt-manager.enable).
+
+- [Soft Serve](https://github.com/charmbracelet/soft-serve), a tasty,
+  self-hostable Git server for the command line. Available as
+  [services.soft-serve](#opt-services.soft-serve.enable).
+
+- [Rosenpass](https://rosenpass.eu/), a service for post-quantum-secure VPNs
+  with WireGuard. Available as
+  [services.rosenpass](#opt-services.rosenpass.enable).
+
+- [c2FmZQ](https://github.com/c2FmZQ/c2FmZQ/), an application that can securely
+  encrypt, store, and share files, including but not limited to pictures and
+  videos. Available as
+  [services.c2fmzq-server](#opt-services.c2fmzq-server.enable).
+
+- [preload](http://sourceforge.net/projects/preload), a service that makes
+  applications run faster by prefetching binaries and shared objects.
+  Available as [services.preload](#opt-services.preload.enable).
+
+### Other Notable Changes {#sec-release-23.11-nixos-notable-changes}
+
+- The new option `system.switch.enable` was added. It is enabled by default.
+  Disabling it makes the system unable to be reconfigured via `nixos-rebuild`.
+  This is of advantage for image based appliances where updates are handled
+  outside the image.
+
+- `services.searx` receives new options for better SearXNG support. This
+  includes options for the built-in rate limiter, bot protection and
+  automatically configuring a local Redis server.
+
+- The iptables firewall module installs the `nixos-firewall-tool` now which
+  allows the user to easily temporarily open ports through the firewall.
+
+- A new option was added to the virtualisation module that enables specifying
+  explicitly named network interfaces in QEMU VMs. The existing
+  `virtualisation.vlans` is still supported for cases where the name of the
+  network interface is irrelevant.
+
+- `services.outline` can be configured to use local filesystem storage now.
+  Previously ony S3 storage was possible. This may be set using
+  [services.outline.storage.storageType](#opt-services.outline.storage.storageType).
+
+- `pkgs.openvpn3` optionally supports systemd-resolved now. `programs.openvpn3`
+  will automatically enable systemd-resolved support if
+  [services.resolved.enable](#opt-services.resolved.enable) is set to true.
+
+- The
+  [services.woodpecker-server.environmentFile](#opt-services.woodpecker-server.environmentFile)
+  type was changed to list of paths to be more consistent to the
+  woodpecker-agent module
+
+- `services.matrix-synapse` has new options to configure worker processes for
+  matrix-synapse using
+  [`services.matrix-synapse.workers`](#opt-services.matrix-synapse.workers).
+  Configuring a local redis server using
+  [`services.matrix-synapse.configureRedisLocally`](#opt-services.matrix-synapse.configureRedisLocally)
+  is also possible now.
+
+- The `services.nginx` module gained a `defaultListen` option at server-level
+  with support for PROXY protocol listeners. Also `proxyProtocol` is exposed in
+  the `services.nginx.virtualHosts.<name>.listen` option now. This it is
+  possible to run PROXY listeners and non-PROXY listeners at a server-level.
+  Refer to [PR #213510](https://github.com/NixOS/nixpkgs/pull/213510/) for more
+  details.
+
+- `services.restic.backups` adds wrapper scripts to your system path now. This
+  wrapper script sets the same environment variables as the service, so restic
+  operations can easily be run from the command line. This behavior can be
+  disabled by setting `createWrapper` to `false`, for each backup
+  configuration.
+
+- `services.prometheus.exporters` has a new exporter to monitor electrical
+  power consumption based on PowercapRAPL sensor called
+  [Scaphandre](https://github.com/hubblo-org/scaphandre). Refer to [PR
+  #239803](https://github.com/NixOS/nixpkgs/pull/239803) for more details.
+
+- The `services.calibre-server` module has new options to configure the `host`,
+  `port`, `auth.enable`, `auth.mode` and `auth.userDb` path. Refer to [PR
+  #216497](https://github.com/NixOS/nixpkgs/pull/216497/) for more details.
+
+- `services.prometheus.exporters` has a new
+  [exporter](https://github.com/hipages/php-fpm_exporter) to monitor PHP-FPM
+  processes. Refer to [PR
+  #240394](https://github.com/NixOS/nixpkgs/pull/240394) for more details.
+
+- `services.github-runner` and `services.github-runners.<name>` gained the
+  option `nodeRuntimes`. This option defaults to `[ "node20" ]`.  I.e., the
+  service supports Node.js 20 GitHub Actions only. The list of Node.js versions
+  accepted by `nodeRuntimes` tracks the versions the upstream GitHub Actions
+  runner supports. Refer to [PR
+  #249103](https://github.com/NixOS/nixpkgs/pull/249103) for details.
+
+- `programs.gnupg` has the option `agent.settings` now. This allows setting
+  verbatim config values in `/etc/gnupg/gpg-agent.conf`.
+
+- `dockerTools.buildImage`, `dockerTools.buildLayeredImage` and
+  `dockerTools.streamLayeredImage` use `lib.makeOverridable` now . This allows
+  `dockerTools`-based images to be customized more efficiently at the Nix
+  level.
+
+- `services.influxdb2` supports doing an automatic initial setup and
+  provisioning of users, organizations, buckets and authentication tokens now.
+  Refer to [PR #249502](https://github.com/NixOS/nixpkgs/pull/249502) for more
+  details.
+
+- `wrapHelm` exposes `passthru.pluginsDir` now which can be passed to
+  `helmfile`. For convenience, a top-level package `helmfile-wrapped` has been
+  added, which inherits `passthru.pluginsDir` from `kubernetes-helm-wrapped`.
+  Refer to [PR #217768](https://github.com/NixOS/nixpkgs/issues/217768) for
+  more details.
+
+- The `boot.initrd.network.udhcp.enable` option allows control over DHCP during
+  Stage 1 regardless of what `networking.useDHCP` is set to.
+
+- `networking.nftables` has the option `networking.nftables.table.<table>` now. This creates tables
+  and have them be updated atomically, instead of flushing the ruleset.
 
-- New `boot.bcache.enable` (default enabled) allows completely removing `bcache` mount support.
+- `hardware.nvidia` gained `datacenter` options for enabling NVIDIA Data Center
+  drivers and configuration of NVLink/NVSwitch topologies through
+  `nv-fabricmanager`.
 
-- The module `services.mbpfan` now has the option `aggressive` enabled by default for better heat moderation. You can disable it for upstream defaults.
+- The new `boot.bcache.enable` option allows completely removing `bcache`
+  mount support. It is enabled by default.
 
-- `security.sudo` now provides two extra options, that do not change the
+- `security.sudo` provides two extra options now, while not changing the
   module's default behaviour:
   - `defaultOptions` controls the options used for the default rules;
   - `keepTerminfo` controls whether `TERMINFO` and `TERMINFO_DIRS` are preserved
     for `root` and the `wheel` group.
 
-- `virtualisation.googleComputeImage` now provides `efi` option to support UEFI booting.
+- `virtualisation.googleComputeImage` provides a `efi` option to support UEFI
+  booting now.
 
-- CoreDNS can now be built with external plugins by overriding `externalPlugins` and `vendorHash` arguments like this:
+- CoreDNS may be built with external plugins now. This may be done by
+  overriding `externalPlugins` and `vendorHash` arguments like this:
 
   ```
   services.coredns = {
@@ -535,57 +1238,69 @@ The module update takes care of the new config syntax and the data itself (user
   };
   ```
 
-  To get the necessary SRI hash, set `vendorHash = "";`. The build will fail and produce the correct `vendorHash` in the error message.
-
-  If you use this feature, updates to CoreDNS may require updating `vendorHash` by following these steps again.
+  To get the necessary SRI hash, set `vendorHash = "";`. The build will fail
+  and produce the correct `vendorHash` in the error message.
 
-- `postgresql_11` has been removed since it'll stop receiving fixes on November 9 2023.
+  If you use this feature, updates to CoreDNS may require updating `vendorHash`
+  by following these steps again.
 
-- `ffmpeg` default upgraded from `ffmpeg_5` to `ffmpeg_6`.
+- Using `fusuma` enables the following plugins now:
+  [appmatcher](https://github.com/iberianpig/fusuma-plugin-appmatcher),
+  [keypress](https://github.com/iberianpig/fusuma-plugin-keypress),
+  [sendkey](https://github.com/iberianpig/fusuma-plugin-sendkey),
+  [tap](https://github.com/iberianpig/fusuma-plugin-tap) and
+  [wmctrl](https://github.com/iberianpig/fusuma-plugin-wmctrl).
 
-- `fusuma` now enables the following plugins: [appmatcher](https://github.com/iberianpig/fusuma-plugin-appmatcher), [keypress](https://github.com/iberianpig/fusuma-plugin-keypress), [sendkey](https://github.com/iberianpig/fusuma-plugin-sendkey), [tap](https://github.com/iberianpig/fusuma-plugin-tap) and [wmctrl](https://github.com/iberianpig/fusuma-plugin-wmctrl).
+- The Home Assistant module offers support for installing custom components and
+  lovelace modules now. Available at
+  [`services.home-assistant.customComponents`](#opt-services.home-assistant.customComponents)
+  and
+  [`services.home-assistant.customLovelaceModules`](#opt-services.home-assistant.customLovelaceModules).
 
-- `services.bitcoind` now properly respects the `enable` option.
+- TeX Live environments can now be built with the new `texlive.withPackages`.
+  The procedure for creating custom TeX packages has been changed. Refer to the
+  [Nixpkgs
+  manual](https://nixos.org/manual/nixpkgs/stable/#sec-language-texlive-custom-packages)
+  for more details.
 
-- The Home Assistant module now offers support for installing custom components and lovelace modules. Available at [`services.home-assistant.customComponents`](#opt-services.home-assistant.customComponents) and [`services.home-assistant.customLovelaceModules`](#opt-services.home-assistant.customLovelaceModules).
+- In `wxGTK32`, the webkit module `wxWebView` has been enabled on all builds.
+  Prior releases only enabled this on Darwin.
 
-- The argument `vendorSha256` of `buildGoModule` is deprecated. Use `vendorHash` instead. ([\#259999](https://github.com/NixOS/nixpkgs/pull/259999))
+- Support for WiFi6 (IEEE 802.11ax) and WPA3-SAE-PK was enabled in the
+  `hostapd` package, along with a significant rework of the hostapd module.
 
-## Nixpkgs internals {#sec-release-23.11-nixpkgs-internals}
-
-- Node.js v14, v16 has been removed as they were end of life. Any dependent packages that contributors were not able to reasonably upgrade were dropped after a month of notice to their maintainers, were **removed**.
-  - This includes VSCode Server.
-  - This includes Kibana 7 as the ELK stack is unmaintained in nixpkgs and is marked for slow removal.
+- LXD supports virtual machine instances now to complement the existing
+  container support.
 
-- The use of `sourceRoot = "source";`, `sourceRoot = "source/subdir";`, and similar lines in package derivations using the default `unpackPhase` is deprecated as it requires `unpackPhase` to always produce a directory named "source". Use `sourceRoot = src.name`, `sourceRoot = "${src.name}/subdir";`, or `setSourceRoot = "sourceRoot=$(echo */subdir)";` or similar instead.
+- The `nixos-rebuild` command has been given a `list-generations` subcommand.
+  Refer to `man nixos-rebuild` for more details.
 
-- The `django` alias in the python package set was upgraded to Django 4.x.
-  Applications that consume Django should always pin their python environment
-  to a compatible major version, so they can move at their own pace.
+- [`sudo-rs`], a reimplementation of `sudo` in Rust, is now supported.
+  An experimental new module `security.sudo-rs` was added.
+  Switching to it (via ` security.sudo-rs.enable = true;`) introduces
+  slight changes in sudo behaviour, due to `sudo-rs`' current limitations:
+  - terminfo-related environment variables aren't preserved for `root` and `wheel`;
+  - `root` and `wheel` are not given the ability to set (or preserve)
+    arbitrary environment variables.
 
-  ```nix
-  python = python3.override {
-    packageOverrides = self: super: {
-      django = super.django_3;
-    };
-  };
-  ```
+  **Note:** The `sudo-rs` module only takes configuration through `security.sudo-rs`,
+  and in particular does not automatically use previously-set rules; this could be
+  achieved with `security.sudo-rs.extraRules = security.sudo.extraRules;` for instance.
 
-- The `qemu-vm.nix` module by default now identifies block devices via
-  persistent names available in `/dev/disk/by-*`. Because the rootDevice is
-  identified by its filesystem label, it needs to be formatted before the VM is
-  started. The functionality of automatically formatting the rootDevice in the
-  initrd is removed from the QEMU module. However, for tests that depend on
-  this functionality, a test utility for the scripted initrd is added
-  (`nixos/tests/common/auto-format-root-device.nix`). To use this in a NixOS
-  test, import the module, e.g. `imports = [
-  ./common/auto-format-root-device.nix ];` When you use the systemd initrd, you
-  can automatically format the root device by setting
-  `virtualisation.fileSystems."/".autoFormat = true;`.
+[`sudo-rs`]: https://github.com/memorysafety/sudo-rs/
 
-- `python3.pkgs.flitBuildHook` has been removed. Use `flit-core` and `format = "pyproject"` instead.
+- There is a new NixOS option when writing NixOS tests
+  `testing.initrdBackdoor`, that enables `backdoor.service` in initrd. Requires
+  `boot.initrd.systemd.enable` to be enabled. Boot will pause in Stage 1 at
+  `initrd.target`, and will listen for commands from the `Machine` python
+  interface, just like Stage 2 normally does. This enables commands to be sent
+  to test and debug Stage 1. Use `machine.switch_root()` to leave Stage 1 and
+  proceed to Stage 2.
 
-- The `extend` function of `llvmPackages` has been removed due it coming from the `tools` attrset thus only extending the `tool` attrset. A possible replacement is to construct the set from `libraries` and `tools`, or patch nixpkgs.
+- The Linux kernel module `msr` (refer to
+  [`msr(4)`](https://man7.org/linux/man-pages/man4/msr.4.html)), which provides
+  an interface to read and write the model-specific registers (MSRs) of an x86
+  CPU, can now be configured via `hardware.cpu.x86.msr`.
 
 - The `qemu-vm.nix` module now supports disabling overriding `fileSystems` with
   `virtualisation.fileSystems`. This enables the user to boot VMs from
@@ -593,12 +1308,121 @@ The module update takes care of the new config syntax and the data itself (user
   qemu-vm module from overriding `fileSystems` by setting
   `virtualisation.fileSystems = lib.mkForce { };`.
 
-- The `electron` packages now places its application files in `$out/libexec/electron` instead of `$out/lib/electron`. Packages using electron-builder will fail to build and need to be adjusted by changing `lib` to `libexec`.
-
-- `teleport` has been upgraded from major version 12 to major version 14. Please see upstream [upgrade instructions](https://goteleport.com/docs/management/operations/upgrading/) and release notes for versions [13](https://goteleport.com/docs/changelog/#1300-050823) and [14](https://goteleport.com/docs/changelog/#1400-092023). Note that Teleport does not officially support upgrades across more than one major version at a time. If you're running Teleport server components, it is recommended to first upgrade to an intermediate 13.x version by setting `services.teleport.package = pkgs.teleport_13`. Afterwards, this option can be removed to upgrade to the default version (14).
+- When using [split parity files](https://www.snapraid.it/manual#7.1) in `snapraid`,
+  the snapraid-sync systemd service will no longer fail to run.
+
+## Nixpkgs Library {#sec-release-23.11-nixpkgs-lib}
+
+### Breaking Changes {#sec-release-23.11-lib-breaking}
+
+- [`lib.lists.foldl'`](https://nixos.org/manual/nixpkgs/unstable#function-library-lib.lists.foldl-prime)
+  now always evaluates the initial accumulator argument first. If you depend on
+  the lazier behavior, consider using
+  [`lib.lists.foldl`](https://nixos.org/manual/nixpkgs/unstable#function-library-lib.lists.foldl)
+  or
+  [`builtins.foldl'`](https://nixos.org/manual/nix/stable/language/builtins.html#builtins-foldl')
+  instead.
+- [`lib.attrsets.foldlAttrs`](https://nixos.org/manual/nixpkgs/unstable#function-library-lib.attrsets.foldlAttrs)
+  now always evaluates the initial accumulator argument first.
+- Now that the internal NixOS transition to Markdown documentation is complete,
+  `lib.options.literalDocBook` has been removed after deprecation in 22.11.
+- `lib.types.string` is now fully deprecated and gives a warning when used.
+
+### Additions and Improvements {#sec-release-23.11-lib-additions-improvements}
+
+- [`lib.fileset`](https://nixos.org/manual/nixpkgs/unstable#sec-functions-library-fileset):
+  A new sub-library to select local files to use for sources, designed to be
+  easy and safe to use.
+
+  This aims to be a replacement for `lib.sources`-based filtering. To learn
+  more about it, see [the blog
+  post](https://www.tweag.io/blog/2023-11-28-file-sets/) or [the
+  tutorial](https://nix.dev/tutorials/file-sets).
+
+- [`lib.gvariant`](https://nixos.org/manual/nixpkgs/unstable#sec-functions-library-gvariant):
+  A partial and basic implementation of GVariant formatted strings. See
+  [GVariant Format
+  Strings](https://docs.gtk.org/glib/gvariant-format-strings.html) for details.
+
+  :::{.warning}
+  This API is not considered fully stable and it might therefore
+  change in backwards incompatible ways without prior notice.
+  :::
+
+- [`lib.asserts`](https://nixos.org/manual/nixpkgs/unstable#sec-functions-library-asserts):
+  New function:
+  [`assertEachOneOf`](https://nixos.org/manual/nixpkgs/unstable#function-library-lib.asserts.assertEachOneOf).
+- [`lib.attrsets`](https://nixos.org/manual/nixpkgs/unstable#sec-functions-library-attrsets):
+  New function:
+  [`attrsToList`](https://nixos.org/manual/nixpkgs/unstable#function-library-lib.attrsets.attrsToList).
+- [`lib.customisation`](https://nixos.org/manual/nixpkgs/unstable#sec-functions-library-customisation):
+  New function:
+  [`makeScopeWithSplicing'`](https://nixos.org/manual/nixpkgs/unstable#function-library-lib.customisation.makeScopeWithSplicing-prime).
+- [`lib.fixedPoints`](https://nixos.org/manual/nixpkgs/unstable#sec-functions-library-fixedPoints):
+  Documentation improvements for
+  [`lib.fixedPoints.fix`](https://nixos.org/manual/nixpkgs/unstable#function-library-lib.fixedPoints.fix).
+- `lib.generators`: New functions:
+  [`mkDconfKeyValue`](https://nixos.org/manual/nixpkgs/unstable#function-library-lib.generators.mkDconfKeyValue),
+  [`toDconfINI`](https://nixos.org/manual/nixpkgs/unstable#function-library-lib.generators.toDconfINI).
+
+  `lib.generators.toKeyValue` now supports the `indent` attribute in its first
+  argument.
+- [`lib.lists`](https://nixos.org/manual/nixpkgs/unstable#sec-functions-library-lists):
+  New functions:
+  [`findFirstIndex`](https://nixos.org/manual/nixpkgs/unstable#function-library-lib.lists.findFirstIndex),
+  [`hasPrefix`](https://nixos.org/manual/nixpkgs/unstable#function-library-lib.lists.hasPrefix),
+  [`removePrefix`](https://nixos.org/manual/nixpkgs/unstable#function-library-lib.lists.removePrefix),
+  [`commonPrefix`](https://nixos.org/manual/nixpkgs/unstable#function-library-lib.lists.commonPrefix),
+  [`allUnique`](https://nixos.org/manual/nixpkgs/unstable#function-library-lib.lists.allUnique).
+
+  Documentation improvements for
+  [`lib.lists.foldl'`](https://nixos.org/manual/nixpkgs/unstable#function-library-lib.lists.foldl-prime).
+- [`lib.meta`](https://nixos.org/manual/nixpkgs/unstable#sec-functions-library-meta):
+  Documentation of functions now gets rendered
+- [`lib.path`](https://nixos.org/manual/nixpkgs/unstable#sec-functions-library-path):
+  New functions:
+  [`hasPrefix`](https://nixos.org/manual/nixpkgs/unstable#function-library-lib.path.hasPrefix),
+  [`removePrefix`](https://nixos.org/manual/nixpkgs/unstable#function-library-lib.path.removePrefix),
+  [`splitRoot`](https://nixos.org/manual/nixpkgs/unstable#function-library-lib.path.splitRoot),
+  [`subpath.components`](https://nixos.org/manual/nixpkgs/unstable#function-library-lib.path.subpath.components).
+- [`lib.strings`](https://nixos.org/manual/nixpkgs/unstable#sec-functions-library-strings):
+  New functions:
+  [`replicate`](https://nixos.org/manual/nixpkgs/unstable#function-library-lib.strings.replicate),
+  [`cmakeOptionType`](https://nixos.org/manual/nixpkgs/unstable#function-library-lib.strings.cmakeOptionType),
+  [`cmakeBool`](https://nixos.org/manual/nixpkgs/unstable#function-library-lib.strings.cmakeBool),
+  [`cmakeFeature`](https://nixos.org/manual/nixpkgs/unstable#function-library-lib.strings.cmakeFeature).
+- [`lib.trivial`](https://nixos.org/manual/nixpkgs/unstable#sec-functions-library-trivial):
+  New function:
+  [`mirrorFunctionArgs`](https://nixos.org/manual/nixpkgs/unstable#function-library-lib.trivial.mirrorFunctionArgs).
+- `lib.systems`: New function:
+  [`equals`](https://nixos.org/manual/nixpkgs/unstable#function-library-lib.systems.equals).
+- [`lib.options`](https://nixos.org/manual/nixpkgs/unstable#sec-functions-library-options):
+  Improved documentation for
+  [`mkPackageOption`](https://nixos.org/manual/nixpkgs/unstable#function-library-lib.options.mkPackageOption).
+
+  [`mkPackageOption`](https://nixos.org/manual/nixpkgs/unstable#function-library-lib.options.mkPackageOption).
+  now also supports the `pkgsText` attribute.
+
+Module system:
+- Options in the `options` module argument now have the `declarationPositions`
+  attribute containing the position where the option was declared:
+  ```
+  $ nix-repl -f '<nixpkgs/nixos>' [...]
+  nix-repl> :p options.environment.systemPackages.declarationPositions
+  [ {
+    column = 7;
+    file = "/nix/store/vm9zf9wvfd628cchj0hdij1g4hzjrcz9-source/nixos/modules/config/system-path.nix";
+    line = 62;
+  } ]
+  ```
 
-- The Linux kernel module `msr` (see [`msr(4)`](https://man7.org/linux/man-pages/man4/msr.4.html)), which provides an interface to read and write the model-specific registers (MSRs) of an x86 CPU, can now be configured via `hardware.cpu.x86.msr`.
+  Not to be confused with `definitionsWithLocations`, which is the same but for option _definitions_.
+- Improved error message for option declarations missing `mkOption`
 
-- Docker now defaults to 24, as 20.10 is stopping to receive security updates and bug fixes after [December 10, 2023](https://github.com/moby/moby/discussions/45104).
+### Deprecations {#sec-release-23.11-lib-deprecations}
 
-- There is a new NixOS option when writing NixOS tests `testing.initrdBackdoor`, that enables `backdoor.service` in initrd. Requires `boot.initrd.systemd.enable` to be enabled. Boot will pause in stage 1 at `initrd.target`, and will listen for commands from the `Machine` python interface, just like stage 2 normally does. This enables commands to be sent to test and debug stage 1. Use `machine.switch_root()` to leave stage 1 and proceed to stage 2.
+- `lib.meta.getExe pkg` (also available as `lib.getExe`) now gives a warning if
+  `pkg.meta.mainProgram` is not set, but it continues to default to the
+  derivation name. Nixpkgs accepts PRs that set `meta.mainProgram` on packages
+  where it makes sense. Use `lib.getExe' pkg "some-command"` to avoid the
+  warning and/or select a different executable.
diff --git a/nixpkgs/nixos/doc/manual/release-notes/rl-2405.section.md b/nixpkgs/nixos/doc/manual/release-notes/rl-2405.section.md
new file mode 100644
index 000000000000..749ebc5cb13b
--- /dev/null
+++ b/nixpkgs/nixos/doc/manual/release-notes/rl-2405.section.md
@@ -0,0 +1,41 @@
+# Release 24.05 (“Uakari”, 2024.05/??) {#sec-release-24.05}
+
+Support is planned until the end of December 2024, handing over to 24.11.
+
+## Highlights {#sec-release-24.05-highlights}
+
+In addition to numerous new and upgraded packages, this release has the following highlights:
+
+<!-- To avoid merge conflicts, consider adding your item at an arbitrary place in the list instead. -->
+
+- Create the first release note entry in this section!
+
+## New Services {#sec-release-24.05-new-services}
+
+<!-- To avoid merge conflicts, consider adding your item at an arbitrary place in the list instead. -->
+
+- [maubot](https://github.com/maubot/maubot), a plugin-based Matrix bot framework. Available as [services.maubot](#opt-services.maubot.enable).
+
+- [Anki Sync Server](https://docs.ankiweb.net/sync-server.html), the official sync server built into recent versions of Anki. Available as [services.anki-sync-server](#opt-services.anki-sync-server.enable).
+
+## Backward Incompatibilities {#sec-release-24.05-incompatibilities}
+
+<!-- To avoid merge conflicts, consider adding your item at an arbitrary place in the list instead. -->
+
+- `mkosi` was updated to v19. Parts of the user interface have changed. Consult the
+  [release notes](https://github.com/systemd/mkosi/releases/tag/v19) for a list of changes.
+
+## Other Notable Changes {#sec-release-24.05-notable-changes}
+
+<!-- To avoid merge conflicts, consider adding your item at an arbitrary place in the list instead. -->
+
+- Programs written in [Nim](https://nim-lang.org/) are built with libraries selected by lockfiles.
+  The `nimPackages` and `nim2Packages` sets have been removed.
+  See https://nixos.org/manual/nixpkgs/unstable#nim for more information.
+
+- The Yama LSM is now enabled by default in the kernel, which prevents ptracing
+  non-child processes. This means you will not be able to attach gdb to an
+  existing process, but will need to start that process from gdb (so it is a
+  child). Or you can set `boot.kernel.sysctl."kernel.yama.ptrace_scope"` to 0.
+
+- The `hardware.pulseaudio` module now sets permission of pulse user home directory to 755 when running in "systemWide" mode. It fixes [issue 114399](https://github.com/NixOS/nixpkgs/issues/114399).
diff --git a/nixpkgs/nixos/maintainers/scripts/lxd/lxd-container-image-inner.nix b/nixpkgs/nixos/maintainers/scripts/lxd/lxd-container-image-inner.nix
index 62a6e1f9aa3a..ef00c6f86cbd 100644
--- a/nixpkgs/nixos/maintainers/scripts/lxd/lxd-container-image-inner.nix
+++ b/nixpkgs/nixos/maintainers/scripts/lxd/lxd-container-image-inner.nix
@@ -8,7 +8,7 @@
   imports =
     [
       # Include the default lxd configuration.
-      "${modulesPath}/modules/virtualisation/lxc-container.nix"
+      "${modulesPath}/virtualisation/lxc-container.nix"
       # Include the container-specific autogenerated configuration.
       ./lxd.nix
     ];
diff --git a/nixpkgs/nixos/modules/config/pulseaudio.nix b/nixpkgs/nixos/modules/config/pulseaudio.nix
index 80ff6c1aabf7..b10edeb75604 100644
--- a/nixpkgs/nixos/modules/config/pulseaudio.nix
+++ b/nixpkgs/nixos/modules/config/pulseaudio.nix
@@ -305,6 +305,7 @@ in {
         extraGroups = [ "audio" ];
         description = "PulseAudio system service user";
         home = stateDir;
+        homeMode = "755";
         createHome = true;
         isSystemUser = true;
       };
diff --git a/nixpkgs/nixos/modules/config/sysctl.nix b/nixpkgs/nixos/modules/config/sysctl.nix
index 0bc7ab9667f9..452c050b6dda 100644
--- a/nixpkgs/nixos/modules/config/sysctl.nix
+++ b/nixpkgs/nixos/modules/config/sysctl.nix
@@ -69,9 +69,6 @@ in
     # users as these make it easier to exploit kernel vulnerabilities.
     boot.kernel.sysctl."kernel.kptr_restrict" = mkDefault 1;
 
-    # Disable YAMA by default to allow easy debugging.
-    boot.kernel.sysctl."kernel.yama.ptrace_scope" = mkDefault 0;
-
     # Improve compatibility with applications that allocate
     # a lot of memory, like modern games
     boot.kernel.sysctl."vm.max_map_count" = mkDefault 1048576;
diff --git a/nixpkgs/nixos/modules/config/xdg/portal.nix b/nixpkgs/nixos/modules/config/xdg/portal.nix
index e19e5cf28b3b..07d4fa76c2e8 100644
--- a/nixpkgs/nixos/modules/config/xdg/portal.nix
+++ b/nixpkgs/nixos/modules/config/xdg/portal.nix
@@ -8,6 +8,10 @@ let
     mkRenamedOptionModule
     teams
     types;
+
+  associationOptions = with types; attrsOf (
+    coercedTo (either (listOf str) str) (x: lib.concatStringsSep ";" (lib.toList x)) str
+  );
 in
 
 {
@@ -72,20 +76,76 @@ in
         See [#160923](https://github.com/NixOS/nixpkgs/issues/160923) for more info.
       '';
     };
+
+    config = mkOption {
+      type = types.attrsOf associationOptions;
+      default = { };
+      example = {
+        x-cinnamon = {
+          default = [ "xapp" "gtk" ];
+        };
+        pantheon = {
+          default = [ "pantheon" "gtk" ];
+          "org.freedesktop.impl.portal.Secret" = [ "gnome-keyring" ];
+        };
+        common = {
+          default = [ "gtk" ];
+        };
+      };
+      description = lib.mdDoc ''
+        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`
+        for `xdg.portal.config.$desktop` and `portals.conf` for `xdg.portal.config.common`
+        as an exception.
+      '';
+    };
+
+    configPackages = mkOption {
+      type = types.listOf types.package;
+      default = [ ];
+      example = lib.literalExpression "[ pkgs.gnome.gnome-session ]";
+      description = lib.mdDoc ''
+        List of packages that provide XDG desktop portal configuration, usually in
+        the form of `share/xdg-desktop-portal/$desktop-portals.conf`.
+
+        Note that configs in `xdg.portal.config` will be preferred if set.
+      '';
+    };
   };
 
   config =
     let
       cfg = config.xdg.portal;
       packages = [ pkgs.xdg-desktop-portal ] ++ cfg.extraPortals;
+      configPackages = cfg.configPackages;
+
       joinedPortals = pkgs.buildEnv {
         name = "xdg-portals";
         paths = packages;
         pathsToLink = [ "/share/xdg-desktop-portal/portals" "/share/applications" ];
       };
 
+      joinedPortalConfigs = pkgs.buildEnv {
+        name = "xdg-portal-configs";
+        paths = configPackages;
+        pathsToLink = [ "/share/xdg-desktop-portal" ];
+      };
     in
     mkIf cfg.enable {
+      warnings = lib.optional (cfg.configPackages == [ ] && cfg.config == { }) ''
+        xdg-desktop-portal 1.17 reworked how portal implementations are loaded, you
+        should either set `xdg.portal.config` or `xdg.portal.configPackages`
+        to specify which portal backend to use for the requested interface.
+
+        https://github.com/flatpak/xdg-desktop-portal/blob/1.18.1/doc/portals.conf.rst.in
+
+        If you simply want to keep the behaviour in < 1.17, which uses the first
+        portal implementation found in lexicographical order, use the following:
+
+        xdg.portal.config.common.default = "*";
+      '';
 
       assertions = [
         {
@@ -108,7 +168,14 @@ in
           GTK_USE_PORTAL = mkIf cfg.gtkUsePortal "1";
           NIXOS_XDG_OPEN_USE_PORTAL = mkIf cfg.xdgOpenUsePortal "1";
           XDG_DESKTOP_PORTAL_DIR = "${joinedPortals}/share/xdg-desktop-portal/portals";
+          NIXOS_XDG_DESKTOP_PORTAL_CONFIG_DIR = mkIf (cfg.configPackages != [ ]) "${joinedPortalConfigs}/share/xdg-desktop-portal";
         };
+
+        etc = lib.concatMapAttrs
+          (desktop: conf: lib.optionalAttrs (conf != { }) {
+            "xdg/xdg-desktop-portal/${lib.optionalString (desktop != "common") "${desktop}-"}portals.conf".text =
+              lib.generators.toINI { } { preferred = conf; };
+          }) cfg.config;
       };
     };
 }
diff --git a/nixpkgs/nixos/modules/hardware/ckb-next.nix b/nixpkgs/nixos/modules/hardware/ckb-next.nix
index 79977939eec8..34f951a7446f 100644
--- a/nixpkgs/nixos/modules/hardware/ckb-next.nix
+++ b/nixpkgs/nixos/modules/hardware/ckb-next.nix
@@ -24,14 +24,7 @@ in
         '';
       };
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.ckb-next;
-        defaultText = literalExpression "pkgs.ckb-next";
-        description = lib.mdDoc ''
-          The package implementing the Corsair keyboard/mouse driver.
-        '';
-      };
+      package = mkPackageOption pkgs "ckb-next" { };
     };
 
     config = mkIf cfg.enable {
diff --git a/nixpkgs/nixos/modules/hardware/digitalbitbox.nix b/nixpkgs/nixos/modules/hardware/digitalbitbox.nix
index 74e46bd34ace..ea04d72a63a5 100644
--- a/nixpkgs/nixos/modules/hardware/digitalbitbox.nix
+++ b/nixpkgs/nixos/modules/hardware/digitalbitbox.nix
@@ -16,11 +16,10 @@ in
       '';
     };
 
-    package = mkOption {
-      type = types.package;
-      default = pkgs.digitalbitbox;
-      defaultText = literalExpression "pkgs.digitalbitbox";
-      description = lib.mdDoc "The Digital Bitbox package to use. This can be used to install a package with udev rules that differ from the defaults.";
+    package = mkPackageOption pkgs "digitalbitbox" {
+      extraDescription = ''
+        This can be used to install a package with udev rules that differ from the defaults.
+      '';
     };
   };
 
diff --git a/nixpkgs/nixos/modules/hardware/opentabletdriver.nix b/nixpkgs/nixos/modules/hardware/opentabletdriver.nix
index e3f418abce4f..f103da14c9dd 100644
--- a/nixpkgs/nixos/modules/hardware/opentabletdriver.nix
+++ b/nixpkgs/nixos/modules/hardware/opentabletdriver.nix
@@ -26,14 +26,7 @@ in
         '';
       };
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.opentabletdriver;
-        defaultText = literalExpression "pkgs.opentabletdriver";
-        description = lib.mdDoc ''
-          OpenTabletDriver derivation to use.
-        '';
-      };
+      package = mkPackageOption pkgs "opentabletdriver" { };
 
       daemon = {
         enable = mkOption {
diff --git a/nixpkgs/nixos/modules/hardware/video/nvidia.nix b/nixpkgs/nixos/modules/hardware/video/nvidia.nix
index c36775dd24bb..c76883b656d4 100644
--- a/nixpkgs/nixos/modules/hardware/video/nvidia.nix
+++ b/nixpkgs/nixos/modules/hardware/video/nvidia.nix
@@ -261,7 +261,16 @@ in {
         ];
         boot = {
           blacklistedKernelModules = ["nouveau" "nvidiafb"];
-          kernelModules = [ "nvidia-uvm" ];
+
+          # 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
diff --git a/nixpkgs/nixos/modules/i18n/input-method/ibus.nix b/nixpkgs/nixos/modules/i18n/input-method/ibus.nix
index 2a35afad2ac7..a81ce828b13d 100644
--- a/nixpkgs/nixos/modules/i18n/input-method/ibus.nix
+++ b/nixpkgs/nixos/modules/i18n/input-method/ibus.nix
@@ -47,7 +47,7 @@ in
       panel = mkOption {
         type = with types; nullOr path;
         default = null;
-        example = literalExpression ''"''${pkgs.plasma5Packages.plasma-desktop}/lib/libexec/kimpanel-ibus-panel"'';
+        example = literalExpression ''"''${pkgs.plasma5Packages.plasma-desktop}/libexec/kimpanel-ibus-panel"'';
         description = lib.mdDoc "Replace the IBus panel with another panel.";
       };
     };
diff --git a/nixpkgs/nixos/modules/installer/tools/tools.nix b/nixpkgs/nixos/modules/installer/tools/tools.nix
index 15e10128ac9a..9ccc76a82c95 100644
--- a/nixpkgs/nixos/modules/installer/tools/tools.nix
+++ b/nixpkgs/nixos/modules/installer/tools/tools.nix
@@ -130,7 +130,7 @@ in
     '';
   };
 
-  config = lib.mkIf (config.nix.enable && !config.system.disableInstallerTools) {
+  config = lib.mkMerge [ (lib.mkIf (config.nix.enable && !config.system.disableInstallerTools) {
 
     system.nixos-generate-config.configuration = mkDefault ''
       # Edit this configuration file to define what should be installed on
@@ -257,10 +257,13 @@ in
 
     documentation.man.man-db.skipPackages = [ nixos-version ];
 
+  })
+
+  # These may be used in auxiliary scripts (ie not part of toplevel), so they are defined unconditionally.
+  ({
     system.build = {
       inherit nixos-install nixos-generate-config nixos-option nixos-rebuild nixos-enter;
     };
-
-  };
+  })];
 
 }
diff --git a/nixpkgs/nixos/modules/misc/locate.nix b/nixpkgs/nixos/modules/misc/locate.nix
index 3c76d17086b5..0dd4bf3f16f3 100644
--- a/nixpkgs/nixos/modules/misc/locate.nix
+++ b/nixpkgs/nixos/modules/misc/locate.nix
@@ -26,14 +26,8 @@ in
       '';
     };
 
-    package = mkOption {
-      type = package;
-      default = pkgs.findutils.locate;
-      defaultText = literalExpression "pkgs.findutils.locate";
-      example = literalExpression "pkgs.mlocate";
-      description = lib.mdDoc ''
-        The locate implementation to use
-      '';
+    package = mkPackageOption pkgs [ "findutils" "locate" ] {
+      example = "mlocate";
     };
 
     interval = mkOption {
diff --git a/nixpkgs/nixos/modules/module-list.nix b/nixpkgs/nixos/modules/module-list.nix
index 9f79c70125fc..2b06951cfb72 100644
--- a/nixpkgs/nixos/modules/module-list.nix
+++ b/nixpkgs/nixos/modules/module-list.nix
@@ -167,6 +167,7 @@
   ./programs/direnv.nix
   ./programs/dmrconfig.nix
   ./programs/droidcam.nix
+  ./programs/dublin-traceroute.nix
   ./programs/ecryptfs.nix
   ./programs/environment.nix
   ./programs/evince.nix
@@ -474,11 +475,13 @@
   ./services/desktops/pipewire/pipewire.nix
   ./services/desktops/pipewire/wireplumber.nix
   ./services/desktops/profile-sync-daemon.nix
+  ./services/desktops/seatd.nix
   ./services/desktops/system-config-printer.nix
   ./services/desktops/system76-scheduler.nix
   ./services/desktops/telepathy.nix
   ./services/desktops/tumbler.nix
   ./services/desktops/zeitgeist.nix
+  ./services/development/athens.nix
   ./services/development/blackfire.nix
   ./services/development/bloop.nix
   ./services/development/distccd.nix
@@ -513,6 +516,7 @@
   ./services/hardware/argonone.nix
   ./services/hardware/asusd.nix
   ./services/hardware/auto-cpufreq.nix
+  ./services/hardware/auto-epp.nix
   ./services/hardware/bluetooth.nix
   ./services/hardware/bolt.nix
   ./services/hardware/brltty.nix
@@ -621,6 +625,7 @@
   ./services/matrix/appservice-irc.nix
   ./services/matrix/conduit.nix
   ./services/matrix/dendrite.nix
+  ./services/matrix/maubot.nix
   ./services/matrix/mautrix-facebook.nix
   ./services/matrix/mautrix-telegram.nix
   ./services/matrix/mautrix-whatsapp.nix
@@ -633,6 +638,7 @@
   ./services/misc/amazon-ssm-agent.nix
   ./services/misc/ananicy.nix
   ./services/misc/ankisyncd.nix
+  ./services/misc/anki-sync-server.nix
   ./services/misc/apache-kafka.nix
   ./services/misc/atuin.nix
   ./services/misc/autofs.nix
@@ -723,6 +729,7 @@
   ./services/misc/podgrab.nix
   ./services/misc/polaris.nix
   ./services/misc/portunus.nix
+  ./services/misc/preload.nix
   ./services/misc/prowlarr.nix
   ./services/misc/pufferpanel.nix
   ./services/misc/pykms.nix
@@ -882,6 +889,7 @@
   ./services/networking/bitlbee.nix
   ./services/networking/blockbook-frontend.nix
   ./services/networking/blocky.nix
+  ./services/networking/centrifugo.nix
   ./services/networking/cgit.nix
   ./services/networking/charybdis.nix
   ./services/networking/chisel-server.nix
@@ -1152,6 +1160,7 @@
   ./services/search/meilisearch.nix
   ./services/search/opensearch.nix
   ./services/search/qdrant.nix
+  ./services/search/sonic-server.nix
   ./services/search/typesense.nix
   ./services/security/aesmd.nix
   ./services/security/authelia.nix
@@ -1215,6 +1224,7 @@
   ./services/torrent/peerflix.nix
   ./services/torrent/rtorrent.nix
   ./services/torrent/transmission.nix
+  ./services/torrent/torrentstream.nix
   ./services/tracing/tempo.nix
   ./services/ttys/getty.nix
   ./services/ttys/gpm.nix
@@ -1405,6 +1415,7 @@
   ./services/x11/xautolock.nix
   ./services/x11/xbanish.nix
   ./services/x11/xfs.nix
+  ./services/x11/xscreensaver.nix
   ./services/x11/xserver.nix
   ./system/activation/activatable-system.nix
   ./system/activation/activation-script.nix
@@ -1435,6 +1446,7 @@
   ./system/boot/stratisroot.nix
   ./system/boot/modprobe.nix
   ./system/boot/networkd.nix
+  ./system/boot/unl0kr.nix
   ./system/boot/plymouth.nix
   ./system/boot/resolved.nix
   ./system/boot/shutdown.nix
@@ -1532,9 +1544,10 @@
   ./virtualisation/waydroid.nix
   ./virtualisation/xe-guest-utilities.nix
   ./virtualisation/xen-dom0.nix
-  { documentation.nixos.extraModules = [
-    ./virtualisation/qemu-vm.nix
-    ./image/repart.nix
+  {
+    documentation.nixos.extraModules = [
+      ./virtualisation/qemu-vm.nix
+      ./image/repart.nix
     ];
   }
 ]
diff --git a/nixpkgs/nixos/modules/profiles/hardened.nix b/nixpkgs/nixos/modules/profiles/hardened.nix
index 856ee480fc0b..74dc2cb1b9aa 100644
--- a/nixpkgs/nixos/modules/profiles/hardened.nix
+++ b/nixpkgs/nixos/modules/profiles/hardened.nix
@@ -79,10 +79,6 @@ with lib;
     "ufs"
   ];
 
-  # Restrict ptrace() usage to processes with a pre-defined relationship
-  # (e.g., parent/child)
-  boot.kernel.sysctl."kernel.yama.ptrace_scope" = mkOverride 500 1;
-
   # Hide kptrs even for processes with CAP_SYSLOG
   boot.kernel.sysctl."kernel.kptr_restrict" = mkOverride 500 2;
 
diff --git a/nixpkgs/nixos/modules/profiles/macos-builder.nix b/nixpkgs/nixos/modules/profiles/macos-builder.nix
index d48afed18f7e..6c2602881d6b 100644
--- a/nixpkgs/nixos/modules/profiles/macos-builder.nix
+++ b/nixpkgs/nixos/modules/profiles/macos-builder.nix
@@ -103,6 +103,19 @@ in
     # server that QEMU provides (normally 10.0.2.3)
     networking.nameservers = [ "8.8.8.8" ];
 
+    # The linux builder is a lightweight VM for remote building; not evaluation.
+    nix.channel.enable = false;
+    # remote builder uses `nix-daemon` (ssh-ng:) or `nix-store --serve` (ssh:)
+    # --force: do not complain when missing
+    # TODO: install a store-only nix
+    #       https://github.com/NixOS/rfcs/blob/master/rfcs/0134-nix-store-layer.md#detailed-design
+    environment.extraSetup = ''
+      rm --force $out/bin/{nix-instantiate,nix-build,nix-shell,nix-prefetch*,nix}
+    '';
+    # Deployment is by image.
+    # TODO system.switch.enable = false;?
+    system.disableInstallerTools = true;
+
     nix.settings = {
       auto-optimise-store = true;
 
diff --git a/nixpkgs/nixos/modules/programs/_1password-gui.nix b/nixpkgs/nixos/modules/programs/_1password-gui.nix
index 27c0d34a2eed..83ef6037fb5a 100644
--- a/nixpkgs/nixos/modules/programs/_1password-gui.nix
+++ b/nixpkgs/nixos/modules/programs/_1password-gui.nix
@@ -27,7 +27,7 @@ in
         '';
       };
 
-      package = mkPackageOptionMD pkgs "1Password GUI" {
+      package = mkPackageOption pkgs "1Password GUI" {
         default = [ "_1password-gui" ];
       };
     };
diff --git a/nixpkgs/nixos/modules/programs/_1password.nix b/nixpkgs/nixos/modules/programs/_1password.nix
index 8537484c7e67..91246150755d 100644
--- a/nixpkgs/nixos/modules/programs/_1password.nix
+++ b/nixpkgs/nixos/modules/programs/_1password.nix
@@ -18,7 +18,7 @@ in
     programs._1password = {
       enable = mkEnableOption (lib.mdDoc "the 1Password CLI tool");
 
-      package = mkPackageOptionMD pkgs "1Password CLI" {
+      package = mkPackageOption pkgs "1Password CLI" {
         default = [ "_1password" ];
       };
     };
diff --git a/nixpkgs/nixos/modules/programs/atop.nix b/nixpkgs/nixos/modules/programs/atop.nix
index a5f4d990bdbe..7d9491d1fc1f 100644
--- a/nixpkgs/nixos/modules/programs/atop.nix
+++ b/nixpkgs/nixos/modules/programs/atop.nix
@@ -16,14 +16,7 @@ in
 
       enable = mkEnableOption (lib.mdDoc "Atop");
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.atop;
-        defaultText = literalExpression "pkgs.atop";
-        description = lib.mdDoc ''
-          Which package to use for Atop.
-        '';
-      };
+      package = mkPackageOption pkgs "atop" { };
 
       netatop = {
         enable = mkOption {
diff --git a/nixpkgs/nixos/modules/programs/captive-browser.nix b/nixpkgs/nixos/modules/programs/captive-browser.nix
index 032c0e71f1f4..1c3ee7638ee0 100644
--- a/nixpkgs/nixos/modules/programs/captive-browser.nix
+++ b/nixpkgs/nixos/modules/programs/captive-browser.nix
@@ -5,7 +5,8 @@ let
 
   inherit (lib)
     concatStringsSep escapeShellArgs optionalString
-    literalExpression mkEnableOption mkIf mkOption mkOptionDefault types;
+    literalExpression mkEnableOption mkPackageOption mkIf mkOption
+    mkOptionDefault types;
 
   requiresSetcapWrapper = config.boot.kernelPackages.kernelOlder "5.7" && cfg.bindInterface;
 
@@ -50,12 +51,7 @@ in
     programs.captive-browser = {
       enable = mkEnableOption (lib.mdDoc "captive browser");
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.captive-browser;
-        defaultText = literalExpression "pkgs.captive-browser";
-        description = lib.mdDoc "Which package to use for captive-browser";
-      };
+      package = mkPackageOption pkgs "captive-browser" { };
 
       interface = mkOption {
         type = types.str;
diff --git a/nixpkgs/nixos/modules/programs/darling.nix b/nixpkgs/nixos/modules/programs/darling.nix
index c4e1c73b5c29..589a9dd5d603 100644
--- a/nixpkgs/nixos/modules/programs/darling.nix
+++ b/nixpkgs/nixos/modules/programs/darling.nix
@@ -6,7 +6,7 @@ in {
   options = {
     programs.darling = {
       enable = lib.mkEnableOption (lib.mdDoc "Darling, a Darwin/macOS compatibility layer for Linux");
-      package = lib.mkPackageOptionMD pkgs "darling" {};
+      package = lib.mkPackageOption pkgs "darling" {};
     };
   };
 
diff --git a/nixpkgs/nixos/modules/programs/digitalbitbox/default.nix b/nixpkgs/nixos/modules/programs/digitalbitbox/default.nix
index 5ee6cdafe63a..bdacbc010c41 100644
--- a/nixpkgs/nixos/modules/programs/digitalbitbox/default.nix
+++ b/nixpkgs/nixos/modules/programs/digitalbitbox/default.nix
@@ -16,11 +16,10 @@ in
       '';
     };
 
-    package = mkOption {
-      type = types.package;
-      default = pkgs.digitalbitbox;
-      defaultText = literalExpression "pkgs.digitalbitbox";
-      description = lib.mdDoc "The Digital Bitbox package to use. This can be used to install a package with udev rules that differ from the defaults.";
+    package = mkPackageOption pkgs "digitalbitbox" {
+      extraDescription = ''
+        This can be used to install a package with udev rules that differ from the defaults.
+      '';
     };
   };
 
diff --git a/nixpkgs/nixos/modules/programs/direnv.nix b/nixpkgs/nixos/modules/programs/direnv.nix
index 2566fa7699bb..1aa62ea54d2c 100644
--- a/nixpkgs/nixos/modules/programs/direnv.nix
+++ b/nixpkgs/nixos/modules/programs/direnv.nix
@@ -14,7 +14,7 @@ in {
       integration. Note that you need to logout and login for this change to apply
     '');
 
-    package = lib.mkPackageOptionMD pkgs "direnv" {};
+    package = lib.mkPackageOption pkgs "direnv" {};
 
     direnvrcExtra = lib.mkOption {
       type = lib.types.lines;
@@ -49,7 +49,7 @@ in {
           default = true;
         };
 
-      package = lib.mkPackageOptionMD pkgs "nix-direnv" {};
+      package = lib.mkPackageOption pkgs "nix-direnv" {};
     };
   };
 
diff --git a/nixpkgs/nixos/modules/programs/dmrconfig.nix b/nixpkgs/nixos/modules/programs/dmrconfig.nix
index 20a0dc9556da..29268cdfeb50 100644
--- a/nixpkgs/nixos/modules/programs/dmrconfig.nix
+++ b/nixpkgs/nixos/modules/programs/dmrconfig.nix
@@ -21,12 +21,7 @@ in {
         relatedPackages = [ "dmrconfig" ];
       };
 
-      package = mkOption {
-        default = pkgs.dmrconfig;
-        type = types.package;
-        defaultText = literalExpression "pkgs.dmrconfig";
-        description = lib.mdDoc "dmrconfig derivation to use";
-      };
+      package = mkPackageOption pkgs "dmrconfig" { };
     };
   };
 
diff --git a/nixpkgs/nixos/modules/programs/dublin-traceroute.nix b/nixpkgs/nixos/modules/programs/dublin-traceroute.nix
new file mode 100644
index 000000000000..cfcd6e8308ff
--- /dev/null
+++ b/nixpkgs/nixos/modules/programs/dublin-traceroute.nix
@@ -0,0 +1,31 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.programs.dublin-traceroute;
+
+in {
+  meta.maintainers = pkgs.dublin-traceroute.meta.maintainers;
+
+  options = {
+    programs.dublin-traceroute = {
+      enable = mkEnableOption (mdDoc ''
+      dublin-traceroute, add it to the global environment and configure a setcap wrapper for it.
+      '');
+
+      package = mkPackageOption pkgs "dublin-traceroute" { };
+    };
+  };
+
+  config = mkIf cfg.enable {
+    environment.systemPackages = [ cfg.package ];
+
+    security.wrappers.dublin-traceroute = {
+      owner = "root";
+      group = "root";
+      capabilities = "cap_net_raw+p";
+      source = getExe cfg.package;
+    };
+  };
+}
diff --git a/nixpkgs/nixos/modules/programs/environment.nix b/nixpkgs/nixos/modules/programs/environment.nix
index 6cf9257d035a..8ac723f42f61 100644
--- a/nixpkgs/nixos/modules/programs/environment.nix
+++ b/nixpkgs/nixos/modules/programs/environment.nix
@@ -45,7 +45,7 @@ in
         GTK_PATH = [ "/lib/gtk-2.0" "/lib/gtk-3.0" "/lib/gtk-4.0" ];
         XDG_CONFIG_DIRS = [ "/etc/xdg" ];
         XDG_DATA_DIRS = [ "/share" ];
-        LIBEXEC_PATH = [ "/lib/libexec" ];
+        LIBEXEC_PATH = [ "/libexec" ];
       };
 
     environment.pathsToLink = [ "/lib/gtk-2.0" "/lib/gtk-3.0" "/lib/gtk-4.0" ];
diff --git a/nixpkgs/nixos/modules/programs/evince.nix b/nixpkgs/nixos/modules/programs/evince.nix
index 9ed5ea0feb04..ed543d35cc5e 100644
--- a/nixpkgs/nixos/modules/programs/evince.nix
+++ b/nixpkgs/nixos/modules/programs/evince.nix
@@ -24,12 +24,7 @@ in {
       enable = mkEnableOption
         (lib.mdDoc "Evince, the GNOME document viewer");
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.evince;
-        defaultText = literalExpression "pkgs.evince";
-        description = lib.mdDoc "Evince derivation to use.";
-      };
+      package = mkPackageOption pkgs "evince" { };
 
     };
 
diff --git a/nixpkgs/nixos/modules/programs/feedbackd.nix b/nixpkgs/nixos/modules/programs/feedbackd.nix
index e3fde947a3df..010287e5cd56 100644
--- a/nixpkgs/nixos/modules/programs/feedbackd.nix
+++ b/nixpkgs/nixos/modules/programs/feedbackd.nix
@@ -12,14 +12,7 @@ in {
 
         Your user needs to be in the `feedbackd` group to trigger effects
       '');
-      package = mkOption {
-        description = lib.mdDoc ''
-          Which feedbackd package to use.
-        '';
-        type = types.package;
-        default = pkgs.feedbackd;
-        defaultText = literalExpression "pkgs.feedbackd";
-      };
+      package = mkPackageOption pkgs "feedbackd" { };
     };
   };
   config = mkIf cfg.enable {
diff --git a/nixpkgs/nixos/modules/programs/file-roller.nix b/nixpkgs/nixos/modules/programs/file-roller.nix
index ca0c4d1b2a2a..a343d4a261c9 100644
--- a/nixpkgs/nixos/modules/programs/file-roller.nix
+++ b/nixpkgs/nixos/modules/programs/file-roller.nix
@@ -23,12 +23,7 @@ in {
 
       enable = mkEnableOption (lib.mdDoc "File Roller, an archive manager for GNOME");
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.gnome.file-roller;
-        defaultText = literalExpression "pkgs.gnome.file-roller";
-        description = lib.mdDoc "File Roller derivation to use.";
-      };
+      package = mkPackageOption pkgs [ "gnome" "file-roller" ] { };
 
     };
 
diff --git a/nixpkgs/nixos/modules/programs/flashrom.nix b/nixpkgs/nixos/modules/programs/flashrom.nix
index 9f8faff14e47..f954bc2197b1 100644
--- a/nixpkgs/nixos/modules/programs/flashrom.nix
+++ b/nixpkgs/nixos/modules/programs/flashrom.nix
@@ -16,7 +16,7 @@ in
         group.
       '';
     };
-    package = mkPackageOptionMD pkgs "flashrom" { };
+    package = mkPackageOption pkgs "flashrom" { };
   };
 
   config = mkIf cfg.enable {
diff --git a/nixpkgs/nixos/modules/programs/flexoptix-app.nix b/nixpkgs/nixos/modules/programs/flexoptix-app.nix
index 2524e7ba4d58..6f37fe54667c 100644
--- a/nixpkgs/nixos/modules/programs/flexoptix-app.nix
+++ b/nixpkgs/nixos/modules/programs/flexoptix-app.nix
@@ -9,12 +9,7 @@ in {
     programs.flexoptix-app = {
       enable = mkEnableOption (lib.mdDoc "FLEXOPTIX app + udev rules");
 
-      package = mkOption {
-        description = lib.mdDoc "FLEXOPTIX app package to use";
-        type = types.package;
-        default = pkgs.flexoptix-app;
-        defaultText = literalExpression "pkgs.flexoptix-app";
-      };
+      package = mkPackageOption pkgs "flexoptix-app" { };
     };
   };
 
diff --git a/nixpkgs/nixos/modules/programs/gamescope.nix b/nixpkgs/nixos/modules/programs/gamescope.nix
index a31295e736df..594e5be5fd58 100644
--- a/nixpkgs/nixos/modules/programs/gamescope.nix
+++ b/nixpkgs/nixos/modules/programs/gamescope.nix
@@ -23,14 +23,7 @@ in
   options.programs.gamescope = {
     enable = mkEnableOption (mdDoc "gamescope");
 
-    package = mkOption {
-      type = types.package;
-      default = pkgs.gamescope;
-      defaultText = literalExpression "pkgs.gamescope";
-      description = mdDoc ''
-        The GameScope package to use.
-      '';
-    };
+    package = mkPackageOption pkgs "gamescope" { };
 
     capSysNice = mkOption {
       type = types.bool;
diff --git a/nixpkgs/nixos/modules/programs/git.nix b/nixpkgs/nixos/modules/programs/git.nix
index 4e271a8c134b..8fb69cbae28f 100644
--- a/nixpkgs/nixos/modules/programs/git.nix
+++ b/nixpkgs/nixos/modules/programs/git.nix
@@ -11,12 +11,8 @@ in
     programs.git = {
       enable = mkEnableOption (lib.mdDoc "git");
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.git;
-        defaultText = literalExpression "pkgs.git";
-        example = literalExpression "pkgs.gitFull";
-        description = lib.mdDoc "The git package to use";
+      package = mkPackageOption pkgs "git" {
+        example = "gitFull";
       };
 
       config = mkOption {
@@ -58,15 +54,14 @@ in
         '';
       };
 
+      prompt = {
+        enable = mkEnableOption "automatically sourcing git-prompt.sh. This does not change $PS1; it simply provides relevant utility functions";
+      };
+
       lfs = {
         enable = mkEnableOption (lib.mdDoc "git-lfs");
 
-        package = mkOption {
-          type = types.package;
-          default = pkgs.git-lfs;
-          defaultText = literalExpression "pkgs.git-lfs";
-          description = lib.mdDoc "The git-lfs package to use";
-        };
+        package = mkPackageOption pkgs "git-lfs" { };
       };
     };
   };
@@ -89,6 +84,11 @@ in
         };
       };
     })
+    (mkIf (cfg.enable && cfg.prompt.enable) {
+      environment.interactiveShellInit = ''
+        source ${cfg.package}/share/bash-completion/completions/git-prompt.sh
+      '';
+    })
   ];
 
   meta.maintainers = with maintainers; [ figsoda ];
diff --git a/nixpkgs/nixos/modules/programs/gnupg.nix b/nixpkgs/nixos/modules/programs/gnupg.nix
index aa1a536247ce..8f82de033666 100644
--- a/nixpkgs/nixos/modules/programs/gnupg.nix
+++ b/nixpkgs/nixos/modules/programs/gnupg.nix
@@ -29,14 +29,7 @@ in
 {
 
   options.programs.gnupg = {
-    package = mkOption {
-      type = types.package;
-      default = pkgs.gnupg;
-      defaultText = literalExpression "pkgs.gnupg";
-      description = lib.mdDoc ''
-        The gpg package that should be used.
-      '';
-    };
+    package = mkPackageOption pkgs "gnupg" { };
 
     agent.enable = mkOption {
       type = types.bool;
diff --git a/nixpkgs/nixos/modules/programs/htop.nix b/nixpkgs/nixos/modules/programs/htop.nix
index 777ea709836e..9dbab954b2bb 100644
--- a/nixpkgs/nixos/modules/programs/htop.nix
+++ b/nixpkgs/nixos/modules/programs/htop.nix
@@ -18,14 +18,7 @@ in
 {
 
   options.programs.htop = {
-    package = mkOption {
-      type = types.package;
-      default = pkgs.htop;
-      defaultText = lib.literalExpression "pkgs.htop";
-      description = lib.mdDoc ''
-        The htop package that should be used.
-      '';
-    };
+    package = mkPackageOption pkgs "htop" { };
 
     enable = mkEnableOption (lib.mdDoc "htop process monitor");
 
diff --git a/nixpkgs/nixos/modules/programs/hyprland.nix b/nixpkgs/nixos/modules/programs/hyprland.nix
index 638dfb98e8ab..166c6cbc5c18 100644
--- a/nixpkgs/nixos/modules/programs/hyprland.nix
+++ b/nixpkgs/nixos/modules/programs/hyprland.nix
@@ -23,7 +23,7 @@ in
       '';
     };
 
-    package = mkPackageOptionMD pkgs "hyprland" { };
+    package = mkPackageOption pkgs "hyprland" { };
 
     finalPackage = mkOption {
       type = types.package;
@@ -39,7 +39,7 @@ in
       '';
     };
 
-    portalPackage = mkPackageOptionMD pkgs "xdg-desktop-portal-hyprland" { };
+    portalPackage = mkPackageOption pkgs "xdg-desktop-portal-hyprland" { };
 
     xwayland.enable = mkEnableOption (mdDoc "XWayland") // { default = true; };
 
@@ -64,6 +64,7 @@ in
     xdg.portal = {
       enable = mkDefault true;
       extraPortals = [ finalPortalPackage ];
+      configPackages = mkDefault [ cfg.finalPackage ];
     };
   };
 
diff --git a/nixpkgs/nixos/modules/programs/i3lock.nix b/nixpkgs/nixos/modules/programs/i3lock.nix
index 466ae59c9277..44e2e04c2799 100644
--- a/nixpkgs/nixos/modules/programs/i3lock.nix
+++ b/nixpkgs/nixos/modules/programs/i3lock.nix
@@ -13,16 +13,12 @@ in {
   options = {
     programs.i3lock = {
       enable = mkEnableOption (mdDoc "i3lock");
-      package = mkOption {
-        type        = types.package;
-        default     = pkgs.i3lock;
-        defaultText = literalExpression "pkgs.i3lock";
-        example     = literalExpression ''
-          pkgs.i3lock-color
-        '';
-        description = mdDoc ''
-          Specify which package to use for the i3lock program,
+      package = mkPackageOption pkgs "i3lock" {
+        example = "i3lock-color";
+        extraDescription = ''
+          ::: {.note}
           The i3lock package must include a i3lock file or link in its out directory in order for the u2fSupport option to work correctly.
+          :::
         '';
       };
       u2fSupport = mkOption {
diff --git a/nixpkgs/nixos/modules/programs/iay.nix b/nixpkgs/nixos/modules/programs/iay.nix
index 9164f5cb6486..1fa00e43795a 100644
--- a/nixpkgs/nixos/modules/programs/iay.nix
+++ b/nixpkgs/nixos/modules/programs/iay.nix
@@ -2,11 +2,11 @@
 
 let
   cfg = config.programs.iay;
-  inherit (lib) mkEnableOption mkIf mkOption mkPackageOptionMD optionalString types;
+  inherit (lib) mkEnableOption mkIf mkOption mkPackageOption optionalString types;
 in {
   options.programs.iay = {
     enable = mkEnableOption (lib.mdDoc "iay");
-    package = mkPackageOptionMD pkgs "iay" {};
+    package = mkPackageOption pkgs "iay" {};
 
     minimalPrompt = mkOption {
       type = types.bool;
diff --git a/nixpkgs/nixos/modules/programs/java.nix b/nixpkgs/nixos/modules/programs/java.nix
index c5f83858d06a..251192183ebf 100644
--- a/nixpkgs/nixos/modules/programs/java.nix
+++ b/nixpkgs/nixos/modules/programs/java.nix
@@ -30,13 +30,8 @@ in
         '';
       };
 
-      package = mkOption {
-        default = pkgs.jdk;
-        defaultText = literalExpression "pkgs.jdk";
-        description = lib.mdDoc ''
-          Java package to install. Typical values are pkgs.jdk or pkgs.jre.
-        '';
-        type = types.package;
+      package = mkPackageOption pkgs "jdk" {
+        example = "jre";
       };
 
       binfmt = mkEnableOption (lib.mdDoc "binfmt to execute java jar's and classes");
diff --git a/nixpkgs/nixos/modules/programs/joycond-cemuhook.nix b/nixpkgs/nixos/modules/programs/joycond-cemuhook.nix
new file mode 100644
index 000000000000..7b129868db28
--- /dev/null
+++ b/nixpkgs/nixos/modules/programs/joycond-cemuhook.nix
@@ -0,0 +1,17 @@
+{ lib, pkgs, config, ... }:
+with lib;
+{
+  options.programs.joycond-cemuhook = {
+    enable = mkEnableOption (lib.mdDoc "joycond-cemuhook, a program to enable support for cemuhook's UDP protocol for joycond devices.");
+  };
+
+  config = lib.mkIf config.programs.joycond-cemuhook.enable {
+    assertions = [
+      {
+        assertion = config.services.joycond.enable;
+        message = "joycond must be enabled through `services.joycond.enable`";
+      }
+    ];
+    environment.systemPackages = [ pkgs.joycond-cemuhook ];
+  };
+}
diff --git a/nixpkgs/nixos/modules/programs/k40-whisperer.nix b/nixpkgs/nixos/modules/programs/k40-whisperer.nix
index 27a79caa4b53..96cf159f2cf7 100644
--- a/nixpkgs/nixos/modules/programs/k40-whisperer.nix
+++ b/nixpkgs/nixos/modules/programs/k40-whisperer.nix
@@ -20,15 +20,7 @@ in
       default = "k40";
     };
 
-    package = mkOption {
-      type = types.package;
-      default = pkgs.k40-whisperer;
-      defaultText = literalExpression "pkgs.k40-whisperer";
-      example = literalExpression "pkgs.k40-whisperer";
-      description = lib.mdDoc ''
-        K40 Whisperer package to use.
-      '';
-    };
+    package = mkPackageOption pkgs "k40-whisperer" { };
   };
 
   config = mkIf cfg.enable {
diff --git a/nixpkgs/nixos/modules/programs/kdeconnect.nix b/nixpkgs/nixos/modules/programs/kdeconnect.nix
index 4ba156f2db8d..a16fad03eefe 100644
--- a/nixpkgs/nixos/modules/programs/kdeconnect.nix
+++ b/nixpkgs/nixos/modules/programs/kdeconnect.nix
@@ -11,14 +11,8 @@ with lib;
       `gnomeExtensions.gsconnect` as an alternative
       implementation if you use Gnome
     '');
-    package = mkOption {
-      default = pkgs.plasma5Packages.kdeconnect-kde;
-      defaultText = literalExpression "pkgs.plasma5Packages.kdeconnect-kde";
-      type = types.package;
-      example = literalExpression "pkgs.gnomeExtensions.gsconnect";
-      description = lib.mdDoc ''
-        The package providing the implementation for kdeconnect.
-      '';
+    package = mkPackageOption pkgs [ "plasma5Packages" "kdeconnect-kde" ] {
+      example = "gnomeExtensions.gsconnect";
     };
   };
   config =
diff --git a/nixpkgs/nixos/modules/programs/mininet.nix b/nixpkgs/nixos/modules/programs/mininet.nix
index 02272729d233..01ffd811e70e 100644
--- a/nixpkgs/nixos/modules/programs/mininet.nix
+++ b/nixpkgs/nixos/modules/programs/mininet.nix
@@ -5,26 +5,39 @@
 with lib;
 
 let
-  cfg  = config.programs.mininet;
+  cfg = config.programs.mininet;
 
-  generatedPath = with pkgs; makeSearchPath "bin"  [
-    iperf ethtool iproute2 socat
+  telnet = pkgs.runCommand "inetutils-telnet"
+    { }
+    ''
+      mkdir -p $out/bin
+      ln -s ${pkgs.inetutils}/bin/telnet $out/bin
+    '';
+
+  generatedPath = with pkgs; makeSearchPath "bin" [
+    iperf
+    ethtool
+    iproute2
+    socat
+    # mn errors out without a telnet binary
+    # pkgs.inetutils brings an undesired ifconfig into PATH see #43105
+    nettools
+    telnet
   ];
 
-  pyEnv = pkgs.python.withPackages(ps: [ ps.mininet-python ]);
+  pyEnv = pkgs.python3.withPackages (ps: [ ps.mininet-python ]);
 
   mnexecWrapped = pkgs.runCommand "mnexec-wrapper"
-    { nativeBuildInputs = [ pkgs.makeWrapper pkgs.pythonPackages.wrapPython ]; }
+    { nativeBuildInputs = [ pkgs.makeWrapper pkgs.python3Packages.wrapPython ]; }
     ''
       makeWrapper ${pkgs.mininet}/bin/mnexec \
         $out/bin/mnexec \
         --prefix PATH : "${generatedPath}"
 
-      ln -s ${pyEnv}/bin/mn $out/bin/mn
-
-      # mn errors out without a telnet binary
-      # pkgs.inetutils brings an undesired ifconfig into PATH see #43105
-      ln -s ${pkgs.inetutils}/bin/telnet $out/bin/telnet
+      makeWrapper ${pyEnv}/bin/mn \
+        $out/bin/mn \
+        --prefix PYTHONPATH : "${pyEnv}/${pyEnv.sitePackages}" \
+        --prefix PATH : "${generatedPath}"
     '';
 in
 {
diff --git a/nixpkgs/nixos/modules/programs/minipro.nix b/nixpkgs/nixos/modules/programs/minipro.nix
index a947f83f2ee0..8cb64866a84c 100644
--- a/nixpkgs/nixos/modules/programs/minipro.nix
+++ b/nixpkgs/nixos/modules/programs/minipro.nix
@@ -13,7 +13,7 @@ in
         '';
       };
 
-      package = lib.mkPackageOptionMD pkgs "minipro" { };
+      package = lib.mkPackageOption pkgs "minipro" { };
     };
   };
 
diff --git a/nixpkgs/nixos/modules/programs/mtr.nix b/nixpkgs/nixos/modules/programs/mtr.nix
index 173f24729417..e247d645b861 100644
--- a/nixpkgs/nixos/modules/programs/mtr.nix
+++ b/nixpkgs/nixos/modules/programs/mtr.nix
@@ -17,14 +17,7 @@ in {
         '';
       };
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.mtr;
-        defaultText = literalExpression "pkgs.mtr";
-        description = lib.mdDoc ''
-          The package to use.
-        '';
-      };
+      package = mkPackageOption pkgs "mtr" { };
     };
   };
 
diff --git a/nixpkgs/nixos/modules/programs/nano.nix b/nixpkgs/nixos/modules/programs/nano.nix
index 88404f3557c6..461681b59863 100644
--- a/nixpkgs/nixos/modules/programs/nano.nix
+++ b/nixpkgs/nixos/modules/programs/nano.nix
@@ -11,7 +11,7 @@ in
         default = true;
       };
 
-      package = lib.mkPackageOptionMD pkgs "nano" { };
+      package = lib.mkPackageOption pkgs "nano" { };
 
       nanorc = lib.mkOption {
         type = lib.types.lines;
diff --git a/nixpkgs/nixos/modules/programs/neovim.nix b/nixpkgs/nixos/modules/programs/neovim.nix
index 1b53b9b5d919..77abec7ef7e9 100644
--- a/nixpkgs/nixos/modules/programs/neovim.nix
+++ b/nixpkgs/nixos/modules/programs/neovim.nix
@@ -86,12 +86,7 @@ in
       '';
     };
 
-    package = mkOption {
-      type = types.package;
-      default = pkgs.neovim-unwrapped;
-      defaultText = literalExpression "pkgs.neovim-unwrapped";
-      description = lib.mdDoc "The package to use for the neovim binary.";
-    };
+    package = mkPackageOption pkgs "neovim-unwrapped" { };
 
     finalPackage = mkOption {
       type = types.package;
diff --git a/nixpkgs/nixos/modules/programs/nexttrace.nix b/nixpkgs/nixos/modules/programs/nexttrace.nix
index 091d4f17f9f6..09143c5f861d 100644
--- a/nixpkgs/nixos/modules/programs/nexttrace.nix
+++ b/nixpkgs/nixos/modules/programs/nexttrace.nix
@@ -8,7 +8,7 @@ in
   options = {
     programs.nexttrace = {
       enable = lib.mkEnableOption (lib.mdDoc "Nexttrace to the global environment and configure a setcap wrapper for it");
-      package = lib.mkPackageOptionMD pkgs "nexttrace" { };
+      package = lib.mkPackageOption pkgs "nexttrace" { };
     };
   };
 
diff --git a/nixpkgs/nixos/modules/programs/nix-index.nix b/nixpkgs/nixos/modules/programs/nix-index.nix
index a494b9d8c2c9..f3e7d22737fa 100644
--- a/nixpkgs/nixos/modules/programs/nix-index.nix
+++ b/nixpkgs/nixos/modules/programs/nix-index.nix
@@ -5,12 +5,7 @@ in {
   options.programs.nix-index = with lib; {
     enable = mkEnableOption (lib.mdDoc "nix-index, a file database for nixpkgs");
 
-    package = mkOption {
-      type = types.package;
-      default = pkgs.nix-index;
-      defaultText = literalExpression "pkgs.nix-index";
-      description = lib.mdDoc "Package providing the `nix-index` tool.";
-    };
+    package = mkPackageOption pkgs "nix-index" { };
 
     enableBashIntegration = mkEnableOption (lib.mdDoc "Bash integration") // {
       default = true;
diff --git a/nixpkgs/nixos/modules/programs/nix-ld.nix b/nixpkgs/nixos/modules/programs/nix-ld.nix
index d54b3917f89a..e3a9bb16410c 100644
--- a/nixpkgs/nixos/modules/programs/nix-ld.nix
+++ b/nixpkgs/nixos/modules/programs/nix-ld.nix
@@ -37,7 +37,7 @@ in
   meta.maintainers = [ lib.maintainers.mic92 ];
   options.programs.nix-ld = {
     enable = lib.mkEnableOption (lib.mdDoc ''nix-ld, Documentation: <https://github.com/Mic92/nix-ld>'');
-    package = lib.mkPackageOptionMD pkgs "nix-ld" { };
+    package = lib.mkPackageOption pkgs "nix-ld" { };
     libraries = lib.mkOption {
       type = lib.types.listOf lib.types.package;
       description = lib.mdDoc "Libraries that automatically become available to all programs. The default set includes common libraries.";
diff --git a/nixpkgs/nixos/modules/programs/nncp.nix b/nixpkgs/nixos/modules/programs/nncp.nix
index 98fea84ab740..e078b718410c 100644
--- a/nixpkgs/nixos/modules/programs/nncp.nix
+++ b/nixpkgs/nixos/modules/programs/nncp.nix
@@ -23,12 +23,7 @@ in {
       '';
     };
 
-    package = mkOption {
-      type = types.package;
-      default = pkgs.nncp;
-      defaultText = literalExpression "pkgs.nncp";
-      description = lib.mdDoc "The NNCP package to use system-wide.";
-    };
+    package = mkPackageOption pkgs "nncp" { };
 
     secrets = mkOption {
       type = with types; listOf str;
diff --git a/nixpkgs/nixos/modules/programs/noisetorch.nix b/nixpkgs/nixos/modules/programs/noisetorch.nix
index c022b01d79af..d8135877d02f 100644
--- a/nixpkgs/nixos/modules/programs/noisetorch.nix
+++ b/nixpkgs/nixos/modules/programs/noisetorch.nix
@@ -8,14 +8,7 @@ in
   options.programs.noisetorch = {
     enable = mkEnableOption (lib.mdDoc "noisetorch + setcap wrapper");
 
-    package = mkOption {
-      type = types.package;
-      default = pkgs.noisetorch;
-      defaultText = literalExpression "pkgs.noisetorch";
-      description = lib.mdDoc ''
-        The noisetorch package to use.
-      '';
-    };
+    package = mkPackageOption pkgs "noisetorch" { };
   };
 
   config = mkIf cfg.enable {
diff --git a/nixpkgs/nixos/modules/programs/npm.nix b/nixpkgs/nixos/modules/programs/npm.nix
index c41fea326149..8113ea1ba4ea 100644
--- a/nixpkgs/nixos/modules/programs/npm.nix
+++ b/nixpkgs/nixos/modules/programs/npm.nix
@@ -13,12 +13,8 @@ in
     programs.npm = {
       enable = mkEnableOption (lib.mdDoc "{command}`npm` global config");
 
-      package = mkOption {
-        type = types.package;
-        description = lib.mdDoc "The npm package version / flavor to use";
-        default = pkgs.nodePackages.npm;
-        defaultText = literalExpression "pkgs.nodePackages.npm";
-        example = literalExpression "pkgs.nodePackages_13_x.npm";
+      package = mkPackageOption pkgs [ "nodePackages" "npm" ] {
+        example = "nodePackages_13_x.npm";
       };
 
       npmrc = mkOption {
diff --git a/nixpkgs/nixos/modules/programs/oddjobd.nix b/nixpkgs/nixos/modules/programs/oddjobd.nix
index b0920d007c9e..08bb8b268473 100644
--- a/nixpkgs/nixos/modules/programs/oddjobd.nix
+++ b/nixpkgs/nixos/modules/programs/oddjobd.nix
@@ -10,11 +10,6 @@ in
   };
 
   config = lib.mkIf cfg.enable {
-    assertions = [
-      { assertion = false;
-        message = "The oddjob service was found to be broken without NixOS test or maintainer. Please take ownership of this service.";
-      }
-    ];
     systemd.packages = [ cfg.package ];
 
     systemd.services.oddjobd = {
@@ -30,4 +25,6 @@ in
       };
     };
   };
+
+  meta.maintainers = with lib.maintainers; [ SohamG ];
 }
diff --git a/nixpkgs/nixos/modules/programs/projecteur.nix b/nixpkgs/nixos/modules/programs/projecteur.nix
index 9fcd357d3b23..140de0209e68 100644
--- a/nixpkgs/nixos/modules/programs/projecteur.nix
+++ b/nixpkgs/nixos/modules/programs/projecteur.nix
@@ -6,7 +6,7 @@ in
 {
   options.programs.projecteur = {
     enable = lib.mkEnableOption (lib.mdDoc "projecteur");
-    package = lib.mkPackageOptionMD pkgs "projecteur" { };
+    package = lib.mkPackageOption pkgs "projecteur" { };
   };
 
   config = lib.mkIf cfg.enable {
diff --git a/nixpkgs/nixos/modules/programs/proxychains.nix b/nixpkgs/nixos/modules/programs/proxychains.nix
index 9bdd5d405668..acd41f355244 100644
--- a/nixpkgs/nixos/modules/programs/proxychains.nix
+++ b/nixpkgs/nixos/modules/programs/proxychains.nix
@@ -51,8 +51,8 @@ in {
 
       enable = mkEnableOption (lib.mdDoc "installing proxychains configuration");
 
-      package = mkPackageOptionMD pkgs "proxychains" {
-        example = "pkgs.proxychains-ng";
+      package = mkPackageOption pkgs "proxychains" {
+        example = "proxychains-ng";
       };
 
       chain = {
diff --git a/nixpkgs/nixos/modules/programs/qdmr.nix b/nixpkgs/nixos/modules/programs/qdmr.nix
index 1bb81317bda8..03ad4d008873 100644
--- a/nixpkgs/nixos/modules/programs/qdmr.nix
+++ b/nixpkgs/nixos/modules/programs/qdmr.nix
@@ -13,7 +13,7 @@ in {
   options = {
     programs.qdmr = {
       enable = lib.mkEnableOption (lib.mdDoc "QDMR - a GUI application and command line tool for programming DMR radios");
-      package = lib.mkPackageOptionMD pkgs "qdmr" { };
+      package = lib.mkPackageOption pkgs "qdmr" { };
     };
   };
 
diff --git a/nixpkgs/nixos/modules/programs/regreet.nix b/nixpkgs/nixos/modules/programs/regreet.nix
index 0fd9cf232981..0c44d717044e 100644
--- a/nixpkgs/nixos/modules/programs/regreet.nix
+++ b/nixpkgs/nixos/modules/programs/regreet.nix
@@ -24,7 +24,7 @@ in
       '';
     };
 
-    package = lib.mkPackageOptionMD pkgs [ "greetd" "regreet" ] { };
+    package = lib.mkPackageOption pkgs [ "greetd" "regreet" ] { };
 
     settings = lib.mkOption {
       type = lib.types.either lib.types.path settingsFormat.type;
diff --git a/nixpkgs/nixos/modules/programs/shadow.nix b/nixpkgs/nixos/modules/programs/shadow.nix
index 00895db03fc3..b232767385c5 100644
--- a/nixpkgs/nixos/modules/programs/shadow.nix
+++ b/nixpkgs/nixos/modules/programs/shadow.nix
@@ -7,7 +7,7 @@ in
 {
   options = with types; {
     security.loginDefs = {
-      package = mkPackageOptionMD pkgs "shadow" { };
+      package = mkPackageOption pkgs "shadow" { };
 
       chfnRestrict = mkOption {
         description = mdDoc ''
diff --git a/nixpkgs/nixos/modules/programs/singularity.nix b/nixpkgs/nixos/modules/programs/singularity.nix
index 05fdb4842c54..9fd37e1793a7 100644
--- a/nixpkgs/nixos/modules/programs/singularity.nix
+++ b/nixpkgs/nixos/modules/programs/singularity.nix
@@ -12,14 +12,8 @@ in
         Whether to install Singularity/Apptainer with system-level overriding such as SUID support.
       '';
     };
-    package = mkOption {
-      type = types.package;
-      default = pkgs.singularity;
-      defaultText = literalExpression "pkgs.singularity";
-      example = literalExpression "pkgs.apptainer";
-      description = mdDoc ''
-        Singularity/Apptainer package to override and install.
-      '';
+    package = mkPackageOption pkgs "singularity" {
+      example = "apptainer";
     };
     packageOverriden = mkOption {
       type = types.nullOr types.package;
@@ -45,6 +39,18 @@ in
         Use `lib.mkForce` to forcefully specify the overridden package.
       '';
     };
+    enableExternalLocalStateDir = mkOption {
+      type = types.bool;
+      default = true;
+      example = false;
+      description = mdDoc ''
+        Whether to use top-level directories as LOCALSTATEDIR
+        instead of the store path ones.
+        This affects the SESSIONDIR of Apptainer/Singularity.
+        If set to true, the SESSIONDIR will become
+        `/var/lib/''${projectName}/mnt/session`.
+      '';
+    };
     enableFakeroot = mkOption {
       type = types.bool;
       default = true;
@@ -65,7 +71,9 @@ in
 
   config = mkIf cfg.enable {
     programs.singularity.packageOverriden = (cfg.package.override (
-      optionalAttrs cfg.enableFakeroot {
+      optionalAttrs cfg.enableExternalLocalStateDir {
+        externalLocalStateDir = "/var/lib";
+      } // optionalAttrs cfg.enableFakeroot {
         newuidmapPath = "/run/wrappers/bin/newuidmap";
         newgidmapPath = "/run/wrappers/bin/newgidmap";
       } // optionalAttrs cfg.enableSuid {
@@ -80,12 +88,8 @@ in
       group = "root";
       source = "${cfg.packageOverriden}/libexec/${cfg.packageOverriden.projectName}/bin/starter-suid.orig";
     };
-    systemd.tmpfiles.rules = [
+    systemd.tmpfiles.rules = mkIf cfg.enableExternalLocalStateDir [
       "d /var/lib/${cfg.packageOverriden.projectName}/mnt/session 0770 root root -"
-      "d /var/lib/${cfg.packageOverriden.projectName}/mnt/final 0770 root root -"
-      "d /var/lib/${cfg.packageOverriden.projectName}/mnt/overlay 0770 root root -"
-      "d /var/lib/${cfg.packageOverriden.projectName}/mnt/container 0770 root root -"
-      "d /var/lib/${cfg.packageOverriden.projectName}/mnt/source 0770 root root -"
     ];
   };
 
diff --git a/nixpkgs/nixos/modules/programs/skim.nix b/nixpkgs/nixos/modules/programs/skim.nix
index 8dadf322606e..57a5d68ec3d5 100644
--- a/nixpkgs/nixos/modules/programs/skim.nix
+++ b/nixpkgs/nixos/modules/programs/skim.nix
@@ -1,6 +1,6 @@
 { pkgs, config, lib, ... }:
 let
-  inherit (lib) mdDoc mkEnableOption mkPackageOptionMD optional optionalString;
+  inherit (lib) mdDoc mkEnableOption mkPackageOption optional optionalString;
   cfg = config.programs.skim;
 in
 {
@@ -8,7 +8,7 @@ in
     programs.skim = {
       fuzzyCompletion = mkEnableOption (mdDoc "fuzzy completion with skim");
       keybindings = mkEnableOption (mdDoc "skim keybindings");
-      package = mkPackageOptionMD pkgs "skim" {};
+      package = mkPackageOption pkgs "skim" {};
     };
   };
 
diff --git a/nixpkgs/nixos/modules/programs/ssh.nix b/nixpkgs/nixos/modules/programs/ssh.nix
index 7c85d1e7c3d5..18eb3f938f3d 100644
--- a/nixpkgs/nixos/modules/programs/ssh.nix
+++ b/nixpkgs/nixos/modules/programs/ssh.nix
@@ -132,14 +132,7 @@ in
         '';
       };
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.openssh;
-        defaultText = literalExpression "pkgs.openssh";
-        description = lib.mdDoc ''
-          The package used for the openssh client and daemon.
-        '';
-      };
+      package = mkPackageOption pkgs "openssh" { };
 
       knownHosts = mkOption {
         default = {};
diff --git a/nixpkgs/nixos/modules/programs/streamdeck-ui.nix b/nixpkgs/nixos/modules/programs/streamdeck-ui.nix
index 220f0a35f162..47b1681cd634 100644
--- a/nixpkgs/nixos/modules/programs/streamdeck-ui.nix
+++ b/nixpkgs/nixos/modules/programs/streamdeck-ui.nix
@@ -15,7 +15,7 @@ in
       description = lib.mdDoc "Whether streamdeck-ui should be started automatically.";
     };
 
-    package = mkPackageOptionMD pkgs "streamdeck-ui" {
+    package = mkPackageOption pkgs "streamdeck-ui" {
       default = [ "streamdeck-ui" ];
     };
 
diff --git a/nixpkgs/nixos/modules/programs/tsm-client.nix b/nixpkgs/nixos/modules/programs/tsm-client.nix
index 41560544c2c7..6cb225d102de 100644
--- a/nixpkgs/nixos/modules/programs/tsm-client.nix
+++ b/nixpkgs/nixos/modules/programs/tsm-client.nix
@@ -5,7 +5,7 @@ let
   inherit (builtins) length map;
   inherit (lib.attrsets) attrNames filterAttrs hasAttr mapAttrs mapAttrsToList optionalAttrs;
   inherit (lib.modules) mkDefault mkIf;
-  inherit (lib.options) literalExpression mkEnableOption mkOption;
+  inherit (lib.options) literalExpression mkEnableOption mkOption mkPackageOption;
   inherit (lib.strings) concatLines optionalString toLower;
   inherit (lib.types) addCheck attrsOf lines nonEmptyStr nullOr package path port str strMatching submodule;
 
@@ -215,14 +215,9 @@ let
         TSM-depending packages used on the system.
       '';
     };
-    package = mkOption {
-      type = package;
-      default = pkgs.tsm-client;
-      defaultText = literalExpression "pkgs.tsm-client";
-      example = literalExpression "pkgs.tsm-client-withGui";
-      description = lib.mdDoc ''
-        The TSM client derivation to be
-        added to the system environment.
+    package = mkPackageOption pkgs "tsm-client" {
+      example = "tsm-client-withGui";
+      extraDescription = ''
         It will be used with `.override`
         to add paths to the client system-options file.
       '';
diff --git a/nixpkgs/nixos/modules/programs/vim.nix b/nixpkgs/nixos/modules/programs/vim.nix
index b12a45166d56..da2813f4bb53 100644
--- a/nixpkgs/nixos/modules/programs/vim.nix
+++ b/nixpkgs/nixos/modules/programs/vim.nix
@@ -15,14 +15,8 @@ in {
       '';
     };
 
-    package = mkOption {
-      type = types.package;
-      default = pkgs.vim;
-      defaultText = literalExpression "pkgs.vim";
-      example = literalExpression "pkgs.vim-full";
-      description = lib.mdDoc ''
-        vim package to use.
-      '';
+    package = mkPackageOption pkgs "vim" {
+      example = "vim-full";
     };
   };
 
diff --git a/nixpkgs/nixos/modules/programs/wayland/cardboard.nix b/nixpkgs/nixos/modules/programs/wayland/cardboard.nix
index 262c698c74ba..77a094a71700 100644
--- a/nixpkgs/nixos/modules/programs/wayland/cardboard.nix
+++ b/nixpkgs/nixos/modules/programs/wayland/cardboard.nix
@@ -9,7 +9,7 @@ in
   options.programs.cardboard = {
     enable = lib.mkEnableOption (lib.mdDoc "cardboard");
 
-    package = lib.mkPackageOptionMD pkgs "cardboard" { };
+    package = lib.mkPackageOption pkgs "cardboard" { };
   };
 
   config = lib.mkIf cfg.enable (lib.mkMerge [
diff --git a/nixpkgs/nixos/modules/programs/wayland/river.nix b/nixpkgs/nixos/modules/programs/wayland/river.nix
index 71232a7d2618..ec59bd50a015 100644
--- a/nixpkgs/nixos/modules/programs/wayland/river.nix
+++ b/nixpkgs/nixos/modules/programs/wayland/river.nix
@@ -10,12 +10,9 @@ in {
   options.programs.river = {
     enable = mkEnableOption (lib.mdDoc "river, a dynamic tiling Wayland compositor");
 
-    package = mkOption {
-      type = with types; nullOr package;
-      default = pkgs.river;
-      defaultText = literalExpression "pkgs.river";
-      description = lib.mdDoc ''
-        River package to use.
+    package = mkPackageOption pkgs "river" {
+      nullable = true;
+      extraDescription = ''
         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.
       '';
diff --git a/nixpkgs/nixos/modules/programs/wayland/sway.nix b/nixpkgs/nixos/modules/programs/wayland/sway.nix
index 698d9c2b46c4..f96c833856db 100644
--- a/nixpkgs/nixos/modules/programs/wayland/sway.nix
+++ b/nixpkgs/nixos/modules/programs/wayland/sway.nix
@@ -149,6 +149,8 @@ in {
             "sway/config".source = mkOptionDefault "${cfg.package}/etc/sway/config";
           };
         };
+        # https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1050913
+        xdg.portal.config.sway.default = mkDefault [ "wlr" "gtk" ];
         # To make a Sway session available if a display manager like SDDM is enabled:
         services.xserver.displayManager.sessionPackages = optionals (cfg.package != null) [ cfg.package ]; }
       (import ./wayland-session.nix { inherit lib pkgs; })
diff --git a/nixpkgs/nixos/modules/programs/wayland/waybar.nix b/nixpkgs/nixos/modules/programs/wayland/waybar.nix
index 2c49ae140813..ec60b84f6997 100644
--- a/nixpkgs/nixos/modules/programs/wayland/waybar.nix
+++ b/nixpkgs/nixos/modules/programs/wayland/waybar.nix
@@ -8,7 +8,7 @@ in
 {
   options.programs.waybar = {
     enable = mkEnableOption (lib.mdDoc "waybar");
-    package = mkPackageOptionMD pkgs "waybar" { };
+    package = mkPackageOption pkgs "waybar" { };
   };
 
   config = mkIf cfg.enable {
diff --git a/nixpkgs/nixos/modules/programs/wayland/wayfire.nix b/nixpkgs/nixos/modules/programs/wayland/wayfire.nix
index 9ea2010cf59c..0840246e5e3e 100644
--- a/nixpkgs/nixos/modules/programs/wayland/wayfire.nix
+++ b/nixpkgs/nixos/modules/programs/wayland/wayfire.nix
@@ -8,7 +8,7 @@ in
   options.programs.wayfire = {
     enable = lib.mkEnableOption (lib.mdDoc "Wayfire, a wayland compositor based on wlroots");
 
-    package = lib.mkPackageOptionMD pkgs "wayfire" { };
+    package = lib.mkPackageOption pkgs "wayfire" { };
 
     plugins = lib.mkOption {
       type = lib.types.listOf lib.types.package;
@@ -43,6 +43,8 @@ in
     xdg.portal = {
       enable = lib.mkDefault true;
       wlr.enable = lib.mkDefault true;
+      # https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1050914
+      config.wayfire.default = lib.mkDefault [ "wlr" "gtk" ];
     };
   };
 }
diff --git a/nixpkgs/nixos/modules/programs/weylus.nix b/nixpkgs/nixos/modules/programs/weylus.nix
index a5775f3b981c..f40dfd5c9613 100644
--- a/nixpkgs/nixos/modules/programs/weylus.nix
+++ b/nixpkgs/nixos/modules/programs/weylus.nix
@@ -26,12 +26,7 @@ in
       '';
     };
 
-    package = mkOption {
-      type = package;
-      default = pkgs.weylus;
-      defaultText = lib.literalExpression "pkgs.weylus";
-      description = lib.mdDoc "Weylus package to install.";
-    };
+    package = mkPackageOption pkgs "weylus" { };
   };
   config = mkIf cfg.enable {
     networking.firewall = mkIf cfg.openFirewall {
diff --git a/nixpkgs/nixos/modules/programs/wireshark.nix b/nixpkgs/nixos/modules/programs/wireshark.nix
index 834b0ba35695..c0dc349cca4a 100644
--- a/nixpkgs/nixos/modules/programs/wireshark.nix
+++ b/nixpkgs/nixos/modules/programs/wireshark.nix
@@ -16,13 +16,8 @@ in {
           setcap wrapper for 'dumpcap' for users in the 'wireshark' group.
         '';
       };
-      package = mkOption {
-        type = types.package;
-        default = pkgs.wireshark-cli;
-        defaultText = literalExpression "pkgs.wireshark-cli";
-        description = lib.mdDoc ''
-          Which Wireshark package to install in the global environment.
-        '';
+      package = mkPackageOption pkgs "wireshark-cli" {
+        example = "wireshark";
       };
     };
   };
diff --git a/nixpkgs/nixos/modules/programs/xonsh.nix b/nixpkgs/nixos/modules/programs/xonsh.nix
index 167c953f5ffd..2ece772c929e 100644
--- a/nixpkgs/nixos/modules/programs/xonsh.nix
+++ b/nixpkgs/nixos/modules/programs/xonsh.nix
@@ -24,14 +24,8 @@ in
         type = types.bool;
       };
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.xonsh;
-        defaultText = literalExpression "pkgs.xonsh";
-        example = literalExpression "pkgs.xonsh.override { extraPackages = ps: [ ps.requests ]; }";
-        description = lib.mdDoc ''
-          xonsh package to use.
-        '';
+      package = mkPackageOption pkgs "xonsh" {
+        example = "xonsh.override { extraPackages = ps: [ ps.requests ]; }";
       };
 
       config = mkOption {
diff --git a/nixpkgs/nixos/modules/programs/yazi.nix b/nixpkgs/nixos/modules/programs/yazi.nix
index 973f5c0122c2..273a7eeed05f 100644
--- a/nixpkgs/nixos/modules/programs/yazi.nix
+++ b/nixpkgs/nixos/modules/programs/yazi.nix
@@ -11,7 +11,7 @@ in
   options.programs.yazi = {
     enable = lib.mkEnableOption (lib.mdDoc "yazi terminal file manager");
 
-    package = lib.mkPackageOptionMD pkgs "yazi" { };
+    package = lib.mkPackageOption pkgs "yazi" { };
 
     settings = lib.mkOption {
       type = with lib.types; submodule {
diff --git a/nixpkgs/nixos/modules/programs/zsh/oh-my-zsh.nix b/nixpkgs/nixos/modules/programs/zsh/oh-my-zsh.nix
index 83eee1c88b3c..09c3bb974a50 100644
--- a/nixpkgs/nixos/modules/programs/zsh/oh-my-zsh.nix
+++ b/nixpkgs/nixos/modules/programs/zsh/oh-my-zsh.nix
@@ -46,15 +46,7 @@ in
           '';
         };
 
-        package = mkOption {
-          default = pkgs.oh-my-zsh;
-          defaultText = literalExpression "pkgs.oh-my-zsh";
-          description = lib.mdDoc ''
-            Package to install for `oh-my-zsh` usage.
-          '';
-
-          type = types.package;
-        };
+        package = mkPackageOption pkgs "oh-my-zsh" { };
 
         plugins = mkOption {
           default = [];
diff --git a/nixpkgs/nixos/modules/programs/zsh/zsh-autoenv.nix b/nixpkgs/nixos/modules/programs/zsh/zsh-autoenv.nix
index be93c96b2bc8..0894bfc3fdda 100644
--- a/nixpkgs/nixos/modules/programs/zsh/zsh-autoenv.nix
+++ b/nixpkgs/nixos/modules/programs/zsh/zsh-autoenv.nix
@@ -8,15 +8,7 @@ in {
   options = {
     programs.zsh.zsh-autoenv = {
       enable = mkEnableOption (lib.mdDoc "zsh-autoenv");
-      package = mkOption {
-        default = pkgs.zsh-autoenv;
-        defaultText = literalExpression "pkgs.zsh-autoenv";
-        description = lib.mdDoc ''
-          Package to install for `zsh-autoenv` usage.
-        '';
-
-        type = types.package;
-      };
+      package = mkPackageOption pkgs "zsh-autoenv" { };
     };
   };
 
diff --git a/nixpkgs/nixos/modules/security/lock-kernel-modules.nix b/nixpkgs/nixos/modules/security/lock-kernel-modules.nix
index 333b64801426..461b9ffe7ee0 100644
--- a/nixpkgs/nixos/modules/security/lock-kernel-modules.nix
+++ b/nixpkgs/nixos/modules/security/lock-kernel-modules.nix
@@ -1,4 +1,4 @@
-{ config, pkgs, lib, ... }:
+{ config, lib, ... }:
 
 with lib;
 
@@ -49,7 +49,7 @@ with lib;
         };
 
       script = ''
-        ${pkgs.udev}/bin/udevadm settle
+        ${config.systemd.package}/bin/udevadm settle
         echo -n 1 >/proc/sys/kernel/modules_disabled
       '';
     };
diff --git a/nixpkgs/nixos/modules/security/pam.nix b/nixpkgs/nixos/modules/security/pam.nix
index b7e1ea526535..c99615d5a636 100644
--- a/nixpkgs/nixos/modules/security/pam.nix
+++ b/nixpkgs/nixos/modules/security/pam.nix
@@ -943,6 +943,11 @@ let
       value.source = pkgs.writeText "${name}.pam" service.text;
     };
 
+  optionalSudoConfigForSSHAgentAuth = optionalString config.security.pam.enableSSHAgentAuth ''
+    # Keep SSH_AUTH_SOCK so that pam_ssh_agent_auth.so can do its magic.
+    Defaults env_keep+=SSH_AUTH_SOCK
+  '';
+
 in
 
 {
@@ -1532,9 +1537,7 @@ in
         concatLines
       ]);
 
-    security.sudo.extraConfig = optionalString config.security.pam.enableSSHAgentAuth ''
-      # Keep SSH_AUTH_SOCK so that pam_ssh_agent_auth.so can do its magic.
-      Defaults env_keep+=SSH_AUTH_SOCK
-    '';
-    };
+    security.sudo.extraConfig = optionalSudoConfigForSSHAgentAuth;
+    security.sudo-rs.extraConfig = optionalSudoConfigForSSHAgentAuth;
+  };
 }
diff --git a/nixpkgs/nixos/modules/security/please.nix b/nixpkgs/nixos/modules/security/please.nix
index 88bb9cba2bfc..ff4bfc9f1be1 100644
--- a/nixpkgs/nixos/modules/security/please.nix
+++ b/nixpkgs/nixos/modules/security/please.nix
@@ -13,14 +13,7 @@ in
       file as another user
     '');
 
-    package = mkOption {
-      type = types.package;
-      default = pkgs.please;
-      defaultText = literalExpression "pkgs.please";
-      description = mdDoc ''
-        Which package to use for {command}`please`.
-      '';
-    };
+    package = mkPackageOption pkgs "please" { };
 
     wheelNeedsPassword = mkOption {
       type = types.bool;
diff --git a/nixpkgs/nixos/modules/security/sudo-rs.nix b/nixpkgs/nixos/modules/security/sudo-rs.nix
index 6b8f09a8d3d0..f991675827ef 100644
--- a/nixpkgs/nixos/modules/security/sudo-rs.nix
+++ b/nixpkgs/nixos/modules/security/sudo-rs.nix
@@ -4,16 +4,9 @@ with lib;
 
 let
 
-  inherit (pkgs) sudo sudo-rs;
-
   cfg = config.security.sudo-rs;
 
-  enableSSHAgentAuth =
-    with config.security;
-    pam.enableSSHAgentAuth && pam.sudo.sshAgentAuth;
-
-  usingMillersSudo = cfg.package.pname == sudo.pname;
-  usingSudoRs = cfg.package.pname == sudo-rs.pname;
+  inherit (config.security.pam) enableSSHAgentAuth;
 
   toUserString = user: if (isInt user) then "#${toString user}" else "${user}";
   toGroupString = group: if (isInt group) then "%#${toString group}" else "%${group}";
@@ -41,33 +34,19 @@ in
 
     defaultOptions = mkOption {
       type = with types; listOf str;
-      default = optional usingMillersSudo "SETENV";
-      defaultText = literalMD ''
-        `[ "SETENV" ]` if using the default `sudo` implementation
-      '';
+      default = [];
       description = mdDoc ''
         Options used for the default rules, granting `root` and the
         `wheel` group permission to run any command as any user.
       '';
     };
 
-    enable = mkOption {
-      type = types.bool;
-      default = false;
-      description = mdDoc ''
-        Whether to enable the {command}`sudo` command, which
-        allows non-root users to execute commands as root.
-      '';
-    };
+    enable = mkEnableOption (mdDoc ''
+      a memory-safe implementation of the {command}`sudo` command,
+      which allows non-root users to execute commands as root.
+    '');
 
-    package = mkOption {
-      type = types.package;
-      default = pkgs.sudo-rs;
-      defaultText = literalExpression "pkgs.sudo-rs";
-      description = mdDoc ''
-        Which package to use for `sudo`.
-      '';
-    };
+    package = mkPackageOption pkgs "sudo-rs" { };
 
     wheelNeedsPassword = mkOption {
       type = types.bool;
@@ -208,6 +187,12 @@ in
   ###### implementation
 
   config = mkIf cfg.enable {
+    assertions = [ {
+      assertion = ! config.security.sudo.enable;
+      message = "`security.sudo` and `security.sudo-rs` cannot both be enabled";
+    }];
+    security.sudo.enable = mkDefault false;
+
     security.sudo-rs.extraRules =
       let
         defaultRule = { users ? [], groups ? [], opts ? [] }: [ {
@@ -235,20 +220,16 @@ in
         # Don't edit this file. Set the NixOS options ‘security.sudo-rs.configFile’
         # or ‘security.sudo-rs.extraRules’ instead.
       ''
-      (optionalString enableSSHAgentAuth ''
-        # Keep SSH_AUTH_SOCK so that pam_ssh_agent_auth.so can do its magic.
-        Defaults env_keep+=SSH_AUTH_SOCK
-      '')
-      (concatStringsSep "\n" (
-        lists.flatten (
-          map (
-            rule: optionals (length rule.commands != 0) [
-              (map (user: "${toUserString user}	${rule.host}=(${rule.runAs})	${toCommandsString rule.commands}") rule.users)
-              (map (group: "${toGroupString group}	${rule.host}=(${rule.runAs})	${toCommandsString rule.commands}") rule.groups)
-            ]
-          ) cfg.extraRules
-        )
-      ) + "\n")
+      (pipe cfg.extraRules [
+        (filter (rule: length rule.commands != 0))
+        (map (rule: [
+          (map (user: "${toUserString user}     ${rule.host}=(${rule.runAs})    ${toCommandsString rule.commands}") rule.users)
+          (map (group: "${toGroupString group}  ${rule.host}=(${rule.runAs})    ${toCommandsString rule.commands}") rule.groups)
+        ]))
+        flatten
+        (concatStringsSep "\n")
+      ])
+      "\n"
       (optionalString (cfg.extraConfig != "") ''
         # extraConfig
         ${cfg.extraConfig}
@@ -265,18 +246,12 @@ in
         source = "${cfg.package.out}/bin/sudo";
         inherit owner group setuid permissions;
       };
-      # sudo-rs does not yet ship a sudoedit (as of v0.2.0)
-      sudoedit = mkIf usingMillersSudo {
-        source = "${cfg.package.out}/bin/sudoedit";
-        inherit owner group setuid permissions;
-      };
     };
 
-    environment.systemPackages = [ sudo ];
+    environment.systemPackages = [ cfg.package ];
 
     security.pam.services.sudo = { sshAgentAuth = true; usshAuth = true; };
-    security.pam.services.sudo-i = mkIf usingSudoRs
-      { sshAgentAuth = true; usshAuth = true; };
+    security.pam.services.sudo-i = { sshAgentAuth = true; usshAuth = true; };
 
     environment.etc.sudoers =
       { source =
@@ -285,7 +260,7 @@ in
             src = pkgs.writeText "sudoers-in" cfg.configFile;
             preferLocalBuild = true;
           }
-          "${pkgs.buildPackages."${cfg.package.pname}"}/bin/visudo -f $src -c && cp $src $out";
+          "${pkgs.buildPackages.sudo-rs}/bin/visudo -f $src -c && cp $src $out";
         mode = "0440";
       };
 
diff --git a/nixpkgs/nixos/modules/services/admin/meshcentral.nix b/nixpkgs/nixos/modules/services/admin/meshcentral.nix
index 22f31e952622..d056356568da 100644
--- a/nixpkgs/nixos/modules/services/admin/meshcentral.nix
+++ b/nixpkgs/nixos/modules/services/admin/meshcentral.nix
@@ -6,12 +6,7 @@ let
 in with lib; {
   options.services.meshcentral = with types; {
     enable = mkEnableOption (lib.mdDoc "MeshCentral computer management server");
-    package = mkOption {
-      description = lib.mdDoc "MeshCentral package to use. Replacing this may be necessary to add dependencies for extra functionality.";
-      type = types.package;
-      default = pkgs.meshcentral;
-      defaultText = literalExpression "pkgs.meshcentral";
-    };
+    package = mkPackageOption pkgs "meshcentral" { };
     settings = mkOption {
       description = lib.mdDoc ''
         Settings for MeshCentral. Refer to upstream documentation for details:
diff --git a/nixpkgs/nixos/modules/services/amqp/rabbitmq.nix b/nixpkgs/nixos/modules/services/amqp/rabbitmq.nix
index 11dabf0b51c8..7dce9d242916 100644
--- a/nixpkgs/nixos/modules/services/amqp/rabbitmq.nix
+++ b/nixpkgs/nixos/modules/services/amqp/rabbitmq.nix
@@ -26,14 +26,7 @@ in
         '';
       };
 
-      package = mkOption {
-        default = pkgs.rabbitmq-server;
-        type = types.package;
-        defaultText = literalExpression "pkgs.rabbitmq-server";
-        description = lib.mdDoc ''
-          Which rabbitmq package to use.
-        '';
-      };
+      package = mkPackageOption pkgs "rabbitmq-server" { };
 
       listenAddress = mkOption {
         default = "127.0.0.1";
diff --git a/nixpkgs/nixos/modules/services/audio/botamusique.nix b/nixpkgs/nixos/modules/services/audio/botamusique.nix
index 5d3f7db12bc9..42227cb14722 100644
--- a/nixpkgs/nixos/modules/services/audio/botamusique.nix
+++ b/nixpkgs/nixos/modules/services/audio/botamusique.nix
@@ -14,12 +14,7 @@ in
   options.services.botamusique = {
     enable = mkEnableOption (lib.mdDoc "botamusique, a bot to play audio streams on mumble");
 
-    package = mkOption {
-      type = types.package;
-      default = pkgs.botamusique;
-      defaultText = literalExpression "pkgs.botamusique";
-      description = lib.mdDoc "The botamusique package to use.";
-    };
+    package = mkPackageOption pkgs "botamusique" { };
 
     settings = mkOption {
       type = with types; submodule {
diff --git a/nixpkgs/nixos/modules/services/audio/gmediarender.nix b/nixpkgs/nixos/modules/services/audio/gmediarender.nix
index 2f23232d19cf..545f2b1a2b60 100644
--- a/nixpkgs/nixos/modules/services/audio/gmediarender.nix
+++ b/nixpkgs/nixos/modules/services/audio/gmediarender.nix
@@ -41,7 +41,7 @@ in
       '';
     };
 
-    package = mkPackageOptionMD pkgs "gmediarender" {
+    package = mkPackageOption pkgs "gmediarender" {
       default = "gmrender-resurrect";
     };
 
diff --git a/nixpkgs/nixos/modules/services/audio/goxlr-utility.nix b/nixpkgs/nixos/modules/services/audio/goxlr-utility.nix
index b719de875c7f..c047dbb221b1 100644
--- a/nixpkgs/nixos/modules/services/audio/goxlr-utility.nix
+++ b/nixpkgs/nixos/modules/services/audio/goxlr-utility.nix
@@ -16,7 +16,7 @@ with lib;
           Whether to enable goxlr-utility for controlling your TC-Helicon GoXLR or GoXLR Mini
         '';
       };
-      package = mkPackageOptionMD pkgs "goxlr-utility" { };
+      package = mkPackageOption pkgs "goxlr-utility" { };
       autoStart.xdg = mkOption {
         default = true;
         type = with types; bool;
diff --git a/nixpkgs/nixos/modules/services/audio/jack.nix b/nixpkgs/nixos/modules/services/audio/jack.nix
index b51f2a78c983..3869bd974cce 100644
--- a/nixpkgs/nixos/modules/services/audio/jack.nix
+++ b/nixpkgs/nixos/modules/services/audio/jack.nix
@@ -20,16 +20,11 @@ in {
           JACK Audio Connection Kit. You need to add yourself to the "jackaudio" group
         '');
 
-        package = mkOption {
+        package = mkPackageOption pkgs "jack2" {
+          example = "jack1";
+        } // {
           # until jack1 promiscuous mode is fixed
           internal = true;
-          type = types.package;
-          default = pkgs.jack2;
-          defaultText = literalExpression "pkgs.jack2";
-          example = literalExpression "pkgs.jack1";
-          description = lib.mdDoc ''
-            The JACK package to use.
-          '';
         };
 
         extraOptions = mkOption {
diff --git a/nixpkgs/nixos/modules/services/audio/jmusicbot.nix b/nixpkgs/nixos/modules/services/audio/jmusicbot.nix
index 348c7b25682e..fd1d4da19284 100644
--- a/nixpkgs/nixos/modules/services/audio/jmusicbot.nix
+++ b/nixpkgs/nixos/modules/services/audio/jmusicbot.nix
@@ -9,12 +9,7 @@ in
     services.jmusicbot = {
       enable = mkEnableOption (lib.mdDoc "jmusicbot, a Discord music bot that's easy to set up and run yourself");
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.jmusicbot;
-        defaultText = literalExpression "pkgs.jmusicbot";
-        description = lib.mdDoc "JMusicBot package to use";
-      };
+      package = mkPackageOption pkgs "jmusicbot" { };
 
       stateDir = mkOption {
         type = types.path;
diff --git a/nixpkgs/nixos/modules/services/audio/navidrome.nix b/nixpkgs/nixos/modules/services/audio/navidrome.nix
index 77a0e74af9ca..e44fc822e4ad 100644
--- a/nixpkgs/nixos/modules/services/audio/navidrome.nix
+++ b/nixpkgs/nixos/modules/services/audio/navidrome.nix
@@ -11,7 +11,7 @@ in {
 
       enable = mkEnableOption (lib.mdDoc "Navidrome music server");
 
-      package = mkPackageOptionMD pkgs "navidrome" { };
+      package = mkPackageOption pkgs "navidrome" { };
 
       settings = mkOption rec {
         type = settingsFormat.type;
diff --git a/nixpkgs/nixos/modules/services/audio/slimserver.nix b/nixpkgs/nixos/modules/services/audio/slimserver.nix
index cdd9d551c501..73cda08c5742 100644
--- a/nixpkgs/nixos/modules/services/audio/slimserver.nix
+++ b/nixpkgs/nixos/modules/services/audio/slimserver.nix
@@ -19,12 +19,7 @@ in {
         '';
       };
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.slimserver;
-        defaultText = literalExpression "pkgs.slimserver";
-        description = lib.mdDoc "Slimserver package to use.";
-      };
+      package = mkPackageOption pkgs "slimserver" { };
 
       dataDir = mkOption {
         type = types.path;
diff --git a/nixpkgs/nixos/modules/services/audio/wyoming/faster-whisper.nix b/nixpkgs/nixos/modules/services/audio/wyoming/faster-whisper.nix
index 2d56acdc1b4c..eda409f1f800 100644
--- a/nixpkgs/nixos/modules/services/audio/wyoming/faster-whisper.nix
+++ b/nixpkgs/nixos/modules/services/audio/wyoming/faster-whisper.nix
@@ -12,7 +12,7 @@ let
     mkOption
     mdDoc
     mkEnableOption
-    mkPackageOptionMD
+    mkPackageOption
     types
     ;
 
@@ -24,7 +24,7 @@ in
 
 {
   options.services.wyoming.faster-whisper = with types; {
-    package = mkPackageOptionMD pkgs "wyoming-faster-whisper" { };
+    package = mkPackageOption pkgs "wyoming-faster-whisper" { };
 
     servers = mkOption {
       default = {};
diff --git a/nixpkgs/nixos/modules/services/audio/wyoming/openwakeword.nix b/nixpkgs/nixos/modules/services/audio/wyoming/openwakeword.nix
index 987818246bde..252f70be2baa 100644
--- a/nixpkgs/nixos/modules/services/audio/wyoming/openwakeword.nix
+++ b/nixpkgs/nixos/modules/services/audio/wyoming/openwakeword.nix
@@ -15,7 +15,7 @@ let
     mdDoc
     mkEnableOption
     mkIf
-    mkPackageOptionMD
+    mkPackageOption
     mkRemovedOptionModule
     types
     ;
@@ -36,7 +36,7 @@ in
   options.services.wyoming.openwakeword = with types; {
     enable = mkEnableOption (mdDoc "Wyoming openWakeWord server");
 
-    package = mkPackageOptionMD pkgs "wyoming-openwakeword" { };
+    package = mkPackageOption pkgs "wyoming-openwakeword" { };
 
     uri = mkOption {
       type = strMatching "^(tcp|unix)://.*$";
diff --git a/nixpkgs/nixos/modules/services/audio/wyoming/piper.nix b/nixpkgs/nixos/modules/services/audio/wyoming/piper.nix
index ed50bd9f48e9..698828aa6cba 100644
--- a/nixpkgs/nixos/modules/services/audio/wyoming/piper.nix
+++ b/nixpkgs/nixos/modules/services/audio/wyoming/piper.nix
@@ -12,7 +12,7 @@ let
     mkOption
     mdDoc
     mkEnableOption
-    mkPackageOptionMD
+    mkPackageOption
     types
     ;
 
@@ -26,7 +26,7 @@ in
   meta.buildDocsInSandbox = false;
 
   options.services.wyoming.piper = with types; {
-    package = mkPackageOptionMD pkgs "wyoming-piper" { };
+    package = mkPackageOption pkgs "wyoming-piper" { };
 
     servers = mkOption {
       default = {};
@@ -38,7 +38,7 @@ in
           options = {
             enable = mkEnableOption (mdDoc "Wyoming Piper server");
 
-            piper = mkPackageOptionMD pkgs "piper-tts" { };
+            piper = mkPackageOption pkgs "piper-tts" { };
 
             voice = mkOption {
               type = str;
diff --git a/nixpkgs/nixos/modules/services/backup/borgbackup.nix b/nixpkgs/nixos/modules/services/backup/borgbackup.nix
index 28887f8e2ad5..039a5f227ac4 100644
--- a/nixpkgs/nixos/modules/services/backup/borgbackup.nix
+++ b/nixpkgs/nixos/modules/services/backup/borgbackup.nix
@@ -231,7 +231,7 @@ in {
 
   ###### interface
 
-  options.services.borgbackup.package = mkPackageOptionMD pkgs "borgbackup" { };
+  options.services.borgbackup.package = mkPackageOption pkgs "borgbackup" { };
 
   options.services.borgbackup.jobs = mkOption {
     description = lib.mdDoc ''
diff --git a/nixpkgs/nixos/modules/services/backup/btrbk.nix b/nixpkgs/nixos/modules/services/backup/btrbk.nix
index 9b7f1566eb1e..1e90ef54d33f 100644
--- a/nixpkgs/nixos/modules/services/backup/btrbk.nix
+++ b/nixpkgs/nixos/modules/services/backup/btrbk.nix
@@ -47,8 +47,21 @@ let
     then [ "${name} ${value}" ]
     else concatLists (mapAttrsToList (genSection name) value);
 
+  sudoRule = {
+    users = [ "btrbk" ];
+    commands = [
+      { command = "${pkgs.btrfs-progs}/bin/btrfs"; options = [ "NOPASSWD" ]; }
+      { command = "${pkgs.coreutils}/bin/mkdir"; options = [ "NOPASSWD" ]; }
+      { command = "${pkgs.coreutils}/bin/readlink"; options = [ "NOPASSWD" ]; }
+      # for ssh, they are not the same than the one hard coded in ${pkgs.btrbk}
+      { command = "/run/current-system/sw/bin/btrfs"; options = [ "NOPASSWD" ]; }
+      { command = "/run/current-system/sw/bin/mkdir"; options = [ "NOPASSWD" ]; }
+      { command = "/run/current-system/sw/bin/readlink"; options = [ "NOPASSWD" ]; }
+    ];
+  };
+
   sudo_doas =
-    if config.security.sudo.enable then "sudo"
+    if config.security.sudo.enable || config.security.sudo-rs.enable then "sudo"
     else if config.security.doas.enable then "doas"
     else throw "The btrbk nixos module needs either sudo or doas enabled in the configuration";
 
@@ -157,22 +170,10 @@ in
   };
   config = mkIf (sshEnabled || serviceEnabled) {
     environment.systemPackages = [ pkgs.btrbk ] ++ cfg.extraPackages;
-    security.sudo = mkIf (sudo_doas == "sudo") {
-      extraRules = [
-        {
-            users = [ "btrbk" ];
-            commands = [
-            { command = "${pkgs.btrfs-progs}/bin/btrfs"; options = [ "NOPASSWD" ]; }
-            { command = "${pkgs.coreutils}/bin/mkdir"; options = [ "NOPASSWD" ]; }
-            { command = "${pkgs.coreutils}/bin/readlink"; options = [ "NOPASSWD" ]; }
-            # for ssh, they are not the same than the one hard coded in ${pkgs.btrbk}
-            { command = "/run/current-system/sw/bin/btrfs"; options = [ "NOPASSWD" ]; }
-            { command = "/run/current-system/sw/bin/mkdir"; options = [ "NOPASSWD" ]; }
-            { command = "/run/current-system/sw/bin/readlink"; options = [ "NOPASSWD" ]; }
-            ];
-        }
-      ];
-    };
+
+    security.sudo.extraRules = mkIf (sudo_doas == "sudo") [ sudoRule ];
+    security.sudo-rs.extraRules = mkIf (sudo_doas == "sudo") [ sudoRule ];
+
     security.doas = mkIf (sudo_doas == "doas") {
       extraRules = let
         doasCmdNoPass = cmd: { users = [ "btrbk" ]; cmd = cmd; noPass = true; };
diff --git a/nixpkgs/nixos/modules/services/backup/duplicati.nix b/nixpkgs/nixos/modules/services/backup/duplicati.nix
index 9b422635e7f0..bd433b777ec4 100644
--- a/nixpkgs/nixos/modules/services/backup/duplicati.nix
+++ b/nixpkgs/nixos/modules/services/backup/duplicati.nix
@@ -10,7 +10,7 @@ in
     services.duplicati = {
       enable = mkEnableOption (lib.mdDoc "Duplicati");
 
-      package = mkPackageOptionMD pkgs "duplicati" { };
+      package = mkPackageOption pkgs "duplicati" { };
 
       port = mkOption {
         default = 8200;
diff --git a/nixpkgs/nixos/modules/services/backup/postgresql-wal-receiver.nix b/nixpkgs/nixos/modules/services/backup/postgresql-wal-receiver.nix
index 773dc0ba447d..332a32d37052 100644
--- a/nixpkgs/nixos/modules/services/backup/postgresql-wal-receiver.nix
+++ b/nixpkgs/nixos/modules/services/backup/postgresql-wal-receiver.nix
@@ -5,12 +5,8 @@ with lib;
 let
   receiverSubmodule = {
     options = {
-      postgresqlPackage = mkOption {
-        type = types.package;
-        example = literalExpression "pkgs.postgresql_15";
-        description = lib.mdDoc ''
-          PostgreSQL package to use.
-        '';
+      postgresqlPackage = mkPackageOption pkgs "postgresql" {
+        example = "postgresql_15";
       };
 
       directory = mkOption {
diff --git a/nixpkgs/nixos/modules/services/backup/restic-rest-server.nix b/nixpkgs/nixos/modules/services/backup/restic-rest-server.nix
index 37a6150c99d3..105a05caf304 100644
--- a/nixpkgs/nixos/modules/services/backup/restic-rest-server.nix
+++ b/nixpkgs/nixos/modules/services/backup/restic-rest-server.nix
@@ -57,12 +57,7 @@ in
       '';
     };
 
-    package = mkOption {
-      default = pkgs.restic-rest-server;
-      defaultText = literalExpression "pkgs.restic-rest-server";
-      type = types.package;
-      description = lib.mdDoc "Restic REST server package to use.";
-    };
+    package = mkPackageOption pkgs "restic-rest-server" { };
   };
 
   config = mkIf cfg.enable {
diff --git a/nixpkgs/nixos/modules/services/backup/restic.nix b/nixpkgs/nixos/modules/services/backup/restic.nix
index 87595f39796d..e3eb504e0adf 100644
--- a/nixpkgs/nixos/modules/services/backup/restic.nix
+++ b/nixpkgs/nixos/modules/services/backup/restic.nix
@@ -245,14 +245,7 @@ in
           '';
         };
 
-        package = mkOption {
-          type = types.package;
-          default = pkgs.restic;
-          defaultText = literalExpression "pkgs.restic";
-          description = lib.mdDoc ''
-            Restic package to use.
-          '';
-        };
+        package = mkPackageOption pkgs "restic" { };
 
         createWrapper = lib.mkOption {
           type = lib.types.bool;
diff --git a/nixpkgs/nixos/modules/services/backup/sanoid.nix b/nixpkgs/nixos/modules/services/backup/sanoid.nix
index aae77cee07d0..46d1de4ed934 100644
--- a/nixpkgs/nixos/modules/services/backup/sanoid.nix
+++ b/nixpkgs/nixos/modules/services/backup/sanoid.nix
@@ -114,7 +114,7 @@ in
   options.services.sanoid = {
     enable = mkEnableOption (lib.mdDoc "Sanoid ZFS snapshotting service");
 
-    package = lib.mkPackageOptionMD pkgs "sanoid" {};
+    package = lib.mkPackageOption pkgs "sanoid" {};
 
     interval = mkOption {
       type = types.str;
diff --git a/nixpkgs/nixos/modules/services/backup/syncoid.nix b/nixpkgs/nixos/modules/services/backup/syncoid.nix
index 1a1df38617b5..7b8d3b431309 100644
--- a/nixpkgs/nixos/modules/services/backup/syncoid.nix
+++ b/nixpkgs/nixos/modules/services/backup/syncoid.nix
@@ -87,7 +87,7 @@ in
   options.services.syncoid = {
     enable = mkEnableOption (lib.mdDoc "Syncoid ZFS synchronization service");
 
-    package = lib.mkPackageOptionMD pkgs "sanoid" {};
+    package = lib.mkPackageOption pkgs "sanoid" {};
 
     interval = mkOption {
       type = types.str;
@@ -123,9 +123,7 @@ in
     };
 
     sshKey = mkOption {
-      type = types.nullOr types.path;
-      # Prevent key from being copied to store
-      apply = mapNullable toString;
+      type = with types; nullOr (coercedTo path toString str);
       default = null;
       description = lib.mdDoc ''
         SSH private key file to use to login to the remote system. Can be
@@ -205,9 +203,7 @@ in
           recursive = mkEnableOption (lib.mdDoc ''the transfer of child datasets'');
 
           sshKey = mkOption {
-            type = types.nullOr types.path;
-            # Prevent key from being copied to store
-            apply = mapNullable toString;
+            type = with types; nullOr (coercedTo path toString str);
             description = lib.mdDoc ''
               SSH private key file to use to login to the remote system.
               Defaults to {option}`services.syncoid.sshKey` option.
diff --git a/nixpkgs/nixos/modules/services/backup/zrepl.nix b/nixpkgs/nixos/modules/services/backup/zrepl.nix
index 1d3afa3eda05..8475a347429e 100644
--- a/nixpkgs/nixos/modules/services/backup/zrepl.nix
+++ b/nixpkgs/nixos/modules/services/backup/zrepl.nix
@@ -13,12 +13,7 @@ in
     services.zrepl = {
       enable = mkEnableOption (lib.mdDoc "zrepl");
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.zrepl;
-        defaultText = literalExpression "pkgs.zrepl";
-        description = lib.mdDoc "Which package to use for zrepl";
-      };
+      package = mkPackageOption pkgs "zrepl" { };
 
       settings = mkOption {
         default = { };
diff --git a/nixpkgs/nixos/modules/services/blockchain/ethereum/erigon.nix b/nixpkgs/nixos/modules/services/blockchain/ethereum/erigon.nix
index 945a373d1274..b8edee33e7c6 100644
--- a/nixpkgs/nixos/modules/services/blockchain/ethereum/erigon.nix
+++ b/nixpkgs/nixos/modules/services/blockchain/ethereum/erigon.nix
@@ -13,7 +13,7 @@ in {
     services.erigon = {
       enable = mkEnableOption (lib.mdDoc "Ethereum implementation on the efficiency frontier");
 
-      package = mkPackageOptionMD pkgs "erigon" { };
+      package = mkPackageOption pkgs "erigon" { };
 
       extraArgs = mkOption {
         type = types.listOf types.str;
diff --git a/nixpkgs/nixos/modules/services/blockchain/ethereum/geth.nix b/nixpkgs/nixos/modules/services/blockchain/ethereum/geth.nix
index d12516ca2f24..f07dfa4dc711 100644
--- a/nixpkgs/nixos/modules/services/blockchain/ethereum/geth.nix
+++ b/nixpkgs/nixos/modules/services/blockchain/ethereum/geth.nix
@@ -135,12 +135,7 @@ let
         default = [];
       };
 
-      package = mkOption {
-        default = pkgs.go-ethereum.geth;
-        defaultText = literalExpression "pkgs.go-ethereum.geth";
-        type = types.package;
-        description = lib.mdDoc "Package to use as Go Ethereum node.";
-      };
+      package = mkPackageOption pkgs [ "go-ethereum" "geth" ] { };
     };
   };
 in
diff --git a/nixpkgs/nixos/modules/services/cluster/corosync/default.nix b/nixpkgs/nixos/modules/services/cluster/corosync/default.nix
index 7ef17c46b81e..477ffbcdb7c7 100644
--- a/nixpkgs/nixos/modules/services/cluster/corosync/default.nix
+++ b/nixpkgs/nixos/modules/services/cluster/corosync/default.nix
@@ -9,12 +9,7 @@ in
   options.services.corosync = {
     enable = mkEnableOption (lib.mdDoc "corosync");
 
-    package = mkOption {
-      type = types.package;
-      default = pkgs.corosync;
-      defaultText = literalExpression "pkgs.corosync";
-      description = lib.mdDoc "Package that should be used for corosync.";
-    };
+    package = mkPackageOption pkgs "corosync" { };
 
     clusterName = mkOption {
       type = types.str;
diff --git a/nixpkgs/nixos/modules/services/cluster/hadoop/default.nix b/nixpkgs/nixos/modules/services/cluster/hadoop/default.nix
index ff6b4d5588b1..6fa91d2f047e 100644
--- a/nixpkgs/nixos/modules/services/cluster/hadoop/default.nix
+++ b/nixpkgs/nixos/modules/services/cluster/hadoop/default.nix
@@ -199,12 +199,7 @@ with lib;
 
     gatewayRole.enable = mkEnableOption (lib.mdDoc "gateway role for deploying hadoop configs");
 
-    package = mkOption {
-      type = types.package;
-      default = pkgs.hadoop;
-      defaultText = literalExpression "pkgs.hadoop";
-      description = lib.mdDoc "";
-    };
+    package = mkPackageOption pkgs "hadoop" { };
   };
 
 
diff --git a/nixpkgs/nixos/modules/services/cluster/hadoop/hbase.nix b/nixpkgs/nixos/modules/services/cluster/hadoop/hbase.nix
index a39da2a84eca..6801e505db64 100644
--- a/nixpkgs/nixos/modules/services/cluster/hadoop/hbase.nix
+++ b/nixpkgs/nixos/modules/services/cluster/hadoop/hbase.nix
@@ -134,12 +134,7 @@ in
 
     hbase = {
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.hbase;
-        defaultText = literalExpression "pkgs.hbase";
-        description = mdDoc "HBase package";
-      };
+      package = mkPackageOption pkgs "hbase" { };
 
       rootdir = mkOption {
         description = mdDoc ''
diff --git a/nixpkgs/nixos/modules/services/cluster/k3s/default.nix b/nixpkgs/nixos/modules/services/cluster/k3s/default.nix
index 72b2f992a339..dc71f1372d7a 100644
--- a/nixpkgs/nixos/modules/services/cluster/k3s/default.nix
+++ b/nixpkgs/nixos/modules/services/cluster/k3s/default.nix
@@ -15,12 +15,7 @@ in
   options.services.k3s = {
     enable = mkEnableOption (lib.mdDoc "k3s");
 
-    package = mkOption {
-      type = types.package;
-      default = pkgs.k3s;
-      defaultText = literalExpression "pkgs.k3s";
-      description = lib.mdDoc "Package that should be used for k3s";
-    };
+    package = mkPackageOption pkgs "k3s" { };
 
     role = mkOption {
       description = lib.mdDoc ''
diff --git a/nixpkgs/nixos/modules/services/cluster/kubernetes/default.nix b/nixpkgs/nixos/modules/services/cluster/kubernetes/default.nix
index f5374fc71942..3fb916c76971 100644
--- a/nixpkgs/nixos/modules/services/cluster/kubernetes/default.nix
+++ b/nixpkgs/nixos/modules/services/cluster/kubernetes/default.nix
@@ -122,12 +122,7 @@ in {
       type = types.listOf (types.enum ["master" "node"]);
     };
 
-    package = mkOption {
-      description = lib.mdDoc "Kubernetes package to use.";
-      type = types.package;
-      default = pkgs.kubernetes;
-      defaultText = literalExpression "pkgs.kubernetes";
-    };
+    package = mkPackageOption pkgs "kubernetes" { };
 
     kubeconfig = mkKubeConfigOptions "Default kubeconfig";
 
diff --git a/nixpkgs/nixos/modules/services/cluster/pacemaker/default.nix b/nixpkgs/nixos/modules/services/cluster/pacemaker/default.nix
index 0f37f4b754fe..255bb107796f 100644
--- a/nixpkgs/nixos/modules/services/cluster/pacemaker/default.nix
+++ b/nixpkgs/nixos/modules/services/cluster/pacemaker/default.nix
@@ -9,12 +9,7 @@ in
   options.services.pacemaker = {
     enable = mkEnableOption (lib.mdDoc "pacemaker");
 
-    package = mkOption {
-      type = types.package;
-      default = pkgs.pacemaker;
-      defaultText = literalExpression "pkgs.pacemaker";
-      description = lib.mdDoc "Package that should be used for pacemaker.";
-    };
+    package = mkPackageOption pkgs "pacemaker" { };
   };
 
   # implementation
diff --git a/nixpkgs/nixos/modules/services/cluster/spark/default.nix b/nixpkgs/nixos/modules/services/cluster/spark/default.nix
index bf39c5537332..2e3914a734be 100644
--- a/nixpkgs/nixos/modules/services/cluster/spark/default.nix
+++ b/nixpkgs/nixos/modules/services/cluster/spark/default.nix
@@ -77,20 +77,18 @@ with lib;
         description = lib.mdDoc "Spark log directory.";
         default = "/var/log/spark";
       };
-      package = mkOption {
-        type = types.package;
-        description = lib.mdDoc "Spark package.";
-        default = pkgs.spark;
-        defaultText = literalExpression "pkgs.spark";
-        example = literalExpression ''pkgs.spark.overrideAttrs (super: rec {
-          pname = "spark";
-          version = "2.4.4";
+      package = mkPackageOption pkgs "spark" {
+        example = ''
+          spark.overrideAttrs (super: rec {
+            pname = "spark";
+            version = "2.4.4";
 
-          src = pkgs.fetchzip {
-            url    = "mirror://apache/spark/"''${pname}-''${version}/''${pname}-''${version}-bin-without-hadoop.tgz";
-            sha256 = "1a9w5k0207fysgpxx6db3a00fs5hdc2ncx99x4ccy2s0v5ndc66g";
-          };
-        })'';
+            src = pkgs.fetchzip {
+              url    = "mirror://apache/spark/"''${pname}-''${version}/''${pname}-''${version}-bin-without-hadoop.tgz";
+              sha256 = "1a9w5k0207fysgpxx6db3a00fs5hdc2ncx99x4ccy2s0v5ndc66g";
+            };
+          })
+        '';
       };
     };
   };
diff --git a/nixpkgs/nixos/modules/services/computing/boinc/client.nix b/nixpkgs/nixos/modules/services/computing/boinc/client.nix
index ff16795c8208..c2132149a3f5 100644
--- a/nixpkgs/nixos/modules/services/computing/boinc/client.nix
+++ b/nixpkgs/nixos/modules/services/computing/boinc/client.nix
@@ -27,14 +27,8 @@ in
         '';
       };
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.boinc;
-        defaultText = literalExpression "pkgs.boinc";
-        example = literalExpression "pkgs.boinc-headless";
-        description = lib.mdDoc ''
-          Which BOINC package to use.
-        '';
+      package = mkPackageOption pkgs "boinc" {
+        example = "boinc-headless";
       };
 
       dataDir = mkOption {
diff --git a/nixpkgs/nixos/modules/services/computing/foldingathome/client.nix b/nixpkgs/nixos/modules/services/computing/foldingathome/client.nix
index 1229e5ac987e..09f31cda769c 100644
--- a/nixpkgs/nixos/modules/services/computing/foldingathome/client.nix
+++ b/nixpkgs/nixos/modules/services/computing/foldingathome/client.nix
@@ -20,14 +20,7 @@ in
   options.services.foldingathome = {
     enable = mkEnableOption (lib.mdDoc "Folding@home client");
 
-    package = mkOption {
-      type = types.package;
-      default = pkgs.fahclient;
-      defaultText = literalExpression "pkgs.fahclient";
-      description = lib.mdDoc ''
-        Which Folding@home client to use.
-      '';
-    };
+    package = mkPackageOption pkgs "fahclient" { };
 
     user = mkOption {
       type = types.nullOr types.str;
@@ -63,7 +56,7 @@ in
       default = [];
       description = lib.mdDoc ''
         Extra startup options for the FAHClient. Run
-        `FAHClient --help` to find all the available options.
+        `fah-client --help` to find all the available options.
       '';
     };
   };
@@ -74,7 +67,7 @@ in
       after = [ "network.target" ];
       wantedBy = [ "multi-user.target" ];
       script = ''
-        exec ${cfg.package}/bin/FAHClient ${lib.escapeShellArgs args}
+        exec ${lib.getExe cfg.package} ${lib.escapeShellArgs args}
       '';
       serviceConfig = {
         DynamicUser = true;
diff --git a/nixpkgs/nixos/modules/services/computing/slurm/slurm.nix b/nixpkgs/nixos/modules/services/computing/slurm/slurm.nix
index 1cbe7b893f83..9212fe39fd83 100644
--- a/nixpkgs/nixos/modules/services/computing/slurm/slurm.nix
+++ b/nixpkgs/nixos/modules/services/computing/slurm/slurm.nix
@@ -131,14 +131,10 @@ in
         '';
       };
 
-      package = mkOption {
-        type = types.package;
+      package = mkPackageOption pkgs "slurm" {
+        example = "slurm-full";
+      } // {
         default = pkgs.slurm.override { enableX11 = ! cfg.enableSrunX11; };
-        defaultText = literalExpression "pkgs.slurm";
-        example = literalExpression "pkgs.slurm-full";
-        description = lib.mdDoc ''
-          The package to use for slurm binaries.
-        '';
       };
 
       controlMachine = mkOption {
diff --git a/nixpkgs/nixos/modules/services/continuous-integration/buildbot/master.nix b/nixpkgs/nixos/modules/services/continuous-integration/buildbot/master.nix
index 9a89745055f0..56abeda3a5cd 100644
--- a/nixpkgs/nixos/modules/services/continuous-integration/buildbot/master.nix
+++ b/nixpkgs/nixos/modules/services/continuous-integration/buildbot/master.nix
@@ -229,12 +229,8 @@ in {
         description = lib.mdDoc "Specifies port number on which the buildbot HTTP interface listens.";
       };
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.buildbot-full;
-        defaultText = literalExpression "pkgs.buildbot-full";
-        description = lib.mdDoc "Package to use for buildbot.";
-        example = literalExpression "pkgs.buildbot";
+      package = mkPackageOption pkgs "buildbot-full" {
+        example = "buildbot";
       };
 
       packages = mkOption {
diff --git a/nixpkgs/nixos/modules/services/continuous-integration/buildbot/worker.nix b/nixpkgs/nixos/modules/services/continuous-integration/buildbot/worker.nix
index 7e78b8935f81..b906788209b1 100644
--- a/nixpkgs/nixos/modules/services/continuous-integration/buildbot/worker.nix
+++ b/nixpkgs/nixos/modules/services/continuous-integration/buildbot/worker.nix
@@ -128,12 +128,8 @@ in {
         '';
       };
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.buildbot-worker;
-        defaultText = literalExpression "pkgs.python3Packages.buildbot-worker";
-        description = lib.mdDoc "Package to use for buildbot worker.";
-        example = literalExpression "pkgs.python2Packages.buildbot-worker";
+      package = mkPackageOption pkgs "python3Packages.buildbot-worker" {
+        example = "python2Packages.buildbot-worker";
       };
 
       packages = mkOption {
diff --git a/nixpkgs/nixos/modules/services/continuous-integration/gitea-actions-runner.nix b/nixpkgs/nixos/modules/services/continuous-integration/gitea-actions-runner.nix
index d8d25898e294..3f2be9464849 100644
--- a/nixpkgs/nixos/modules/services/continuous-integration/gitea-actions-runner.nix
+++ b/nixpkgs/nixos/modules/services/continuous-integration/gitea-actions-runner.nix
@@ -19,7 +19,7 @@ let
     mapAttrs'
     mkEnableOption
     mkOption
-    mkPackageOptionMD
+    mkPackageOption
     mkIf
     nameValuePair
     types
@@ -56,7 +56,7 @@ in
   ];
 
   options.services.gitea-actions-runner = with types; {
-    package = mkPackageOptionMD pkgs "gitea-actions-runner" { };
+    package = mkPackageOption pkgs "gitea-actions-runner" { };
 
     instances = mkOption {
       default = {};
diff --git a/nixpkgs/nixos/modules/services/continuous-integration/github-runner/options.nix b/nixpkgs/nixos/modules/services/continuous-integration/github-runner/options.nix
index f2887c7711b3..2335826e8b66 100644
--- a/nixpkgs/nixos/modules/services/continuous-integration/github-runner/options.nix
+++ b/nixpkgs/nixos/modules/services/continuous-integration/github-runner/options.nix
@@ -161,14 +161,7 @@ with lib;
     default = {};
   };
 
-  package = mkOption {
-    type = types.package;
-    description = lib.mdDoc ''
-      Which github-runner derivation to use.
-    '';
-    default = pkgs.github-runner;
-    defaultText = literalExpression "pkgs.github-runner";
-  };
+  package = mkPackageOption pkgs "github-runner" { };
 
   ephemeral = mkOption {
     type = types.bool;
diff --git a/nixpkgs/nixos/modules/services/continuous-integration/gitlab-runner.nix b/nixpkgs/nixos/modules/services/continuous-integration/gitlab-runner.nix
index 10a2fe8a44dd..05b2449936bc 100644
--- a/nixpkgs/nixos/modules/services/continuous-integration/gitlab-runner.nix
+++ b/nixpkgs/nixos/modules/services/continuous-integration/gitlab-runner.nix
@@ -195,12 +195,8 @@ in {
         Time to wait until a graceful shutdown is turned into a forceful one.
       '';
     };
-    package = mkOption {
-      type = types.package;
-      default = pkgs.gitlab-runner;
-      defaultText = literalExpression "pkgs.gitlab-runner";
-      example = literalExpression "pkgs.gitlab-runner_1_11";
-      description = lib.mdDoc "Gitlab Runner package to use.";
+    package = mkPackageOption pkgs "gitlab-runner" {
+      example = "gitlab-runner_1_11";
     };
     extraPackages = mkOption {
       type = types.listOf types.package;
diff --git a/nixpkgs/nixos/modules/services/continuous-integration/hercules-ci-agent/common.nix b/nixpkgs/nixos/modules/services/continuous-integration/hercules-ci-agent/common.nix
index ea9b5ffbf43c..7d33989044de 100644
--- a/nixpkgs/nixos/modules/services/continuous-integration/hercules-ci-agent/common.nix
+++ b/nixpkgs/nixos/modules/services/continuous-integration/hercules-ci-agent/common.nix
@@ -16,7 +16,7 @@ let
     mkRemovedOptionModule
     mkRenamedOptionModule
     types
-
+    mkPackageOption
     ;
 
   cfg = config.services.hercules-ci-agent;
@@ -45,14 +45,7 @@ in
         Support is available at [help@hercules-ci.com](mailto:help@hercules-ci.com).
       '';
     };
-    package = mkOption {
-      description = lib.mdDoc ''
-        Package containing the bin/hercules-ci-agent executable.
-      '';
-      type = types.package;
-      default = pkgs.hercules-ci-agent;
-      defaultText = literalExpression "pkgs.hercules-ci-agent";
-    };
+    package = mkPackageOption pkgs "hercules-ci-agent" { };
     settings = mkOption {
       description = lib.mdDoc ''
         These settings are written to the `agent.toml` file.
diff --git a/nixpkgs/nixos/modules/services/continuous-integration/hydra/default.nix b/nixpkgs/nixos/modules/services/continuous-integration/hydra/default.nix
index 83078706fcae..46b03bba37be 100644
--- a/nixpkgs/nixos/modules/services/continuous-integration/hydra/default.nix
+++ b/nixpkgs/nixos/modules/services/continuous-integration/hydra/default.nix
@@ -97,12 +97,7 @@ in
         '';
       };
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.hydra_unstable;
-        defaultText = literalExpression "pkgs.hydra_unstable";
-        description = lib.mdDoc "The Hydra package.";
-      };
+      package = mkPackageOption pkgs "hydra_unstable" { };
 
       hydraURL = mkOption {
         type = types.str;
diff --git a/nixpkgs/nixos/modules/services/continuous-integration/jenkins/default.nix b/nixpkgs/nixos/modules/services/continuous-integration/jenkins/default.nix
index e4d54b0cb0f4..e96743784e04 100644
--- a/nixpkgs/nixos/modules/services/continuous-integration/jenkins/default.nix
+++ b/nixpkgs/nixos/modules/services/continuous-integration/jenkins/default.nix
@@ -79,12 +79,7 @@ in {
         '';
       };
 
-      package = mkOption {
-        default = pkgs.jenkins;
-        defaultText = literalExpression "pkgs.jenkins";
-        type = types.package;
-        description = lib.mdDoc "Jenkins package to use.";
-      };
+      package = mkPackageOption pkgs "jenkins" { };
 
       packages = mkOption {
         default = [ pkgs.stdenv pkgs.git pkgs.jdk17 config.programs.ssh.package pkgs.nix ];
diff --git a/nixpkgs/nixos/modules/services/continuous-integration/jenkins/slave.nix b/nixpkgs/nixos/modules/services/continuous-integration/jenkins/slave.nix
index 9b86917ab380..82d34a058c57 100644
--- a/nixpkgs/nixos/modules/services/continuous-integration/jenkins/slave.nix
+++ b/nixpkgs/nixos/modules/services/continuous-integration/jenkins/slave.nix
@@ -47,14 +47,7 @@ in {
         '';
       };
 
-      javaPackage = mkOption {
-        default = pkgs.jdk;
-        defaultText = literalExpression "pkgs.jdk";
-        description = lib.mdDoc ''
-          Java package to install.
-        '';
-        type = types.package;
-      };
+      javaPackage = mkPackageOption pkgs "jdk" { };
     };
   };
 
diff --git a/nixpkgs/nixos/modules/services/continuous-integration/woodpecker/agents.nix b/nixpkgs/nixos/modules/services/continuous-integration/woodpecker/agents.nix
index 3b883c72ff07..ef7bf3fd2a6e 100644
--- a/nixpkgs/nixos/modules/services/continuous-integration/woodpecker/agents.nix
+++ b/nixpkgs/nixos/modules/services/continuous-integration/woodpecker/agents.nix
@@ -11,7 +11,7 @@ let
     options = {
       enable = lib.mkEnableOption (lib.mdDoc "this Woodpecker-Agent. Agents execute tasks generated by a Server, every install will need one server and at least one agent");
 
-      package = lib.mkPackageOptionMD pkgs "woodpecker-agent" { };
+      package = lib.mkPackageOption pkgs "woodpecker-agent" { };
 
       environment = lib.mkOption {
         default = { };
diff --git a/nixpkgs/nixos/modules/services/continuous-integration/woodpecker/server.nix b/nixpkgs/nixos/modules/services/continuous-integration/woodpecker/server.nix
index 38b42f7288c0..4a0f15756c30 100644
--- a/nixpkgs/nixos/modules/services/continuous-integration/woodpecker/server.nix
+++ b/nixpkgs/nixos/modules/services/continuous-integration/woodpecker/server.nix
@@ -14,7 +14,7 @@ in
   options = {
     services.woodpecker-server = {
       enable = lib.mkEnableOption (lib.mdDoc "the Woodpecker-Server, a CI/CD application for automatic builds, deployments and tests");
-      package = lib.mkPackageOptionMD pkgs "woodpecker-server" { };
+      package = lib.mkPackageOption pkgs "woodpecker-server" { };
       environment = lib.mkOption {
         default = { };
         type = lib.types.attrsOf lib.types.str;
diff --git a/nixpkgs/nixos/modules/services/databases/aerospike.nix b/nixpkgs/nixos/modules/services/databases/aerospike.nix
index 21df4cd0577b..373c8f4bffb0 100644
--- a/nixpkgs/nixos/modules/services/databases/aerospike.nix
+++ b/nixpkgs/nixos/modules/services/databases/aerospike.nix
@@ -41,12 +41,7 @@ in
     services.aerospike = {
       enable = mkEnableOption (lib.mdDoc "Aerospike server");
 
-      package = mkOption {
-        default = pkgs.aerospike;
-        defaultText = literalExpression "pkgs.aerospike";
-        type = types.package;
-        description = lib.mdDoc "Which Aerospike derivation to use";
-      };
+      package = mkPackageOption pkgs "aerospike" { };
 
       workDir = mkOption {
         type = types.str;
diff --git a/nixpkgs/nixos/modules/services/databases/cassandra.nix b/nixpkgs/nixos/modules/services/databases/cassandra.nix
index cd816ffaf0dd..adf7213dd13f 100644
--- a/nixpkgs/nixos/modules/services/databases/cassandra.nix
+++ b/nixpkgs/nixos/modules/services/databases/cassandra.nix
@@ -11,6 +11,7 @@ let
     recursiveUpdate
     mdDoc
     mkEnableOption
+    mkPackageOption
     mkIf
     mkOption
     types
@@ -155,14 +156,8 @@ in
       '';
     };
 
-    package = mkOption {
-      type = types.package;
-      default = pkgs.cassandra;
-      defaultText = literalExpression "pkgs.cassandra";
-      example = literalExpression "pkgs.cassandra_3_11";
-      description = mdDoc ''
-        The Apache Cassandra package to use.
-      '';
+    package = mkPackageOption pkgs "cassandra" {
+      example = "cassandra_3_11";
     };
 
     jvmOpts = mkOption {
diff --git a/nixpkgs/nixos/modules/services/databases/clickhouse.nix b/nixpkgs/nixos/modules/services/databases/clickhouse.nix
index dca352ef72fe..288046677721 100644
--- a/nixpkgs/nixos/modules/services/databases/clickhouse.nix
+++ b/nixpkgs/nixos/modules/services/databases/clickhouse.nix
@@ -13,14 +13,7 @@ with lib;
 
       enable = mkEnableOption (lib.mdDoc "ClickHouse database server");
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.clickhouse;
-        defaultText = lib.literalExpression "pkgs.clickhouse";
-        description = lib.mdDoc ''
-          ClickHouse package to use.
-        '';
-      };
+      package = mkPackageOption pkgs "clickhouse" { };
 
     };
 
diff --git a/nixpkgs/nixos/modules/services/databases/cockroachdb.nix b/nixpkgs/nixos/modules/services/databases/cockroachdb.nix
index ff77d30588fe..789f086158db 100644
--- a/nixpkgs/nixos/modules/services/databases/cockroachdb.nix
+++ b/nixpkgs/nixos/modules/services/databases/cockroachdb.nix
@@ -145,13 +145,8 @@ in
         '';
       };
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.cockroachdb;
-        defaultText = literalExpression "pkgs.cockroachdb";
-        description = lib.mdDoc ''
-          The CockroachDB derivation to use for running the service.
-
+      package = mkPackageOption pkgs "cockroachdb" {
+        extraDescription = ''
           This would primarily be useful to enable Enterprise Edition features
           in your own custom CockroachDB build (Nixpkgs CockroachDB binaries
           only contain open source features and open source code).
diff --git a/nixpkgs/nixos/modules/services/databases/couchdb.nix b/nixpkgs/nixos/modules/services/databases/couchdb.nix
index bfecfbb3664f..72212c390413 100644
--- a/nixpkgs/nixos/modules/services/databases/couchdb.nix
+++ b/nixpkgs/nixos/modules/services/databases/couchdb.nix
@@ -36,14 +36,7 @@ in {
 
       enable = mkEnableOption (lib.mdDoc "CouchDB Server");
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.couchdb3;
-        defaultText = literalExpression "pkgs.couchdb3";
-        description = lib.mdDoc ''
-          CouchDB package to use.
-        '';
-      };
+      package = mkPackageOption pkgs "couchdb3" { };
 
       adminUser = mkOption {
         type = types.str;
diff --git a/nixpkgs/nixos/modules/services/databases/dgraph.nix b/nixpkgs/nixos/modules/services/databases/dgraph.nix
index 7f005a9971a6..479754a6447d 100644
--- a/nixpkgs/nixos/modules/services/databases/dgraph.nix
+++ b/nixpkgs/nixos/modules/services/databases/dgraph.nix
@@ -55,7 +55,7 @@ in
     services.dgraph = {
       enable = mkEnableOption (lib.mdDoc "Dgraph native GraphQL database with a graph backend");
 
-      package = lib.mkPackageOptionMD pkgs "dgraph" { };
+      package = lib.mkPackageOption pkgs "dgraph" { };
 
       settings = mkOption {
         type = settingsFormat.type;
diff --git a/nixpkgs/nixos/modules/services/databases/firebird.nix b/nixpkgs/nixos/modules/services/databases/firebird.nix
index 3927c81d953d..36c12eaaf5f1 100644
--- a/nixpkgs/nixos/modules/services/databases/firebird.nix
+++ b/nixpkgs/nixos/modules/services/databases/firebird.nix
@@ -42,13 +42,9 @@ in
 
       enable = mkEnableOption (lib.mdDoc "the Firebird super server");
 
-      package = mkOption {
-        default = pkgs.firebird;
-        defaultText = literalExpression "pkgs.firebird";
-        type = types.package;
-        example = literalExpression "pkgs.firebird_3";
-        description = lib.mdDoc ''
-          Which Firebird package to be installed: `pkgs.firebird_3`
+      package = mkPackageOption pkgs "firebird" {
+        example = "firebird_3";
+        extraDescription = ''
           For SuperServer use override: `pkgs.firebird_3.override { superServer = true; };`
         '';
       };
diff --git a/nixpkgs/nixos/modules/services/databases/hbase-standalone.nix b/nixpkgs/nixos/modules/services/databases/hbase-standalone.nix
index 1ee73ec8d1ff..08ae7625d50a 100644
--- a/nixpkgs/nixos/modules/services/databases/hbase-standalone.nix
+++ b/nixpkgs/nixos/modules/services/databases/hbase-standalone.nix
@@ -46,15 +46,7 @@ in {
         Do not use this configuration for production nor for evaluating HBase performance.
       '');
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.hbase;
-        defaultText = literalExpression "pkgs.hbase";
-        description = lib.mdDoc ''
-          HBase package to use.
-        '';
-      };
-
+      package = mkPackageOption pkgs "hbase" { };
 
       user = mkOption {
         type = types.str;
diff --git a/nixpkgs/nixos/modules/services/databases/influxdb.nix b/nixpkgs/nixos/modules/services/databases/influxdb.nix
index b3361d2014ca..34b4139e7c58 100644
--- a/nixpkgs/nixos/modules/services/databases/influxdb.nix
+++ b/nixpkgs/nixos/modules/services/databases/influxdb.nix
@@ -116,12 +116,7 @@ in
         type = types.bool;
       };
 
-      package = mkOption {
-        default = pkgs.influxdb;
-        defaultText = literalExpression "pkgs.influxdb";
-        description = lib.mdDoc "Which influxdb derivation to use";
-        type = types.package;
-      };
+      package = mkPackageOption pkgs "influxdb" { };
 
       user = mkOption {
         default = "influxdb";
diff --git a/nixpkgs/nixos/modules/services/databases/influxdb2.nix b/nixpkgs/nixos/modules/services/databases/influxdb2.nix
index 3740cd01b5dc..2a67d87d4bbb 100644
--- a/nixpkgs/nixos/modules/services/databases/influxdb2.nix
+++ b/nixpkgs/nixos/modules/services/databases/influxdb2.nix
@@ -19,6 +19,7 @@ let
     mapAttrsToList
     mdDoc
     mkEnableOption
+    mkPackageOption
     mkIf
     mkOption
     nameValuePair
@@ -278,12 +279,7 @@ in
     services.influxdb2 = {
       enable = mkEnableOption (mdDoc "the influxdb2 server");
 
-      package = mkOption {
-        default = pkgs.influxdb2-server;
-        defaultText = literalExpression "pkgs.influxdb2";
-        description = mdDoc "influxdb2 derivation to use.";
-        type = types.package;
-      };
+      package = mkPackageOption pkgs "influxdb2" { };
 
       settings = mkOption {
         default = { };
diff --git a/nixpkgs/nixos/modules/services/databases/lldap.nix b/nixpkgs/nixos/modules/services/databases/lldap.nix
index 960792d0805f..d1574c98fe67 100644
--- a/nixpkgs/nixos/modules/services/databases/lldap.nix
+++ b/nixpkgs/nixos/modules/services/databases/lldap.nix
@@ -8,7 +8,7 @@ in
   options.services.lldap = with lib; {
     enable = mkEnableOption (mdDoc "lldap");
 
-    package = mkPackageOptionMD pkgs "lldap" { };
+    package = mkPackageOption pkgs "lldap" { };
 
     environment = mkOption {
       type = with types; attrsOf str;
diff --git a/nixpkgs/nixos/modules/services/databases/monetdb.nix b/nixpkgs/nixos/modules/services/databases/monetdb.nix
index 5573b530a913..1dddeda0959c 100644
--- a/nixpkgs/nixos/modules/services/databases/monetdb.nix
+++ b/nixpkgs/nixos/modules/services/databases/monetdb.nix
@@ -14,12 +14,7 @@ in {
 
       enable = mkEnableOption (lib.mdDoc "the MonetDB database server");
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.monetdb;
-        defaultText = literalExpression "pkgs.monetdb";
-        description = lib.mdDoc "MonetDB package to use.";
-      };
+      package = mkPackageOption pkgs "monetdb" { };
 
       user = mkOption {
         type = types.str;
diff --git a/nixpkgs/nixos/modules/services/databases/mongodb.nix b/nixpkgs/nixos/modules/services/databases/mongodb.nix
index 8f3be1492e9e..f10364bc76c1 100644
--- a/nixpkgs/nixos/modules/services/databases/mongodb.nix
+++ b/nixpkgs/nixos/modules/services/databases/mongodb.nix
@@ -31,14 +31,7 @@ in
 
       enable = mkEnableOption (lib.mdDoc "the MongoDB server");
 
-      package = mkOption {
-        default = pkgs.mongodb;
-        defaultText = literalExpression "pkgs.mongodb";
-        type = types.package;
-        description = lib.mdDoc ''
-          Which MongoDB derivation to use.
-        '';
-      };
+      package = mkPackageOption pkgs "mongodb" { };
 
       user = mkOption {
         type = types.str;
diff --git a/nixpkgs/nixos/modules/services/databases/neo4j.nix b/nixpkgs/nixos/modules/services/databases/neo4j.nix
index 090502424028..56b916ee3758 100644
--- a/nixpkgs/nixos/modules/services/databases/neo4j.nix
+++ b/nixpkgs/nixos/modules/services/databases/neo4j.nix
@@ -174,14 +174,7 @@ in {
       '';
     };
 
-    package = mkOption {
-      type = types.package;
-      default = pkgs.neo4j;
-      defaultText = literalExpression "pkgs.neo4j";
-      description = lib.mdDoc ''
-        Neo4j package to use.
-      '';
-    };
+    package = mkPackageOption pkgs "neo4j" { };
 
     readOnly = mkOption {
       type = types.bool;
diff --git a/nixpkgs/nixos/modules/services/databases/openldap.nix b/nixpkgs/nixos/modules/services/databases/openldap.nix
index cba3442023cb..a7a0909f55e1 100644
--- a/nixpkgs/nixos/modules/services/databases/openldap.nix
+++ b/nixpkgs/nixos/modules/services/databases/openldap.nix
@@ -91,13 +91,8 @@ in {
         description = lib.mdDoc "Whether to enable the ldap server.";
       };
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.openldap;
-        defaultText = literalExpression "pkgs.openldap";
-        description = lib.mdDoc ''
-          OpenLDAP package to use.
-
+      package = mkPackageOption pkgs "openldap" {
+        extraDescription = ''
           This can be used to, for example, set an OpenLDAP package
           with custom overrides to enable modules or other
           functionality.
diff --git a/nixpkgs/nixos/modules/services/databases/opentsdb.nix b/nixpkgs/nixos/modules/services/databases/opentsdb.nix
index 288b716fce03..25f413db809f 100644
--- a/nixpkgs/nixos/modules/services/databases/opentsdb.nix
+++ b/nixpkgs/nixos/modules/services/databases/opentsdb.nix
@@ -17,14 +17,7 @@ in {
 
       enable = mkEnableOption (lib.mdDoc "OpenTSDB");
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.opentsdb;
-        defaultText = literalExpression "pkgs.opentsdb";
-        description = lib.mdDoc ''
-          OpenTSDB package to use.
-        '';
-      };
+      package = mkPackageOption pkgs "opentsdb" { };
 
       user = mkOption {
         type = types.str;
diff --git a/nixpkgs/nixos/modules/services/databases/pgbouncer.nix b/nixpkgs/nixos/modules/services/databases/pgbouncer.nix
index 1aec03c114d1..65b287e84442 100644
--- a/nixpkgs/nixos/modules/services/databases/pgbouncer.nix
+++ b/nixpkgs/nixos/modules/services/databases/pgbouncer.nix
@@ -82,14 +82,7 @@ in {
 
     enable = mkEnableOption (lib.mdDoc "PostgreSQL connection pooler");
 
-    package = mkOption {
-      type = types.package;
-      default = pkgs.pgbouncer;
-      defaultText = literalExpression "pkgs.pgbouncer";
-      description = lib.mdDoc ''
-        The pgbouncer package to use.
-      '';
-    };
+    package = mkPackageOption pkgs "pgbouncer" { };
 
     openFirewall = mkOption {
       type = types.bool;
diff --git a/nixpkgs/nixos/modules/services/databases/pgmanage.nix b/nixpkgs/nixos/modules/services/databases/pgmanage.nix
index a0933a5ffc45..4b963aee4640 100644
--- a/nixpkgs/nixos/modules/services/databases/pgmanage.nix
+++ b/nixpkgs/nixos/modules/services/databases/pgmanage.nix
@@ -46,14 +46,7 @@ in {
   options.services.pgmanage = {
     enable = mkEnableOption (lib.mdDoc "PostgreSQL Administration for the web");
 
-    package = mkOption {
-      type = types.package;
-      default = pkgs.pgmanage;
-      defaultText = literalExpression "pkgs.pgmanage";
-      description = lib.mdDoc ''
-        The pgmanage package to use.
-      '';
-    };
+    package = mkPackageOption pkgs "pgmanage" { };
 
     connections = mkOption {
       type = types.attrsOf types.str;
diff --git a/nixpkgs/nixos/modules/services/databases/postgresql.nix b/nixpkgs/nixos/modules/services/databases/postgresql.nix
index a9067d5974a9..690f2d85a4c9 100644
--- a/nixpkgs/nixos/modules/services/databases/postgresql.nix
+++ b/nixpkgs/nixos/modules/services/databases/postgresql.nix
@@ -53,12 +53,8 @@ in
 
       enableJIT = mkEnableOption (lib.mdDoc "JIT support");
 
-      package = mkOption {
-        type = types.package;
-        example = literalExpression "pkgs.postgresql_15";
-        description = lib.mdDoc ''
-          PostgreSQL package to use.
-        '';
+      package = mkPackageOption pkgs "postgresql" {
+        example = "postgresql_15";
       };
 
       port = mkOption {
@@ -467,9 +463,9 @@ in
     }) cfg.ensureUsers;
     # `ensurePermissions` is now deprecated, let's avoid it.
     warnings = lib.optional (any ({ ensurePermissions, ... }: ensurePermissions != {}) cfg.ensureUsers) "
-      `services.postgresql.*.ensurePermissions` is used in your expressions,
+      `services.postgresql.ensureUsers.*.ensurePermissions` is used in your expressions,
       this option is known to be broken with newer PostgreSQL versions,
-      consider migrating to `services.postgresql.*.ensureDBOwnership` or
+      consider migrating to `services.postgresql.ensureUsers.*.ensureDBOwnership` or
       consult the release notes or manual for more migration guidelines.
 
       This option will be removed in NixOS 24.05 unless it sees significant
diff --git a/nixpkgs/nixos/modules/services/databases/redis.nix b/nixpkgs/nixos/modules/services/databases/redis.nix
index 315a0282cd73..2e644895a260 100644
--- a/nixpkgs/nixos/modules/services/databases/redis.nix
+++ b/nixpkgs/nixos/modules/services/databases/redis.nix
@@ -54,12 +54,7 @@ in {
   options = {
 
     services.redis = {
-      package = mkOption {
-        type = types.package;
-        default = pkgs.redis;
-        defaultText = literalExpression "pkgs.redis";
-        description = lib.mdDoc "Which Redis derivation to use.";
-      };
+      package = mkPackageOption pkgs "redis" { };
 
       vmOverCommit = mkEnableOption (lib.mdDoc ''
         setting of vm.overcommit_memory to 1
@@ -393,9 +388,7 @@ in {
         ProtectKernelModules = true;
         ProtectKernelTunables = true;
         ProtectControlGroups = true;
-        RestrictAddressFamilies =
-          optionals (conf.port != 0) ["AF_INET" "AF_INET6"] ++
-          optional (conf.unixSocket != null) "AF_UNIX";
+        RestrictAddressFamilies = [ "AF_INET" "AF_INET6" "AF_UNIX" ];
         RestrictNamespaces = true;
         LockPersonality = true;
         MemoryDenyWriteExecute = true;
diff --git a/nixpkgs/nixos/modules/services/databases/surrealdb.nix b/nixpkgs/nixos/modules/services/databases/surrealdb.nix
index e1a1faed1f8f..55216d022d1c 100644
--- a/nixpkgs/nixos/modules/services/databases/surrealdb.nix
+++ b/nixpkgs/nixos/modules/services/databases/surrealdb.nix
@@ -10,14 +10,7 @@ in {
     services.surrealdb = {
       enable = mkEnableOption (lib.mdDoc "SurrealDB, a scalable, distributed, collaborative, document-graph database, for the realtime web");
 
-      package = mkOption {
-        default = pkgs.surrealdb;
-        defaultText = literalExpression "pkgs.surrealdb";
-        type = types.package;
-        description = lib.mdDoc ''
-          Which surrealdb derivation to use.
-        '';
-      };
+      package = mkPackageOption pkgs "surrealdb" { };
 
       dbPath = mkOption {
         type = types.str;
diff --git a/nixpkgs/nixos/modules/services/databases/victoriametrics.nix b/nixpkgs/nixos/modules/services/databases/victoriametrics.nix
index 638066a42dbd..0ad2028c95b0 100644
--- a/nixpkgs/nixos/modules/services/databases/victoriametrics.nix
+++ b/nixpkgs/nixos/modules/services/databases/victoriametrics.nix
@@ -3,14 +3,7 @@ let cfg = config.services.victoriametrics; in
 {
   options.services.victoriametrics = with lib; {
     enable = mkEnableOption (lib.mdDoc "victoriametrics");
-    package = mkOption {
-      type = types.package;
-      default = pkgs.victoriametrics;
-      defaultText = literalExpression "pkgs.victoriametrics";
-      description = lib.mdDoc ''
-        The VictoriaMetrics distribution to use.
-      '';
-    };
+    package = mkPackageOption pkgs "victoriametrics" { };
     listenAddress = mkOption {
       default = ":8428";
       type = types.str;
diff --git a/nixpkgs/nixos/modules/services/desktops/deepin/app-services.nix b/nixpkgs/nixos/modules/services/desktops/deepin/app-services.nix
index 4592bc7bb340..a6c33af03e95 100644
--- a/nixpkgs/nixos/modules/services/desktops/deepin/app-services.nix
+++ b/nixpkgs/nixos/modules/services/desktops/deepin/app-services.nix
@@ -25,8 +25,17 @@ with lib;
 
   config = mkIf config.services.deepin.app-services.enable {
 
-    environment.systemPackages = [ pkgs.deepin.dde-app-services ];
+    users.groups.dde-dconfig-daemon = { };
+    users.users.dde-dconfig-daemon = {
+      description = "Dconfig daemon user";
+      home = "/var/lib/dde-dconfig-daemon";
+      createHome = true;
+      group = "dde-dconfig-daemon";
+      isSystemUser = true;
+    };
 
+    environment.systemPackages = [ pkgs.deepin.dde-app-services ];
+    systemd.packages = [ pkgs.deepin.dde-app-services ];
     services.dbus.packages = [ pkgs.deepin.dde-app-services ];
 
     environment.pathsToLink = [ "/share/dsg" ];
diff --git a/nixpkgs/nixos/modules/services/desktops/flatpak.md b/nixpkgs/nixos/modules/services/desktops/flatpak.md
index 65b1554d79b4..af71d85b5a15 100644
--- a/nixpkgs/nixos/modules/services/desktops/flatpak.md
+++ b/nixpkgs/nixos/modules/services/desktops/flatpak.md
@@ -18,6 +18,7 @@ in other cases, you will need to add something like the following to your
 {file}`configuration.nix`:
 ```
   xdg.portal.extraPortals = [ pkgs.xdg-desktop-portal-gtk ];
+  xdg.portal.config.common.default = "gtk";
 ```
 
 Then, you will need to add a repository, for example,
diff --git a/nixpkgs/nixos/modules/services/desktops/gnome/gnome-initial-setup.nix b/nixpkgs/nixos/modules/services/desktops/gnome/gnome-initial-setup.nix
index f24e6f1eb155..6eaf861e4974 100644
--- a/nixpkgs/nixos/modules/services/desktops/gnome/gnome-initial-setup.nix
+++ b/nixpkgs/nixos/modules/services/desktops/gnome/gnome-initial-setup.nix
@@ -93,6 +93,9 @@ in
       "gnome-initial-setup.service"
     ];
 
+    programs.dconf.profiles.gnome-initial-setup.databases = [
+      "${pkgs.gnome.gnome-initial-setup}/share/gnome-initial-setup/initial-setup-dconf-defaults"
+    ];
   };
 
 }
diff --git a/nixpkgs/nixos/modules/services/desktops/gvfs.nix b/nixpkgs/nixos/modules/services/desktops/gvfs.nix
index 7e15b433fcc2..a4770d703f54 100644
--- a/nixpkgs/nixos/modules/services/desktops/gvfs.nix
+++ b/nixpkgs/nixos/modules/services/desktops/gvfs.nix
@@ -32,12 +32,7 @@ in
       enable = mkEnableOption (lib.mdDoc "GVfs, a userspace virtual filesystem");
 
       # gvfs can be built with multiple configurations
-      package = mkOption {
-        type = types.package;
-        default = pkgs.gnome.gvfs;
-        defaultText = literalExpression "pkgs.gnome.gvfs";
-        description = lib.mdDoc "Which GVfs package to use.";
-      };
+      package = mkPackageOption pkgs [ "gnome" "gvfs" ] { };
 
     };
 
diff --git a/nixpkgs/nixos/modules/services/desktops/pipewire/pipewire.nix b/nixpkgs/nixos/modules/services/desktops/pipewire/pipewire.nix
index 07ca2727cf48..04ac415c177c 100644
--- a/nixpkgs/nixos/modules/services/desktops/pipewire/pipewire.nix
+++ b/nixpkgs/nixos/modules/services/desktops/pipewire/pipewire.nix
@@ -25,14 +25,7 @@ in {
     services.pipewire = {
       enable = mkEnableOption (lib.mdDoc "pipewire service");
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.pipewire;
-        defaultText = literalExpression "pkgs.pipewire";
-        description = lib.mdDoc ''
-          The pipewire derivation to use.
-        '';
-      };
+      package = mkPackageOption pkgs "pipewire" { };
 
       socketActivation = mkOption {
         default = true;
diff --git a/nixpkgs/nixos/modules/services/desktops/seatd.nix b/nixpkgs/nixos/modules/services/desktops/seatd.nix
new file mode 100644
index 000000000000..51977dfd2153
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/desktops/seatd.nix
@@ -0,0 +1,51 @@
+{ config, lib, pkgs, ... }:
+
+let
+  cfg = config.services.seatd;
+  inherit (lib) mkEnableOption mkOption mdDoc types;
+in
+{
+  meta.maintainers = with lib.maintainers; [ sinanmohd ];
+
+  options.services.seatd = {
+    enable = mkEnableOption (mdDoc "seatd");
+
+    user = mkOption {
+      type = types.str;
+      default = "root";
+      description = mdDoc "User to own the seatd socket";
+    };
+    group = mkOption {
+      type = types.str;
+      default = "seat";
+      description = mdDoc "Group to own the seatd socket";
+    };
+    logLevel = mkOption {
+      type = types.enum [ "debug" "info" "error" "silent" ];
+      default = "info";
+      description = mdDoc "Logging verbosity";
+    };
+  };
+
+  config = lib.mkIf cfg.enable {
+    environment.systemPackages = with pkgs; [ seatd sdnotify-wrapper ];
+    users.groups.seat = lib.mkIf (cfg.group == "seat") {};
+
+    systemd.services.seatd = {
+      description = "Seat management daemon";
+      documentation = [ "man:seatd(1)" ];
+
+      wantedBy = [ "multi-user.target" ];
+      restartIfChanged = false;
+
+      serviceConfig = {
+        Type = "notify";
+        NotifyAccess = "all";
+        SyslogIdentifier = "seatd";
+        ExecStart = "${pkgs.sdnotify-wrapper}/bin/sdnotify-wrapper ${pkgs.seatd.bin}/bin/seatd -n 1 -u ${cfg.user} -g ${cfg.group} -l ${cfg.logLevel}";
+        RestartSec = 1;
+        Restart = "always";
+      };
+    };
+  };
+}
diff --git a/nixpkgs/nixos/modules/services/development/athens.md b/nixpkgs/nixos/modules/services/development/athens.md
new file mode 100644
index 000000000000..77663db509d5
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/development/athens.md
@@ -0,0 +1,52 @@
+# Athens {#module-athens}
+
+*Source:* {file}`modules/services/development/athens.nix`
+
+*Upstream documentation:* <https://docs.gomods.io/>
+
+[Athens](https://github.com/gomods/athens)
+is a Go module datastore and proxy
+
+The main goal of Athens is providing a Go proxy (`$GOPROXY`) in regions without access to `https://proxy.golang.org` or to
+improve the speed of Go module downloads for CI/CD systems.
+
+## Configuring {#module-services-development-athens-configuring}
+
+A complete list of options for the Athens module may be found
+[here](#opt-services.athens.enable).
+
+## Basic usage for a caching proxy configuration {#opt-services-development-athens-caching-proxy}
+
+A very basic configuration for Athens that acts as a caching and forwarding HTTP proxy is:
+```
+{
+    services.athens = {
+      enable = true;
+    };
+}
+```
+
+If you want to prevent Athens from writing to disk, you can instead configure it to cache modules only in memory:
+
+```
+{
+    services.athens = {
+      enable = true;
+      storageType = "memory";
+    };
+}
+```
+
+To use the local proxy in Go builds, you can set the proxy as environment variable:
+
+```
+{
+  environment.variables = {
+    GOPROXY = "http://localhost:3000"
+  };
+}
+```
+
+It is currently not possible to use the local proxy for builds done by the Nix daemon. This might be enabled
+by experimental features, specifically [`configurable-impure-env`](https://nixos.org/manual/nix/unstable/contributing/experimental-features#xp-feature-configurable-impure-env),
+in upcoming Nix versions.
diff --git a/nixpkgs/nixos/modules/services/development/athens.nix b/nixpkgs/nixos/modules/services/development/athens.nix
new file mode 100644
index 000000000000..34f8964a3bd5
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/development/athens.nix
@@ -0,0 +1,936 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.services.athens;
+
+  athensConfig = flip recursiveUpdate cfg.extraConfig (
+    {
+      GoBinary = "${cfg.goBinary}/bin/go";
+      GoEnv = cfg.goEnv;
+      GoBinaryEnvVars = lib.mapAttrsToList (k: v: "${k}=${v}") cfg.goBinaryEnvVars;
+      GoGetWorkers = cfg.goGetWorkers;
+      GoGetDir = cfg.goGetDir;
+      ProtocolWorkers = cfg.protocolWorkers;
+      LogLevel = cfg.logLevel;
+      CloudRuntime = cfg.cloudRuntime;
+      EnablePprof = cfg.enablePprof;
+      PprofPort = ":${toString cfg.pprofPort}";
+      FilterFile = cfg.filterFile;
+      RobotsFile = cfg.robotsFile;
+      Timeout = cfg.timeout;
+      StorageType = cfg.storageType;
+      TLSCertFile = cfg.tlsCertFile;
+      TLSKeyFile = cfg.tlsKeyFile;
+      Port = ":${toString cfg.port}";
+      UnixSocket = cfg.unixSocket;
+      GlobalEndpoint = cfg.globalEndpoint;
+      BasicAuthUser = cfg.basicAuthUser;
+      BasicAuthPass = cfg.basicAuthPass;
+      ForceSSL = cfg.forceSSL;
+      ValidatorHook = cfg.validatorHook;
+      PathPrefix = cfg.pathPrefix;
+      NETRCPath = cfg.netrcPath;
+      GithubToken = cfg.githubToken;
+      HGRCPath = cfg.hgrcPath;
+      TraceExporter = cfg.traceExporter;
+      StatsExporter = cfg.statsExporter;
+      SumDBs = cfg.sumDBs;
+      NoSumPatterns = cfg.noSumPatterns;
+      DownloadMode = cfg.downloadMode;
+      NetworkMode = cfg.networkMode;
+      DownloadURL = cfg.downloadURL;
+      SingleFlightType = cfg.singleFlightType;
+      IndexType = cfg.indexType;
+      ShutdownTimeout = cfg.shutdownTimeout;
+      SingleFlight = {
+        Etcd = {
+          Endpoints = builtins.concatStringsSep "," cfg.singleFlight.etcd.endpoints;
+        };
+        Redis = {
+          Endpoint = cfg.singleFlight.redis.endpoint;
+          Password = cfg.singleFlight.redis.password;
+          LockConfig = {
+            TTL = cfg.singleFlight.redis.lockConfig.ttl;
+            Timeout = cfg.singleFlight.redis.lockConfig.timeout;
+            MaxRetries = cfg.singleFlight.redis.lockConfig.maxRetries;
+          };
+        };
+        RedisSentinel = {
+          Endpoints = cfg.singleFlight.redisSentinel.endpoints;
+          MasterName = cfg.singleFlight.redisSentinel.masterName;
+          SentinelPassword = cfg.singleFlight.redisSentinel.sentinelPassword;
+          LockConfig = {
+            TTL = cfg.singleFlight.redisSentinel.lockConfig.ttl;
+            Timeout = cfg.singleFlight.redisSentinel.lockConfig.timeout;
+            MaxRetries = cfg.singleFlight.redisSentinel.lockConfig.maxRetries;
+          };
+        };
+      };
+      Storage = {
+        CDN = {
+          Endpoint = cfg.storage.cdn.endpoint;
+        };
+        Disk = {
+          RootPath = cfg.storage.disk.rootPath;
+        };
+        GCP = {
+          ProjectID = cfg.storage.gcp.projectID;
+          Bucket = cfg.storage.gcp.bucket;
+          JSONKey = cfg.storage.gcp.jsonKey;
+        };
+        Minio = {
+          Endpoint = cfg.storage.minio.endpoint;
+          Key = cfg.storage.minio.key;
+          Secret = cfg.storage.minio.secret;
+          EnableSSL = cfg.storage.minio.enableSSL;
+          Bucket = cfg.storage.minio.bucket;
+          region = cfg.storage.minio.region;
+        };
+        Mongo = {
+          URL = cfg.storage.mongo.url;
+          DefaultDBName = cfg.storage.mongo.defaultDBName;
+          CertPath = cfg.storage.mongo.certPath;
+          Insecure = cfg.storage.mongo.insecure;
+        };
+        S3 = {
+          Region = cfg.storage.s3.region;
+          Key = cfg.storage.s3.key;
+          Secret = cfg.storage.s3.secret;
+          Token = cfg.storage.s3.token;
+          Bucket = cfg.storage.s3.bucket;
+          ForcePathStyle = cfg.storage.s3.forcePathStyle;
+          UseDefaultConfiguration = cfg.storage.s3.useDefaultConfiguration;
+          CredentialsEndpoint = cfg.storage.s3.credentialsEndpoint;
+          AwsContainerCredentialsRelativeURI = cfg.storage.s3.awsContainerCredentialsRelativeURI;
+          Endpoint = cfg.storage.s3.endpoint;
+        };
+        AzureBlob = {
+          AccountName = cfg.storage.azureblob.accountName;
+          AccountKey = cfg.storage.azureblob.accountKey;
+          ContainerName = cfg.storage.azureblob.containerName;
+        };
+        External = {
+          URL = cfg.storage.external.url;
+        };
+      };
+      Index = {
+        MySQL = {
+          Protocol = cfg.index.mysql.protocol;
+          Host = cfg.index.mysql.host;
+          Port = cfg.index.mysql.port;
+          User = cfg.index.mysql.user;
+          Password = cfg.index.mysql.password;
+          Database = cfg.index.mysql.database;
+          Params = {
+            parseTime = cfg.index.mysql.params.parseTime;
+            timeout = cfg.index.mysql.params.timeout;
+          };
+        };
+        Postgres = {
+          Host = cfg.index.postgres.host;
+          Port = cfg.index.postgres.port;
+          User = cfg.index.postgres.user;
+          Password = cfg.index.postgres.password;
+          Database = cfg.index.postgres.database;
+          Params = {
+            connect_timeout = cfg.index.postgres.params.connect_timeout;
+            sslmode = cfg.index.postgres.params.sslmode;
+          };
+        };
+      };
+    }
+  );
+
+  configFile = pkgs.runCommandLocal "config.toml" { } ''
+    ${pkgs.buildPackages.jq}/bin/jq 'del(..|nulls)' \
+      < ${pkgs.writeText "config.json" (builtins.toJSON athensConfig)} | \
+    ${pkgs.buildPackages.remarshal}/bin/remarshal -if json -of toml \
+      > $out
+  '';
+in
+{
+  meta = {
+    maintainers = pkgs.athens.meta.maintainers;
+    doc = ./athens.md;
+  };
+
+  options.services.athens = {
+    enable = mkEnableOption (lib.mdDoc "Go module datastore and proxy");
+
+    package = mkOption {
+      default = pkgs.athens;
+      defaultText = literalExpression "pkgs.athens";
+      example = "pkgs.athens";
+      description = lib.mdDoc "Which athens derivation to use";
+      type = types.package;
+    };
+
+    goBinary = mkOption {
+      type = types.package;
+      default = pkgs.go;
+      defaultText = literalExpression "pkgs.go";
+      example = "pkgs.go_1_21";
+      description = lib.mdDoc ''
+        The Go package used by Athens at runtime.
+
+        Athens primarily runs two Go commands:
+        1. `go mod download -json <module>@<version>`
+        2. `go list -m -json <module>@latest`
+      '';
+    };
+
+    goEnv = mkOption {
+      type = types.enum [ "development" "production" ];
+      description = lib.mdDoc "Specifies the type of environment to run. One of 'development' or 'production'.";
+      default = "development";
+      example = "production";
+    };
+
+    goBinaryEnvVars = mkOption {
+      type = types.attrs;
+      description = lib.mdDoc "Environment variables to pass to the Go binary.";
+      example = ''
+        { "GOPROXY" = "direct", "GODEBUG" = "true" }
+      '';
+      default = { };
+    };
+
+    goGetWorkers = mkOption {
+      type = types.int;
+      description = lib.mdDoc "Number of workers concurrently downloading modules.";
+      default = 10;
+      example = 32;
+    };
+
+    goGetDir = mkOption {
+      type = types.nullOr types.path;
+      description = lib.mdDoc ''
+        Temporary directory that Athens will use to
+        fetch modules from VCS prior to persisting
+        them to a storage backend.
+
+        If the value is empty, Athens will use the
+        default OS temp directory.
+      '';
+      default = null;
+      example = "/tmp/athens";
+    };
+
+    protocolWorkers = mkOption {
+      type = types.int;
+      description = lib.mdDoc "Number of workers concurrently serving protocol paths.";
+      default = 30;
+    };
+
+    logLevel = mkOption {
+      type = types.nullOr (types.enum [ "panic" "fatal" "error" "warning" "info" "debug" "trace" ]);
+      description = lib.mdDoc ''
+        Log level for Athens.
+        Supports all logrus log levels (https://github.com/Sirupsen/logrus#level-logging)".
+      '';
+      default = "warning";
+      example = "debug";
+    };
+
+    cloudRuntime = mkOption {
+      type = types.enum [ "GCP" "none" ];
+      description = lib.mdDoc ''
+        Specifies the Cloud Provider on which the Proxy/registry is running.
+      '';
+      default = "none";
+      example = "GCP";
+    };
+
+    enablePprof = mkOption {
+      type = types.bool;
+      description = lib.mdDoc "Enable pprof endpoints.";
+      default = false;
+    };
+
+    pprofPort = mkOption {
+      type = types.port;
+      description = lib.mdDoc "Port number for pprof endpoints.";
+      default = 3301;
+      example = 443;
+    };
+
+    filterFile = mkOption {
+      type = types.nullOr types.path;
+      description = lib.mdDoc ''Filename for the include exclude filter.'';
+      default = null;
+      example = literalExpression ''
+        pkgs.writeText "filterFile" '''
+          - github.com/azure
+          + github.com/azure/azure-sdk-for-go
+          D golang.org/x/tools
+        '''
+      '';
+    };
+
+    robotsFile = mkOption {
+      type = types.nullOr types.path;
+      description = lib.mdDoc ''Provides /robots.txt for net crawlers.'';
+      default = null;
+      example = literalExpression ''pkgs.writeText "robots.txt" "# my custom robots.txt ..."'';
+    };
+
+    timeout = mkOption {
+      type = types.int;
+      description = lib.mdDoc "Timeout for external network calls in seconds.";
+      default = 300;
+      example = 3;
+    };
+
+    storageType = mkOption {
+      type = types.enum [ "memory" "disk" "mongo" "gcp" "minio" "s3" "azureblob" "external" ];
+      description = lib.mdDoc "Specifies the type of storage backend to use.";
+      default = "disk";
+    };
+
+    tlsCertFile = mkOption {
+      type = types.nullOr types.path;
+      description = lib.mdDoc "Path to the TLS certificate file.";
+      default = null;
+      example = "/etc/ssl/certs/athens.crt";
+    };
+
+    tlsKeyFile = mkOption {
+      type = types.nullOr types.path;
+      description = lib.mdDoc "Path to the TLS key file.";
+      default = null;
+      example = "/etc/ssl/certs/athens.key";
+    };
+
+    port = mkOption {
+      type = types.port;
+      default = 3000;
+      description = lib.mdDoc ''
+        Port number Athens listens on.
+      '';
+      example = 443;
+    };
+
+    unixSocket = mkOption {
+      type = types.nullOr types.path;
+      description = lib.mdDoc ''
+        Path to the unix socket file.
+        If set, Athens will listen on the unix socket instead of TCP socket.
+      '';
+      default = null;
+      example = "/run/athens.sock";
+    };
+
+    globalEndpoint = mkOption {
+      type = types.str;
+      description = lib.mdDoc ''
+        Endpoint for a package registry in case of a proxy cache miss.
+      '';
+      default = "";
+      example = "http://upstream-athens.example.com:3000";
+    };
+
+    basicAuthUser = mkOption {
+      type = types.nullOr types.str;
+      description = lib.mdDoc ''
+        Username for basic auth.
+      '';
+      default = null;
+      example = "user";
+    };
+
+    basicAuthPass = mkOption {
+      type = types.nullOr types.str;
+      description = lib.mdDoc ''
+        Password for basic auth. Warning: this is stored in plain text in the config file.
+      '';
+      default = null;
+      example = "swordfish";
+    };
+
+    forceSSL = mkOption {
+      type = types.bool;
+      description = lib.mdDoc ''
+        Force SSL redirects for incoming requests.
+      '';
+      default = false;
+    };
+
+    validatorHook = mkOption {
+      type = types.nullOr types.str;
+      description = lib.mdDoc ''
+        Endpoint to validate modules against.
+
+        Not used if empty.
+      '';
+      default = null;
+      example = "https://validation.example.com";
+    };
+
+    pathPrefix = mkOption {
+      type = types.nullOr types.str;
+      description = lib.mdDoc ''
+        Sets basepath for all routes.
+      '';
+      default = null;
+      example = "/athens";
+    };
+
+    netrcPath = mkOption {
+      type = types.nullOr types.path;
+      description = lib.mdDoc ''
+        Path to the .netrc file.
+      '';
+      default = null;
+      example = "/home/user/.netrc";
+    };
+
+    githubToken = mkOption {
+      type = types.nullOr types.str;
+      description = lib.mdDoc ''
+        Creates .netrc file with the given token to be used for GitHub.
+        Warning: this is stored in plain text in the config file.
+      '';
+      default = null;
+      example = "ghp_1234567890";
+    };
+
+    hgrcPath = mkOption {
+      type = types.nullOr types.path;
+      description = lib.mdDoc ''
+        Path to the .hgrc file.
+      '';
+      default = null;
+      example = "/home/user/.hgrc";
+    };
+
+    traceExporter = mkOption {
+      type = types.nullOr (types.enum [ "jaeger" "datadog" ]);
+      description = lib.mdDoc ''
+        Trace exporter to use.
+      '';
+      default = null;
+    };
+
+    traceExporterURL = mkOption {
+      type = types.nullOr types.str;
+      description = lib.mdDoc ''
+        URL endpoint that traces will be sent to.
+      '';
+      default = null;
+      example = "http://localhost:14268";
+    };
+
+    statsExporter = mkOption {
+      type = types.nullOr (types.enum [ "prometheus" ]);
+      description = lib.mdDoc "Stats exporter to use.";
+      default = null;
+    };
+
+    sumDBs = mkOption {
+      type = types.listOf types.str;
+      description = lib.mdDoc ''
+        List of fully qualified URLs that Athens will proxy
+        that the go command can use a checksum verifier.
+      '';
+      default = [ "https://sum.golang.org" ];
+    };
+
+    noSumPatterns = mkOption {
+      type = types.listOf types.str;
+      description = lib.mdDoc ''
+        List of patterns that Athens sum db proxy will return a 403 for.
+      '';
+      default = [ ];
+      example = [ "github.com/mycompany/*" ];
+    };
+
+    downloadMode = mkOption {
+      type = types.oneOf [ (types.enum [ "sync" "async" "redirect" "async_redirect" "none" ]) (types.strMatching "^file:.*$|^custom:.*$") ];
+      description = lib.mdDoc ''
+        Defines how Athens behaves when a module@version
+        is not found in storage. There are 7 options:
+        1. "sync": download the module synchronously and
+        return the results to the client.
+        2. "async": return 404, but asynchronously store the module
+        in the storage backend.
+        3. "redirect": return a 301 redirect status to the client
+        with the base URL as the DownloadRedirectURL from below.
+        4. "async_redirect": same as option number 3 but it will
+        asynchronously store the module to the backend.
+        5. "none": return 404 if a module is not found and do nothing.
+        6. "file:<path>": will point to an HCL file that specifies
+        any of the 5 options above based on different import paths.
+        7. "custom:<base64-encoded-hcl>" is the same as option 6
+        but the file is fully encoded in the option. This is
+        useful for using an environment variable in serverless
+        deployments.
+      '';
+      default = "async_redirect";
+    };
+
+    networkMode = mkOption {
+      type = types.enum [ "strict" "offline" "fallback" ];
+      description = lib.mdDoc ''
+        Configures how Athens will return the results
+        of the /list endpoint as it can be assembled from both its own
+        storage and the upstream VCS.
+
+        Note, that for better error messaging, this would also affect how other
+        endpoints behave.
+
+        Modes:
+        1. strict: merge VCS versions with storage versions, but fail if either of them fails.
+        2. offline: only get storage versions, never reach out to VCS.
+        3. fallback: only return storage versions, if VCS fails. Note this means that you may
+        see inconsistent results since fallback mode does a best effort of giving you what's
+        available at the time of requesting versions.
+      '';
+      default = "strict";
+    };
+
+    downloadURL = mkOption {
+      type = types.str;
+      description = lib.mdDoc "URL used if DownloadMode is set to redirect.";
+      default = "https://proxy.golang.org";
+    };
+
+    singleFlightType = mkOption {
+      type = types.enum [ "memory" "etcd" "redis" "redis-sentinel" "gcp" "azureblob" ];
+      description = lib.mdDoc ''
+        Determines what mechanism Athens uses to manage concurrency flowing into the Athens backend.
+      '';
+      default = "memory";
+    };
+
+    indexType = mkOption {
+      type = types.enum [ "none" "memory" "mysql" "postgres" ];
+      description = lib.mdDoc ''
+        Type of index backend Athens will use.
+      '';
+      default = "none";
+    };
+
+    shutdownTimeout = mkOption {
+      type = types.int;
+      description = lib.mdDoc ''
+        Number of seconds to wait for the server to shutdown gracefully.
+      '';
+      default = 60;
+      example = 1;
+    };
+
+    singleFlight = {
+      etcd = {
+        endpoints = mkOption {
+          type = types.listOf types.str;
+          description = lib.mdDoc "URLs that determine all distributed etcd servers.";
+          default = [ ];
+          example = [ "localhost:2379" ];
+        };
+      };
+      redis = {
+        endpoint = mkOption {
+          type = types.str;
+          description = lib.mdDoc "URL of the redis server.";
+          default = "";
+          example = "localhost:6379";
+        };
+        password = mkOption {
+          type = types.str;
+          description = lib.mdDoc "Password for the redis server. Warning: this is stored in plain text in the config file.";
+          default = "";
+          example = "swordfish";
+        };
+
+        lockConfig = {
+          ttl = mkOption {
+            type = types.int;
+            description = lib.mdDoc "TTL for the lock in seconds.";
+            default = 900;
+            example = 1;
+          };
+          timeout = mkOption {
+            type = types.int;
+            description = lib.mdDoc "Timeout for the lock in seconds.";
+            default = 15;
+            example = 1;
+          };
+          maxRetries = mkOption {
+            type = types.int;
+            description = lib.mdDoc "Maximum number of retries for the lock.";
+            default = 10;
+            example = 1;
+          };
+        };
+      };
+
+      redisSentinel = {
+        endpoints = mkOption {
+          type = types.listOf types.str;
+          description = lib.mdDoc "URLs that determine all distributed redis servers.";
+          default = [ ];
+          example = [ "localhost:26379" ];
+        };
+        masterName = mkOption {
+          type = types.str;
+          description = lib.mdDoc "Name of the sentinel master server.";
+          default = "";
+          example = "redis-1";
+        };
+        sentinelPassword = mkOption {
+          type = types.str;
+          description = lib.mdDoc "Password for the sentinel server. Warning: this is stored in plain text in the config file.";
+          default = "";
+          example = "swordfish";
+        };
+
+        lockConfig = {
+          ttl = mkOption {
+            type = types.int;
+            description = lib.mdDoc "TTL for the lock in seconds.";
+            default = 900;
+            example = 1;
+          };
+          timeout = mkOption {
+            type = types.int;
+            description = lib.mdDoc "Timeout for the lock in seconds.";
+            default = 15;
+            example = 1;
+          };
+          maxRetries = mkOption {
+            type = types.int;
+            description = lib.mdDoc "Maximum number of retries for the lock.";
+            default = 10;
+            example = 1;
+          };
+        };
+      };
+    };
+
+    storage = {
+      cdn = {
+        endpoint = mkOption {
+          type = types.nullOr types.str;
+          description = lib.mdDoc "hostname of the CDN server.";
+          example = "cdn.example.com";
+          default = null;
+        };
+      };
+
+      disk = {
+        rootPath = mkOption {
+          type = types.nullOr types.path;
+          description = lib.mdDoc "Athens disk root folder.";
+          default = "/var/lib/athens";
+        };
+      };
+
+      gcp = {
+        projectID = mkOption {
+          type = types.nullOr types.str;
+          description = lib.mdDoc "GCP project ID.";
+          example = "my-project";
+          default = null;
+        };
+        bucket = mkOption {
+          type = types.nullOr types.str;
+          description = lib.mdDoc "GCP backend storage bucket.";
+          example = "my-bucket";
+          default = null;
+        };
+        jsonKey = mkOption {
+          type = types.nullOr types.str;
+          description = lib.mdDoc "Base64 encoded GCP service account key. Warning: this is stored in plain text in the config file.";
+          default = null;
+        };
+      };
+
+      minio = {
+        endpoint = mkOption {
+          type = types.nullOr types.str;
+          description = lib.mdDoc "Endpoint of the minio storage backend.";
+          example = "minio.example.com:9001";
+          default = null;
+        };
+        key = mkOption {
+          type = types.nullOr types.str;
+          description = lib.mdDoc "Access key id for the minio storage backend.";
+          example = "minio";
+          default = null;
+        };
+        secret = mkOption {
+          type = types.nullOr types.str;
+          description = lib.mdDoc "Secret key for the minio storage backend. Warning: this is stored in plain text in the config file.";
+          example = "minio123";
+          default = null;
+        };
+        enableSSL = mkOption {
+          type = types.bool;
+          description = lib.mdDoc "Enable SSL for the minio storage backend.";
+          default = false;
+        };
+        bucket = mkOption {
+          type = types.nullOr types.str;
+          description = lib.mdDoc "Bucket name for the minio storage backend.";
+          example = "gomods";
+          default = null;
+        };
+        region = mkOption {
+          type = types.nullOr types.str;
+          description = lib.mdDoc "Region for the minio storage backend.";
+          example = "us-east-1";
+          default = null;
+        };
+      };
+
+      mongo = {
+        url = mkOption {
+          type = types.nullOr types.str;
+          description = lib.mdDoc "URL of the mongo database.";
+          example = "mongodb://localhost:27017";
+          default = null;
+        };
+        defaultDBName = mkOption {
+          type = types.nullOr types.str;
+          description = lib.mdDoc "Name of the mongo database.";
+          example = "athens";
+          default = null;
+        };
+        certPath = mkOption {
+          type = types.nullOr types.path;
+          description = lib.mdDoc "Path to the certificate file for the mongo database.";
+          example = "/etc/ssl/mongo.pem";
+          default = null;
+        };
+        insecure = mkOption {
+          type = types.bool;
+          description = lib.mdDoc "Allow insecure connections to the mongo database.";
+          default = false;
+        };
+      };
+
+      s3 = {
+        region = mkOption {
+          type = types.nullOr types.str;
+          description = lib.mdDoc "Region of the S3 storage backend.";
+          example = "eu-west-3";
+          default = null;
+        };
+        key = mkOption {
+          type = types.nullOr types.str;
+          description = lib.mdDoc "Access key id for the S3 storage backend.";
+          example = "minio";
+          default = null;
+        };
+        secret = mkOption {
+          type = types.str;
+          description = lib.mdDoc "Secret key for the S3 storage backend. Warning: this is stored in plain text in the config file.";
+          default = "";
+        };
+        token = mkOption {
+          type = types.nullOr types.str;
+          description = lib.mdDoc "Token for the S3 storage backend. Warning: this is stored in plain text in the config file.";
+          default = null;
+        };
+        bucket = mkOption {
+          type = types.nullOr types.str;
+          description = lib.mdDoc "Bucket name for the S3 storage backend.";
+          example = "gomods";
+          default = null;
+        };
+        forcePathStyle = mkOption {
+          type = types.bool;
+          description = lib.mdDoc "Force path style for the S3 storage backend.";
+          default = false;
+        };
+        useDefaultConfiguration = mkOption {
+          type = types.bool;
+          description = lib.mdDoc "Use default configuration for the S3 storage backend.";
+          default = false;
+        };
+        credentialsEndpoint = mkOption {
+          type = types.str;
+          description = lib.mdDoc "Credentials endpoint for the S3 storage backend.";
+          default = "";
+        };
+        awsContainerCredentialsRelativeURI = mkOption {
+          type = types.nullOr types.str;
+          description = lib.mdDoc "Container relative url (used by fargate).";
+          default = null;
+        };
+        endpoint = mkOption {
+          type = types.nullOr types.str;
+          description = lib.mdDoc "Endpoint for the S3 storage backend.";
+          default = null;
+        };
+      };
+
+      azureblob = {
+        accountName = mkOption {
+          type = types.nullOr types.str;
+          description = lib.mdDoc "Account name for the Azure Blob storage backend.";
+          default = null;
+        };
+        accountKey = mkOption {
+          type = types.nullOr types.str;
+          description = lib.mdDoc "Account key for the Azure Blob storage backend. Warning: this is stored in plain text in the config file.";
+          default = null;
+        };
+        containerName = mkOption {
+          type = types.nullOr types.str;
+          description = lib.mdDoc "Container name for the Azure Blob storage backend.";
+          default = null;
+        };
+      };
+
+      external = {
+        url = mkOption {
+          type = types.nullOr types.str;
+          description = lib.mdDoc "URL of the backend storage layer.";
+          example = "https://athens.example.com";
+          default = null;
+        };
+      };
+    };
+
+    index = {
+      mysql = {
+        protocol = mkOption {
+          type = types.str;
+          description = lib.mdDoc "Protocol for the MySQL database.";
+          default = "tcp";
+        };
+        host = mkOption {
+          type = types.str;
+          description = lib.mdDoc "Host for the MySQL database.";
+          default = "localhost";
+        };
+        port = mkOption {
+          type = types.int;
+          description = lib.mdDoc "Port for the MySQL database.";
+          default = 3306;
+        };
+        user = mkOption {
+          type = types.str;
+          description = lib.mdDoc "User for the MySQL database.";
+          default = "root";
+        };
+        password = mkOption {
+          type = types.nullOr types.str;
+          description = lib.mdDoc "Password for the MySQL database. Warning: this is stored in plain text in the config file.";
+          default = null;
+        };
+        database = mkOption {
+          type = types.str;
+          description = lib.mdDoc "Database name for the MySQL database.";
+          default = "athens";
+        };
+        params = {
+          parseTime = mkOption {
+            type = types.nullOr types.str;
+            description = lib.mdDoc "Parse time for the MySQL database.";
+            default = "true";
+          };
+          timeout = mkOption {
+            type = types.nullOr types.str;
+            description = lib.mdDoc "Timeout for the MySQL database.";
+            default = "30s";
+          };
+        };
+      };
+
+      postgres = {
+        host = mkOption {
+          type = types.str;
+          description = lib.mdDoc "Host for the Postgres database.";
+          default = "localhost";
+        };
+        port = mkOption {
+          type = types.int;
+          description = lib.mdDoc "Port for the Postgres database.";
+          default = 5432;
+        };
+        user = mkOption {
+          type = types.str;
+          description = lib.mdDoc "User for the Postgres database.";
+          default = "postgres";
+        };
+        password = mkOption {
+          type = types.nullOr types.str;
+          description = lib.mdDoc "Password for the Postgres database. Warning: this is stored in plain text in the config file.";
+          default = null;
+        };
+        database = mkOption {
+          type = types.str;
+          description = lib.mdDoc "Database name for the Postgres database.";
+          default = "athens";
+        };
+        params = {
+          connect_timeout = mkOption {
+            type = types.nullOr types.str;
+            description = lib.mdDoc "Connect timeout for the Postgres database.";
+            default = "30s";
+          };
+          sslmode = mkOption {
+            type = types.nullOr types.str;
+            description = lib.mdDoc "SSL mode for the Postgres database.";
+            default = "disable";
+          };
+        };
+      };
+    };
+
+    extraConfig = mkOption {
+      type = types.attrs;
+      description = lib.mdDoc ''
+        Extra configuration options for the athens config file.
+      '';
+      default = { };
+    };
+  };
+
+  config = mkIf cfg.enable {
+    systemd.services.athens = {
+      description = "Athens Go module proxy";
+      documentation = [ "https://docs.gomods.io" ];
+
+      wantedBy = [ "multi-user.target" ];
+      after = [ "network-online.target" ];
+      wants = [ "network-online.target" ];
+
+      serviceConfig = {
+        Restart = "on-abnormal";
+        Nice = 5;
+        ExecStart = ''${cfg.package}/bin/athens -config_file=${configFile}'';
+
+        KillMode = "mixed";
+        KillSignal = "SIGINT";
+        TimeoutStopSec = cfg.shutdownTimeout;
+
+        LimitNOFILE = 1048576;
+        LimitNPROC = 512;
+
+        DynamicUser = true;
+        PrivateTmp = true;
+        PrivateDevices = true;
+        ProtectHome = "read-only";
+        ProtectSystem = "full";
+
+        ReadWritePaths = mkIf (cfg.storage.disk.rootPath != null && (! hasPrefix "/var/lib/" cfg.storage.disk.rootPath)) [ cfg.storage.disk.rootPath ];
+        StateDirectory = mkIf (hasPrefix "/var/lib/" cfg.storage.disk.rootPath) [ (removePrefix "/var/lib/" cfg.storage.disk.rootPath) ];
+
+        CapabilityBoundingSet = [ "CAP_NET_BIND_SERVICE" ];
+        AmbientCapabilities = [ "CAP_NET_BIND_SERVICE" ];
+        NoNewPrivileges = true;
+      };
+    };
+
+    networking.firewall = {
+      allowedTCPPorts = optionals (cfg.unixSocket == null) [ cfg.port ]
+        ++ optionals cfg.enablePprof [ cfg.pprofPort ];
+    };
+  };
+
+}
diff --git a/nixpkgs/nixos/modules/services/development/distccd.nix b/nixpkgs/nixos/modules/services/development/distccd.nix
index a3c909eb1959..c33bf436bffb 100644
--- a/nixpkgs/nixos/modules/services/development/distccd.nix
+++ b/nixpkgs/nixos/modules/services/development/distccd.nix
@@ -66,14 +66,7 @@ in
         '';
       };
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.distcc;
-        defaultText = literalExpression "pkgs.distcc";
-        description = lib.mdDoc ''
-          The distcc package to use.
-        '';
-      };
+      package = mkPackageOption pkgs "distcc" { };
 
       port = mkOption {
         type = types.port;
diff --git a/nixpkgs/nixos/modules/services/development/jupyter/default.nix b/nixpkgs/nixos/modules/services/development/jupyter/default.nix
index 9f7910844468..da8c7547fdd7 100644
--- a/nixpkgs/nixos/modules/services/development/jupyter/default.nix
+++ b/nixpkgs/nixos/modules/services/development/jupyter/default.nix
@@ -34,17 +34,10 @@ in {
       '';
     };
 
-    package = mkOption {
-      type = types.package;
-      # NOTE: We don't use top-level jupyter because we don't
-      # want to pass in JUPYTER_PATH but use .environment instead,
-      # saving a rebuild.
-      default = pkgs.python3.pkgs.notebook;
-      defaultText = literalExpression "pkgs.python3.pkgs.notebook";
-      description = lib.mdDoc ''
-        Jupyter package to use.
-      '';
-    };
+    # NOTE: We don't use top-level jupyter because we don't
+    # want to pass in JUPYTER_PATH but use .environment instead,
+    # saving a rebuild.
+    package = mkPackageOption pkgs [ "python3" "pkgs" "notebook" ] { };
 
     command = mkOption {
       type = types.str;
diff --git a/nixpkgs/nixos/modules/services/development/rstudio-server/default.nix b/nixpkgs/nixos/modules/services/development/rstudio-server/default.nix
index bf4c7727bf74..fc3756edf0ab 100644
--- a/nixpkgs/nixos/modules/services/development/rstudio-server/default.nix
+++ b/nixpkgs/nixos/modules/services/development/rstudio-server/default.nix
@@ -39,14 +39,8 @@ in
       '';
     };
 
-    package = mkOption {
-      type = types.package;
-      default = pkgs.rstudio-server;
-      defaultText = literalExpression "pkgs.rstudio-server";
-      example = literalExpression "pkgs.rstudioServerWrapper.override { packages = [ pkgs.rPackages.ggplot2 ]; }";
-      description = lib.mdDoc ''
-        Rstudio server package to use. Can be set to rstudioServerWrapper to provide packages.
-      '';
+    package = mkPackageOption pkgs "rstudio-server" {
+      example = "rstudioServerWrapper.override { packages = [ pkgs.rPackages.ggplot2 ]; }";
     };
 
     rserverExtraConfig = mkOption {
diff --git a/nixpkgs/nixos/modules/services/development/zammad.nix b/nixpkgs/nixos/modules/services/development/zammad.nix
index d24ed24ef395..87aceddd6635 100644
--- a/nixpkgs/nixos/modules/services/development/zammad.nix
+++ b/nixpkgs/nixos/modules/services/development/zammad.nix
@@ -30,12 +30,7 @@ in
     services.zammad = {
       enable = mkEnableOption (lib.mdDoc "Zammad, a web-based, open source user support/ticketing solution");
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.zammad;
-        defaultText = literalExpression "pkgs.zammad";
-        description = lib.mdDoc "Zammad package to use.";
-      };
+      package = mkPackageOption pkgs "zammad" { };
 
       dataDir = mkOption {
         type = types.path;
diff --git a/nixpkgs/nixos/modules/services/display-managers/greetd.nix b/nixpkgs/nixos/modules/services/display-managers/greetd.nix
index 89cb81f3a78f..779e141ca24b 100644
--- a/nixpkgs/nixos/modules/services/display-managers/greetd.nix
+++ b/nixpkgs/nixos/modules/services/display-managers/greetd.nix
@@ -10,12 +10,7 @@ in
   options.services.greetd = {
     enable = mkEnableOption (lib.mdDoc "greetd");
 
-    package = mkOption {
-      type = types.package;
-      default = pkgs.greetd.greetd;
-      defaultText = literalExpression "pkgs.greetd.greetd";
-      description = lib.mdDoc "The greetd package that should be used.";
-    };
+    package = mkPackageOption pkgs [ "greetd" "greetd" ] { };
 
     settings = mkOption {
       type = settingsFormat.type;
diff --git a/nixpkgs/nixos/modules/services/editors/emacs.md b/nixpkgs/nixos/modules/services/editors/emacs.md
index 9db1bd594175..02f47b098d86 100644
--- a/nixpkgs/nixos/modules/services/editors/emacs.md
+++ b/nixpkgs/nixos/modules/services/editors/emacs.md
@@ -172,9 +172,9 @@ nix-env -f "<nixpkgs>" -qaP -A emacs.pkgs.orgPackages
 :::
 
 If you are on NixOS, you can install this particular Emacs for all users by
-adding it to the list of system packages (see
-[](#sec-declarative-package-mgmt)). Simply modify your file
-{file}`configuration.nix` to make it contain:
+putting the `emacs.nix` file in `/etc/nixos` and adding it to the list of
+system packages (see [](#sec-declarative-package-mgmt)). Simply modify your
+file {file}`configuration.nix` to make it contain:
 ::: {.example #module-services-emacs-configuration-nix}
 ### Custom Emacs in `configuration.nix`
 
@@ -182,7 +182,7 @@ adding it to the list of system packages (see
 {
  environment.systemPackages = [
    # [...]
-   (import /path/to/emacs.nix { inherit pkgs; })
+   (import ./emacs.nix { inherit pkgs; })
   ];
 }
 ```
@@ -197,8 +197,8 @@ https://nixos.org/nixpkgs/manual/#sec-modify-via-packageOverrides
 -->
 
 If you are not on NixOS or want to install this particular Emacs only for
-yourself, you can do so by adding it to your
-{file}`~/.config/nixpkgs/config.nix` (see
+yourself, you can do so by putting `emacs.nix` in `~/.config/nixpkgs` and
+adding it to your {file}`~/.config/nixpkgs/config.nix` (see
 [Nixpkgs manual](https://nixos.org/nixpkgs/manual/#sec-modify-via-packageOverrides)):
 ::: {.example #module-services-emacs-config-nix}
 ### Custom Emacs in `~/.config/nixpkgs/config.nix`
@@ -206,7 +206,7 @@ yourself, you can do so by adding it to your
 ```
 {
   packageOverrides = super: let self = super.pkgs; in {
-    myemacs = import /path/to/emacs.nix { pkgs = self; };
+    myemacs = import ./emacs.nix { pkgs = self; };
   };
 }
 ```
@@ -264,7 +264,6 @@ To install and enable the {command}`systemd` user service for Emacs
 daemon, add the following to your {file}`configuration.nix`:
 ```
 services.emacs.enable = true;
-services.emacs.package = import /home/cassou/.emacs.d { pkgs = pkgs; };
 ```
 
 The {var}`services.emacs.package` option allows a custom
diff --git a/nixpkgs/nixos/modules/services/editors/emacs.nix b/nixpkgs/nixos/modules/services/editors/emacs.nix
index fad4f39ff210..6f45be6640bc 100644
--- a/nixpkgs/nixos/modules/services/editors/emacs.nix
+++ b/nixpkgs/nixos/modules/services/editors/emacs.nix
@@ -63,14 +63,7 @@ in
     };
 
 
-    package = mkOption {
-      type = types.package;
-      default = pkgs.emacs;
-      defaultText = literalExpression "pkgs.emacs";
-      description = lib.mdDoc ''
-        emacs derivation to use.
-      '';
-    };
+    package = mkPackageOption pkgs "emacs" { };
 
     defaultEditor = mkOption {
       type = types.bool;
diff --git a/nixpkgs/nixos/modules/services/editors/infinoted.nix b/nixpkgs/nixos/modules/services/editors/infinoted.nix
index de0989994019..976163d4d0b2 100644
--- a/nixpkgs/nixos/modules/services/editors/infinoted.nix
+++ b/nixpkgs/nixos/modules/services/editors/infinoted.nix
@@ -8,14 +8,7 @@ in {
   options.services.infinoted = {
     enable = mkEnableOption (lib.mdDoc "infinoted");
 
-    package = mkOption {
-      type = types.package;
-      default = pkgs.libinfinity;
-      defaultText = literalExpression "pkgs.libinfinity";
-      description = lib.mdDoc ''
-        Package providing infinoted
-      '';
-    };
+    package = mkPackageOption pkgs "libinfinity" { };
 
     keyFile = mkOption {
       type = types.nullOr types.path;
diff --git a/nixpkgs/nixos/modules/services/finance/odoo.nix b/nixpkgs/nixos/modules/services/finance/odoo.nix
index b8574ed09af9..aa9bd0014d98 100644
--- a/nixpkgs/nixos/modules/services/finance/odoo.nix
+++ b/nixpkgs/nixos/modules/services/finance/odoo.nix
@@ -11,12 +11,7 @@ in
     services.odoo = {
       enable = mkEnableOption (lib.mdDoc "odoo");
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.odoo;
-        defaultText = literalExpression "pkgs.odoo";
-        description = lib.mdDoc "Odoo package to use.";
-      };
+      package = mkPackageOption pkgs "odoo" { };
 
       addons = mkOption {
         type = with types; listOf package;
diff --git a/nixpkgs/nixos/modules/services/games/asf.nix b/nixpkgs/nixos/modules/services/games/asf.nix
index 432de6336ce2..27d174d6726b 100644
--- a/nixpkgs/nixos/modules/services/games/asf.nix
+++ b/nixpkgs/nixos/modules/services/games/asf.nix
@@ -47,12 +47,12 @@ in
             description = lib.mdDoc "Whether to start the web-ui. This is the preferred way of configuring things such as the steam guard token.";
           };
 
-          package = mkOption {
-            type = types.package;
-            default = pkgs.ArchiSteamFarm.ui;
-            defaultText = lib.literalExpression "pkgs.ArchiSteamFarm.ui";
-            description =
-              lib.mdDoc "Web-UI package to use. Contents must be in lib/dist.";
+          package = mkPackageOption pkgs [ "ArchiSteamFarm" "ui" ] {
+            extraDescription = ''
+              ::: {.note}
+              Contents must be in lib/dist
+              :::
+            '';
           };
         };
       };
@@ -65,12 +65,13 @@ in
       description = lib.mdDoc "The Web-UI hosted on 127.0.0.1:1242.";
     };
 
-    package = mkOption {
-      type = types.package;
-      default = pkgs.ArchiSteamFarm;
-      defaultText = lib.literalExpression "pkgs.ArchiSteamFarm";
-      description =
-        lib.mdDoc "Package to use. Should always be the latest version, for security reasons, since this module uses very new features and to not get out of sync with the Steam API.";
+    package = mkPackageOption pkgs "ArchiSteamFarm" {
+      extraDescription = ''
+        ::: {.warning}
+        Should always be the latest version, for security reasons,
+        since this module uses very new features and to not get out of sync with the Steam API.
+        :::
+      '';
     };
 
     dataDir = mkOption {
diff --git a/nixpkgs/nixos/modules/services/games/crossfire-server.nix b/nixpkgs/nixos/modules/services/games/crossfire-server.nix
index 0849667e61c9..b19a86253cb4 100644
--- a/nixpkgs/nixos/modules/services/games/crossfire-server.nix
+++ b/nixpkgs/nixos/modules/services/games/crossfire-server.nix
@@ -15,13 +15,11 @@ in {
       '';
     };
 
-    package = mkOption {
-      type = types.package;
-      default = pkgs.crossfire-server;
-      defaultText = literalExpression "pkgs.crossfire-server";
-      description = lib.mdDoc ''
-        The package to use for the Crossfire server (and map/arch data, if you
-        don't change dataDir).
+    package = mkPackageOption pkgs "crossfire-server" {
+      extraDescription = ''
+        ::: {.note}
+        This will also be used for map/arch data, if you don't change {option}`dataDir`
+        :::
       '';
     };
 
diff --git a/nixpkgs/nixos/modules/services/games/deliantra-server.nix b/nixpkgs/nixos/modules/services/games/deliantra-server.nix
index f39044eda7c7..b405f338fe3d 100644
--- a/nixpkgs/nixos/modules/services/games/deliantra-server.nix
+++ b/nixpkgs/nixos/modules/services/games/deliantra-server.nix
@@ -15,13 +15,11 @@ in {
       '';
     };
 
-    package = mkOption {
-      type = types.package;
-      default = pkgs.deliantra-server;
-      defaultText = literalExpression "pkgs.deliantra-server";
-      description = lib.mdDoc ''
-        The package to use for the Deliantra server (and map/arch data, if you
-        don't change dataDir).
+    package = mkPackageOption pkgs "deliantra-server" {
+      extraDescription = ''
+        ::: {.note}
+        This will also be used for map/arch data, if you don't change {option}`dataDir`
+        :::
       '';
     };
 
diff --git a/nixpkgs/nixos/modules/services/games/factorio.nix b/nixpkgs/nixos/modules/services/games/factorio.nix
index b349ffa2375f..14bb80c2d112 100644
--- a/nixpkgs/nixos/modules/services/games/factorio.nix
+++ b/nixpkgs/nixos/modules/services/games/factorio.nix
@@ -37,7 +37,8 @@ let
     autosave_only_on_server = true;
     non_blocking_saving = cfg.nonBlockingSaving;
   } // cfg.extraSettings;
-  serverSettingsFile = pkgs.writeText "server-settings.json" (builtins.toJSON (filterAttrsRecursive (n: v: v != null) serverSettings));
+  serverSettingsString = builtins.toJSON (filterAttrsRecursive (n: v: v != null) serverSettings);
+  serverSettingsFile = pkgs.writeText "server-settings.json" serverSettingsString;
   serverAdminsFile = pkgs.writeText "server-adminlist.json" (builtins.toJSON cfg.admins);
   modDir = pkgs.factorio-utils.mkModDirDrv cfg.mods cfg.mods-dat;
 in
@@ -115,6 +116,23 @@ in
           customizations.
         '';
       };
+      extraSettingsFile = mkOption {
+        type = types.nullOr types.path;
+        default = null;
+        description = lib.mdDoc ''
+          File, which is dynamically applied to server-settings.json before
+          startup.
+
+          This option should be used for credentials.
+
+          For example a settings file could contain:
+          ```json
+          {
+            "game-password": "hunter1"
+          }
+          ```
+        '';
+      };
       stateDirName = mkOption {
         type = types.str;
         default = "factorio";
@@ -186,22 +204,20 @@ in
         default = null;
         description = lib.mdDoc ''
           Your factorio.com login credentials. Required for games with visibility public.
+
+          This option is insecure. Use extraSettingsFile instead.
         '';
       };
-      package = mkOption {
-        type = types.package;
-        default = pkgs.factorio-headless;
-        defaultText = literalExpression "pkgs.factorio-headless";
-        example = literalExpression "pkgs.factorio-headless-experimental";
-        description = lib.mdDoc ''
-          Factorio version to use. This defaults to the stable channel.
-        '';
+      package = mkPackageOption pkgs "factorio-headless" {
+        example = "factorio-headless-experimental";
       };
       password = mkOption {
         type = types.nullOr types.str;
         default = null;
         description = lib.mdDoc ''
           Your factorio.com login credentials. Required for games with visibility public.
+
+          This option is insecure. Use extraSettingsFile instead.
         '';
       };
       token = mkOption {
@@ -216,6 +232,8 @@ in
         default = null;
         description = lib.mdDoc ''
           Game password.
+
+          This option is insecure. Use extraSettingsFile instead.
         '';
       };
       requireUserVerification = mkOption {
@@ -251,14 +269,18 @@ in
       wantedBy      = [ "multi-user.target" ];
       after         = [ "network.target" ];
 
-      preStart = toString [
-        "test -e ${stateDir}/saves/${cfg.saveName}.zip"
-        "||"
-        "${cfg.package}/bin/factorio"
+      preStart =
+        (toString [
+          "test -e ${stateDir}/saves/${cfg.saveName}.zip"
+          "||"
+          "${cfg.package}/bin/factorio"
           "--config=${cfg.configFile}"
           "--create=${mkSavePath cfg.saveName}"
           (optionalString (cfg.mods != []) "--mod-directory=${modDir}")
-      ];
+        ])
+        + (optionalString (cfg.extraSettingsFile != null) ("\necho ${lib.strings.escapeShellArg serverSettingsString}"
+          + " \"$(cat ${cfg.extraSettingsFile})\" | ${lib.getExe pkgs.jq} -s add"
+          + " > ${stateDir}/server-settings.json"));
 
       serviceConfig = {
         Restart = "always";
@@ -272,7 +294,11 @@ in
           "--port=${toString cfg.port}"
           "--bind=${cfg.bind}"
           (optionalString (!cfg.loadLatestSave) "--start-server=${mkSavePath cfg.saveName}")
-          "--server-settings=${serverSettingsFile}"
+          "--server-settings=${
+            if (cfg.extraSettingsFile != null)
+            then "${stateDir}/server-settings.json"
+            else serverSettingsFile
+          }"
           (optionalString cfg.loadLatestSave "--start-server-load-latest")
           (optionalString (cfg.mods != []) "--mod-directory=${modDir}")
           (optionalString (cfg.admins != []) "--server-adminlist=${serverAdminsFile}")
diff --git a/nixpkgs/nixos/modules/services/games/mchprs.nix b/nixpkgs/nixos/modules/services/games/mchprs.nix
index a65001b0b3e2..71e546049c58 100644
--- a/nixpkgs/nixos/modules/services/games/mchprs.nix
+++ b/nixpkgs/nixos/modules/services/games/mchprs.nix
@@ -73,12 +73,7 @@ in
         '';
       };
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.mchprs;
-        defaultText = literalExpression "pkgs.mchprs";
-        description = mdDoc "Version of MCHPRS to run.";
-      };
+      package = mkPackageOption pkgs "mchprs" { };
 
       settings = mkOption {
         type = types.submodule {
diff --git a/nixpkgs/nixos/modules/services/games/minecraft-server.nix b/nixpkgs/nixos/modules/services/games/minecraft-server.nix
index 77f92ab97db7..116fc533dfd8 100644
--- a/nixpkgs/nixos/modules/services/games/minecraft-server.nix
+++ b/nixpkgs/nixos/modules/services/games/minecraft-server.nix
@@ -150,12 +150,8 @@ in {
         '';
       };
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.minecraft-server;
-        defaultText = literalExpression "pkgs.minecraft-server";
-        example = literalExpression "pkgs.minecraft-server_1_12_2";
-        description = lib.mdDoc "Version of minecraft-server to run.";
+      package = mkPackageOption pkgs "minecraft-server" {
+        example = "minecraft-server_1_12_2";
       };
 
       jvmOpts = mkOption {
diff --git a/nixpkgs/nixos/modules/services/games/openarena.nix b/nixpkgs/nixos/modules/services/games/openarena.nix
index 8f6d4986903f..14e485b06a0d 100644
--- a/nixpkgs/nixos/modules/services/games/openarena.nix
+++ b/nixpkgs/nixos/modules/services/games/openarena.nix
@@ -8,7 +8,7 @@ in
   options = {
     services.openarena = {
       enable = mkEnableOption (lib.mdDoc "OpenArena");
-      package = lib.mkPackageOptionMD pkgs "openarena" { };
+      package = lib.mkPackageOption pkgs "openarena" { };
 
       openPorts = mkOption {
         type = types.bool;
diff --git a/nixpkgs/nixos/modules/services/games/quake3-server.nix b/nixpkgs/nixos/modules/services/games/quake3-server.nix
index e51830c12e78..41688d56173b 100644
--- a/nixpkgs/nixos/modules/services/games/quake3-server.nix
+++ b/nixpkgs/nixos/modules/services/games/quake3-server.nix
@@ -41,7 +41,7 @@ in {
   options = {
     services.quake3-server = {
       enable = mkEnableOption (lib.mdDoc "Quake 3 dedicated server");
-      package = lib.mkPackageOptionMD pkgs "ioquake3" { };
+      package = lib.mkPackageOption pkgs "ioquake3" { };
 
       port = mkOption {
         type = types.port;
diff --git a/nixpkgs/nixos/modules/services/hardware/auto-epp.nix b/nixpkgs/nixos/modules/services/hardware/auto-epp.nix
new file mode 100644
index 000000000000..84b6a337d28a
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/hardware/auto-epp.nix
@@ -0,0 +1,80 @@
+{ config, lib, pkgs, ... }:
+
+let
+  cfg = config.services.auto-epp;
+  format = pkgs.formats.ini {};
+
+  inherit (lib) mkOption types;
+in {
+  options = {
+    services.auto-epp = {
+      enable = lib.mkEnableOption (lib.mdDoc "auto-epp for amd active pstate");
+
+      package = lib.mkPackageOptionMD pkgs "auto-epp" {};
+
+      settings = mkOption {
+        type = types.submodule {
+          freeformType = format.type;
+          options = {
+            Settings = {
+              epp_state_for_AC = mkOption {
+                type = types.str;
+                default = "balance_performance";
+                description = lib.mdDoc ''
+                  energy_performance_preference when on plugged in
+
+                  ::: {.note}
+                  See available epp states by running:
+                  {command}`cat /sys/devices/system/cpu/cpu0/cpufreq/energy_performance_available_preferences`
+                  :::
+                '';
+              };
+
+              epp_state_for_BAT = mkOption {
+                type = types.str;
+                default = "power";
+                description = lib.mdDoc ''
+                  `energy_performance_preference` when on battery
+
+                  ::: {.note}
+                  See available epp states by running:
+                  {command}`cat /sys/devices/system/cpu/cpu0/cpufreq/energy_performance_available_preferences`
+                  :::
+                '';
+              };
+            };
+          };
+        };
+        default = {};
+        description = lib.mdDoc ''
+          Settings for the auto-epp application.
+          See upstream example: <https://github.com/jothi-prasath/auto-epp/blob/master/sample-auto-epp.conf>
+        '';
+      };
+    };
+  };
+
+  config = lib.mkIf cfg.enable {
+
+    boot.kernelParams = [
+      "amd_pstate=active"
+    ];
+
+    environment.etc."auto-epp.conf".source = format.generate "auto-epp.conf" cfg.settings;
+    systemd.packages = [ cfg.package ];
+
+    systemd.services.auto-epp = {
+      after = [ "multi-user.target" ];
+      wantedBy  = [ "multi-user.target" ];
+      description = "auto-epp - Automatic EPP Changer for amd-pstate-epp";
+      serviceConfig = {
+        Type = "simple";
+        User = "root";
+        ExecStart = lib.getExe cfg.package;
+        Restart = "on-failure";
+      };
+    };
+  };
+
+  meta.maintainers = with lib.maintainers; [ lamarios ];
+}
diff --git a/nixpkgs/nixos/modules/services/hardware/bluetooth.nix b/nixpkgs/nixos/modules/services/hardware/bluetooth.nix
index 2a58be51bb02..51ec12f96537 100644
--- a/nixpkgs/nixos/modules/services/hardware/bluetooth.nix
+++ b/nixpkgs/nixos/modules/services/hardware/bluetooth.nix
@@ -4,7 +4,7 @@ let
   package = cfg.package;
 
   inherit (lib)
-    mkDefault mkEnableOption mkIf mkOption
+    mkDefault mkEnableOption mkIf mkOption mkPackageOption
     mkRenamedOptionModule mkRemovedOptionModule
     concatStringsSep escapeShellArgs literalExpression
     optional optionals optionalAttrs recursiveUpdate types;
@@ -46,14 +46,7 @@ in
         description = lib.mdDoc "Whether to power up the default Bluetooth controller on boot.";
       };
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.bluez;
-        defaultText = literalExpression "pkgs.bluez";
-        description = lib.mdDoc ''
-          Which BlueZ package to use.
-        '';
-      };
+      package = mkPackageOption pkgs "bluez" { };
 
       disabledPlugins = mkOption {
         type = types.listOf types.str;
diff --git a/nixpkgs/nixos/modules/services/hardware/freefall.nix b/nixpkgs/nixos/modules/services/hardware/freefall.nix
index 7b794264ff35..2985739bc2df 100644
--- a/nixpkgs/nixos/modules/services/hardware/freefall.nix
+++ b/nixpkgs/nixos/modules/services/hardware/freefall.nix
@@ -18,14 +18,7 @@ in {
       '';
     };
 
-    package = mkOption {
-      type = types.package;
-      default = pkgs.freefall;
-      defaultText = literalExpression "pkgs.freefall";
-      description = lib.mdDoc ''
-        freefall derivation to use.
-      '';
-    };
+    package = mkPackageOption pkgs "freefall" { };
 
     devices = mkOption {
       type = types.listOf types.str;
diff --git a/nixpkgs/nixos/modules/services/hardware/fwupd.nix b/nixpkgs/nixos/modules/services/hardware/fwupd.nix
index 7b6c336bd221..6b3a109ed6f7 100644
--- a/nixpkgs/nixos/modules/services/hardware/fwupd.nix
+++ b/nixpkgs/nixos/modules/services/hardware/fwupd.nix
@@ -94,14 +94,7 @@ in {
         '';
       };
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.fwupd;
-        defaultText = literalExpression "pkgs.fwupd";
-        description = lib.mdDoc ''
-          Which fwupd package to use.
-        '';
-      };
+      package = mkPackageOption pkgs "fwupd" { };
 
       daemonSettings = mkOption {
         type = types.submodule {
diff --git a/nixpkgs/nixos/modules/services/hardware/joycond.nix b/nixpkgs/nixos/modules/services/hardware/joycond.nix
index df3239cb2a7d..060303b520e5 100644
--- a/nixpkgs/nixos/modules/services/hardware/joycond.nix
+++ b/nixpkgs/nixos/modules/services/hardware/joycond.nix
@@ -10,14 +10,7 @@ with lib;
   options.services.joycond = {
     enable = mkEnableOption (lib.mdDoc "support for Nintendo Pro Controllers and Joycons");
 
-    package = mkOption {
-      type = types.package;
-      default = pkgs.joycond;
-      defaultText = lib.literalExpression "pkgs.joycond";
-      description = lib.mdDoc ''
-        The joycond package to use.
-      '';
-    };
+    package = mkPackageOption pkgs "joycond" { };
   };
 
   config = mkIf cfg.enable {
diff --git a/nixpkgs/nixos/modules/services/hardware/kanata.nix b/nixpkgs/nixos/modules/services/hardware/kanata.nix
index aac20c6c760e..0b77bfbc33b3 100644
--- a/nixpkgs/nixos/modules/services/hardware/kanata.nix
+++ b/nixpkgs/nixos/modules/services/hardware/kanata.nix
@@ -146,16 +146,11 @@ in
 {
   options.services.kanata = {
     enable = mkEnableOption (mdDoc "kanata");
-    package = mkOption {
-      type = types.package;
-      default = pkgs.kanata;
-      defaultText = literalExpression "pkgs.kanata";
-      example = literalExpression "pkgs.kanata-with-cmd";
-      description = mdDoc ''
-        The kanata package to use.
-
+    package = mkPackageOption pkgs "kanata" {
+      example = "kanata-with-cmd";
+      extraDescription = ''
         ::: {.note}
-        If `danger-enable-cmd` is enabled in any of the keyboards, the
+        If {option}`danger-enable-cmd` is enabled in any of the keyboards, the
         `kanata-with-cmd` package should be used.
         :::
       '';
diff --git a/nixpkgs/nixos/modules/services/hardware/openrgb.nix b/nixpkgs/nixos/modules/services/hardware/openrgb.nix
index 13b1d07e53b7..81b199e50778 100644
--- a/nixpkgs/nixos/modules/services/hardware/openrgb.nix
+++ b/nixpkgs/nixos/modules/services/hardware/openrgb.nix
@@ -8,12 +8,7 @@ in {
   options.services.hardware.openrgb = {
     enable = mkEnableOption (lib.mdDoc "OpenRGB server");
 
-    package = mkOption {
-      type = types.package;
-      default = pkgs.openrgb;
-      defaultText = literalMD "pkgs.openrgb";
-      description = lib.mdDoc "Set version of openrgb package to use.";
-    };
+    package = mkPackageOption pkgs "openrgb" { };
 
     motherboard = mkOption {
       type = types.nullOr (types.enum [ "amd" "intel" ]);
diff --git a/nixpkgs/nixos/modules/services/hardware/sane.nix b/nixpkgs/nixos/modules/services/hardware/sane.nix
index 2cac2e8e8bb4..8408844c4f94 100644
--- a/nixpkgs/nixos/modules/services/hardware/sane.nix
+++ b/nixpkgs/nixos/modules/services/hardware/sane.nix
@@ -114,14 +114,11 @@ in
       '';
     };
 
-    hardware.sane.drivers.scanSnap.package = mkOption {
-      type = types.package;
-      default = pkgs.sane-drivers.epjitsu;
-      defaultText = literalExpression "pkgs.sane-drivers.epjitsu";
-      description = lib.mdDoc ''
-        Epjitsu driver package to use. Useful if you want to extract the driver files yourself.
+    hardware.sane.drivers.scanSnap.package = mkPackageOption pkgs [ "sane-drivers" "epjitsu" ] {
+      extraDescription = ''
+        Useful if you want to extract the driver files yourself.
 
-        The process is described in the `/etc/sane.d/epjitsu.conf` file in
+        The process is described in the {file}`/etc/sane.d/epjitsu.conf` file in
         the `sane-backends` package.
       '';
     };
diff --git a/nixpkgs/nixos/modules/services/hardware/thermald.nix b/nixpkgs/nixos/modules/services/hardware/thermald.nix
index 6b694ede5885..7ae602823cd6 100644
--- a/nixpkgs/nixos/modules/services/hardware/thermald.nix
+++ b/nixpkgs/nixos/modules/services/hardware/thermald.nix
@@ -25,12 +25,7 @@ in
         description = lib.mdDoc "the thermald manual configuration file.";
       };
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.thermald;
-        defaultText = literalExpression "pkgs.thermald";
-        description = lib.mdDoc "Which thermald package to use.";
-      };
+      package = mkPackageOption pkgs "thermald" { };
     };
   };
 
diff --git a/nixpkgs/nixos/modules/services/hardware/undervolt.nix b/nixpkgs/nixos/modules/services/hardware/undervolt.nix
index 258f09bbab09..67d8171587bb 100644
--- a/nixpkgs/nixos/modules/services/hardware/undervolt.nix
+++ b/nixpkgs/nixos/modules/services/hardware/undervolt.nix
@@ -47,14 +47,7 @@ in
       '';
     };
 
-    package = mkOption {
-      type = types.package;
-      default = pkgs.undervolt;
-      defaultText = literalExpression "pkgs.undervolt";
-      description = lib.mdDoc ''
-        undervolt derivation to use.
-      '';
-    };
+    package = mkPackageOption pkgs "undervolt" { };
 
     coreOffset = mkOption {
       type = types.nullOr types.int;
diff --git a/nixpkgs/nixos/modules/services/hardware/upower.nix b/nixpkgs/nixos/modules/services/hardware/upower.nix
index aacc8a63dbeb..0ae31d99aa86 100644
--- a/nixpkgs/nixos/modules/services/hardware/upower.nix
+++ b/nixpkgs/nixos/modules/services/hardware/upower.nix
@@ -27,14 +27,7 @@ in
         '';
       };
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.upower;
-        defaultText = literalExpression "pkgs.upower";
-        description = lib.mdDoc ''
-          Which upower package to use.
-        '';
-      };
+      package = mkPackageOption pkgs "upower" { };
 
       enableWattsUpPro = mkOption {
         type = types.bool;
diff --git a/nixpkgs/nixos/modules/services/hardware/usbmuxd.nix b/nixpkgs/nixos/modules/services/hardware/usbmuxd.nix
index 9466ea26995b..d05ad3af8b12 100644
--- a/nixpkgs/nixos/modules/services/hardware/usbmuxd.nix
+++ b/nixpkgs/nixos/modules/services/hardware/usbmuxd.nix
@@ -77,7 +77,7 @@ in
       serviceConfig = {
         # Trigger the udev rule manually. This doesn't require replugging the
         # device when first enabling the option to get it to work
-        ExecStartPre = "${pkgs.udev}/bin/udevadm trigger -s usb -a idVendor=${apple}";
+        ExecStartPre = "${config.systemd.package}/bin/udevadm trigger -s usb -a idVendor=${apple}";
         ExecStart = "${cfg.package}/bin/usbmuxd -U ${cfg.user} -v";
       };
     };
diff --git a/nixpkgs/nixos/modules/services/hardware/vdr.nix b/nixpkgs/nixos/modules/services/hardware/vdr.nix
index de63ed893b02..afa64fa16c4a 100644
--- a/nixpkgs/nixos/modules/services/hardware/vdr.nix
+++ b/nixpkgs/nixos/modules/services/hardware/vdr.nix
@@ -14,12 +14,8 @@ in {
     services.vdr = {
       enable = mkEnableOption (lib.mdDoc "VDR. Please put config into ${libDir}");
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.vdr;
-        defaultText = literalExpression "pkgs.vdr";
-        example = literalExpression "pkgs.wrapVdr.override { plugins = with pkgs.vdrPlugins; [ hello ]; }";
-        description = lib.mdDoc "Package to use.";
+      package = mkPackageOption pkgs "vdr" {
+        example = "wrapVdr.override { plugins = with pkgs.vdrPlugins; [ hello ]; }";
       };
 
       videoDir = mkOption {
diff --git a/nixpkgs/nixos/modules/services/home-automation/esphome.nix b/nixpkgs/nixos/modules/services/home-automation/esphome.nix
index 080c8876382f..4fc007a97683 100644
--- a/nixpkgs/nixos/modules/services/home-automation/esphome.nix
+++ b/nixpkgs/nixos/modules/services/home-automation/esphome.nix
@@ -26,12 +26,7 @@ in
   options.services.esphome = {
     enable = mkEnableOption (mdDoc "esphome");
 
-    package = mkOption {
-      type = types.package;
-      default = pkgs.esphome;
-      defaultText = literalExpression "pkgs.esphome";
-      description = mdDoc "The package to use for the esphome command.";
-    };
+    package = lib.mkPackageOption pkgs "esphome" { };
 
     enableUnixSocket = mkOption {
       type = types.bool;
@@ -107,10 +102,10 @@ in
         ProtectClock = true;
         ProtectControlGroups = true;
         ProtectHome = true;
-        ProtectHostname = true;
-        ProtectKernelLogs = true;
+        ProtectHostname = false; # breaks bwrap
+        ProtectKernelLogs = false; # breaks bwrap
         ProtectKernelModules = true;
-        ProtectKernelTunables = true;
+        ProtectKernelTunables = false; # breaks bwrap
         ProtectProc = "invisible";
         ProcSubset = "all"; # Using "pid" breaks bwrap
         ProtectSystem = "strict";
diff --git a/nixpkgs/nixos/modules/services/home-automation/homeassistant-satellite.nix b/nixpkgs/nixos/modules/services/home-automation/homeassistant-satellite.nix
index e3f0617cf01c..6ca428f2af81 100644
--- a/nixpkgs/nixos/modules/services/home-automation/homeassistant-satellite.nix
+++ b/nixpkgs/nixos/modules/services/home-automation/homeassistant-satellite.nix
@@ -14,7 +14,7 @@ let
     mdDoc
     mkEnableOption
     mkIf
-    mkPackageOptionMD
+    mkPackageOption
     types
     ;
 
@@ -38,7 +38,7 @@ in
   options.services.homeassistant-satellite = with types; {
     enable = mkEnableOption (mdDoc "Home Assistant Satellite");
 
-    package = mkPackageOptionMD pkgs "homeassistant-satellite" { };
+    package = mkPackageOption pkgs "homeassistant-satellite" { };
 
     user = mkOption {
       type = str;
diff --git a/nixpkgs/nixos/modules/services/home-automation/zigbee2mqtt.nix b/nixpkgs/nixos/modules/services/home-automation/zigbee2mqtt.nix
index 6b5bd8a0d9bb..a653e49a09f6 100644
--- a/nixpkgs/nixos/modules/services/home-automation/zigbee2mqtt.nix
+++ b/nixpkgs/nixos/modules/services/home-automation/zigbee2mqtt.nix
@@ -20,14 +20,7 @@ in
   options.services.zigbee2mqtt = {
     enable = mkEnableOption (lib.mdDoc "zigbee2mqtt service");
 
-    package = mkOption {
-      description = lib.mdDoc "Zigbee2mqtt package to use";
-      default = pkgs.zigbee2mqtt;
-      defaultText = literalExpression ''
-        pkgs.zigbee2mqtt
-      '';
-      type = types.package;
-    };
+    package = mkPackageOption pkgs "zigbee2mqtt" { };
 
     dataDir = mkOption {
       description = lib.mdDoc "Zigbee2mqtt data directory";
diff --git a/nixpkgs/nixos/modules/services/home-automation/zwave-js.nix b/nixpkgs/nixos/modules/services/home-automation/zwave-js.nix
index 87c9b8f1ac81..9821da7ef6ed 100644
--- a/nixpkgs/nixos/modules/services/home-automation/zwave-js.nix
+++ b/nixpkgs/nixos/modules/services/home-automation/zwave-js.nix
@@ -10,7 +10,7 @@ in {
   options.services.zwave-js = {
     enable = mkEnableOption (mdDoc "the zwave-js server on boot");
 
-    package = mkPackageOptionMD pkgs "zwave-js-server" { };
+    package = mkPackageOption pkgs "zwave-js-server" { };
 
     port = mkOption {
       type = types.port;
diff --git a/nixpkgs/nixos/modules/services/logging/SystemdJournal2Gelf.nix b/nixpkgs/nixos/modules/services/logging/SystemdJournal2Gelf.nix
index 3d85c2b62c63..429dde33b521 100644
--- a/nixpkgs/nixos/modules/services/logging/SystemdJournal2Gelf.nix
+++ b/nixpkgs/nixos/modules/services/logging/SystemdJournal2Gelf.nix
@@ -33,14 +33,7 @@ in
         '';
       };
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.systemd-journal2gelf;
-        defaultText = literalExpression "pkgs.systemd-journal2gelf";
-        description = lib.mdDoc ''
-          SystemdJournal2Gelf package to use.
-        '';
-      };
+      package = mkPackageOption pkgs "systemd-journal2gelf" { };
 
     };
   };
diff --git a/nixpkgs/nixos/modules/services/logging/filebeat.nix b/nixpkgs/nixos/modules/services/logging/filebeat.nix
index 5b5e7fd5ae89..071e001eb3c5 100644
--- a/nixpkgs/nixos/modules/services/logging/filebeat.nix
+++ b/nixpkgs/nixos/modules/services/logging/filebeat.nix
@@ -5,6 +5,7 @@ let
     attrValues
     literalExpression
     mkEnableOption
+    mkPackageOption
     mkIf
     mkOption
     types;
@@ -20,14 +21,8 @@ in
 
       enable = mkEnableOption (lib.mdDoc "filebeat");
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.filebeat;
-        defaultText = literalExpression "pkgs.filebeat";
-        example = literalExpression "pkgs.filebeat7";
-        description = lib.mdDoc ''
-          The filebeat package to use.
-        '';
+      package = mkPackageOption pkgs "filebeat" {
+        example = "filebeat7";
       };
 
       inputs = mkOption {
diff --git a/nixpkgs/nixos/modules/services/logging/fluentd.nix b/nixpkgs/nixos/modules/services/logging/fluentd.nix
index 7764aafb2d1a..c8718f26db38 100644
--- a/nixpkgs/nixos/modules/services/logging/fluentd.nix
+++ b/nixpkgs/nixos/modules/services/logging/fluentd.nix
@@ -20,12 +20,7 @@ in {
         description = lib.mdDoc "Fluentd config.";
       };
 
-      package = mkOption {
-        type = types.path;
-        default = pkgs.fluentd;
-        defaultText = literalExpression "pkgs.fluentd";
-        description = lib.mdDoc "The fluentd package to use.";
-      };
+      package = mkPackageOption pkgs "fluentd" { };
 
       plugins = mkOption {
         type = types.listOf types.path;
diff --git a/nixpkgs/nixos/modules/services/logging/heartbeat.nix b/nixpkgs/nixos/modules/services/logging/heartbeat.nix
index a9ae11ec66e6..768ffe5315fe 100644
--- a/nixpkgs/nixos/modules/services/logging/heartbeat.nix
+++ b/nixpkgs/nixos/modules/services/logging/heartbeat.nix
@@ -20,14 +20,8 @@ in
 
       enable = mkEnableOption (lib.mdDoc "heartbeat");
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.heartbeat;
-        defaultText = literalExpression "pkgs.heartbeat";
-        example = literalExpression "pkgs.heartbeat7";
-        description = lib.mdDoc ''
-          The heartbeat package to use.
-        '';
+      package = mkPackageOption pkgs "heartbeat" {
+        example = "heartbeat7";
       };
 
       name = mkOption {
diff --git a/nixpkgs/nixos/modules/services/logging/journalbeat.nix b/nixpkgs/nixos/modules/services/logging/journalbeat.nix
index e761380552de..80933d6a0f96 100644
--- a/nixpkgs/nixos/modules/services/logging/journalbeat.nix
+++ b/nixpkgs/nixos/modules/services/logging/journalbeat.nix
@@ -20,14 +20,7 @@ in
 
       enable = mkEnableOption (lib.mdDoc "journalbeat");
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.journalbeat;
-        defaultText = literalExpression "pkgs.journalbeat";
-        description = lib.mdDoc ''
-          The journalbeat package to use
-        '';
-      };
+      package = mkPackageOption pkgs "journalbeat" { };
 
       name = mkOption {
         type = types.str;
diff --git a/nixpkgs/nixos/modules/services/logging/logstash.nix b/nixpkgs/nixos/modules/services/logging/logstash.nix
index 42d52a61639e..22292dbd931b 100644
--- a/nixpkgs/nixos/modules/services/logging/logstash.nix
+++ b/nixpkgs/nixos/modules/services/logging/logstash.nix
@@ -54,12 +54,7 @@ in
         description = lib.mdDoc "Enable logstash.";
       };
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.logstash;
-        defaultText = literalExpression "pkgs.logstash";
-        description = lib.mdDoc "Logstash package to use.";
-      };
+      package = mkPackageOption pkgs "logstash" { };
 
       plugins = mkOption {
         type = types.listOf types.path;
diff --git a/nixpkgs/nixos/modules/services/logging/syslog-ng.nix b/nixpkgs/nixos/modules/services/logging/syslog-ng.nix
index 48d556b9459e..eea236263f7e 100644
--- a/nixpkgs/nixos/modules/services/logging/syslog-ng.nix
+++ b/nixpkgs/nixos/modules/services/logging/syslog-ng.nix
@@ -40,14 +40,7 @@ in {
           Whether to enable the syslog-ng daemon.
         '';
       };
-      package = mkOption {
-        type = types.package;
-        default = pkgs.syslogng;
-        defaultText = literalExpression "pkgs.syslogng";
-        description = lib.mdDoc ''
-          The package providing syslog-ng binaries.
-        '';
-      };
+      package = mkPackageOption pkgs "syslogng" { };
       extraModulePaths = mkOption {
         type = types.listOf types.str;
         default = [];
diff --git a/nixpkgs/nixos/modules/services/logging/vector.nix b/nixpkgs/nixos/modules/services/logging/vector.nix
index f2edeabfc06f..48f9eeb4ce8f 100644
--- a/nixpkgs/nixos/modules/services/logging/vector.nix
+++ b/nixpkgs/nixos/modules/services/logging/vector.nix
@@ -8,7 +8,7 @@ in
   options.services.vector = {
     enable = mkEnableOption (lib.mdDoc "Vector");
 
-    package = mkPackageOptionMD pkgs "vector" { };
+    package = mkPackageOption pkgs "vector" { };
 
     journaldAccess = mkOption {
       type = types.bool;
diff --git a/nixpkgs/nixos/modules/services/mail/exim.nix b/nixpkgs/nixos/modules/services/mail/exim.nix
index 1d1258913b67..63d3fa54b23d 100644
--- a/nixpkgs/nixos/modules/services/mail/exim.nix
+++ b/nixpkgs/nixos/modules/services/mail/exim.nix
@@ -1,7 +1,7 @@
 { config, lib, pkgs, ... }:
 
 let
-  inherit (lib) literalExpression mkIf mkOption singleton types;
+  inherit (lib) literalExpression mkIf mkOption singleton types mkPackageOption;
   inherit (pkgs) coreutils;
   cfg = config.services.exim;
 in
@@ -57,12 +57,8 @@ in
         '';
       };
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.exim;
-        defaultText = literalExpression "pkgs.exim";
-        description = lib.mdDoc ''
-          The Exim derivation to use.
+      package = mkPackageOption pkgs "exim" {
+        extraDescription = ''
           This can be used to enable features such as LDAP or PAM support.
         '';
       };
diff --git a/nixpkgs/nixos/modules/services/mail/listmonk.nix b/nixpkgs/nixos/modules/services/mail/listmonk.nix
index cea1bc956081..be2f9680ca5a 100644
--- a/nixpkgs/nixos/modules/services/mail/listmonk.nix
+++ b/nixpkgs/nixos/modules/services/mail/listmonk.nix
@@ -128,7 +128,7 @@ in {
           '';
         };
       };
-      package = mkPackageOptionMD pkgs "listmonk" {};
+      package = mkPackageOption pkgs "listmonk" {};
       settings = mkOption {
         type = types.submodule { freeformType = tomlFormat.type; };
         description = lib.mdDoc ''
diff --git a/nixpkgs/nixos/modules/services/mail/offlineimap.nix b/nixpkgs/nixos/modules/services/mail/offlineimap.nix
index 64fa09e83612..0166ec4e8d4e 100644
--- a/nixpkgs/nixos/modules/services/mail/offlineimap.nix
+++ b/nixpkgs/nixos/modules/services/mail/offlineimap.nix
@@ -22,12 +22,7 @@ in {
       '';
     };
 
-    package = mkOption {
-      type = types.package;
-      default = pkgs.offlineimap;
-      defaultText = literalExpression "pkgs.offlineimap";
-      description = lib.mdDoc "Offlineimap derivation to use.";
-    };
+    package = mkPackageOption pkgs "offlineimap" { };
 
     path = mkOption {
       type = types.listOf types.path;
diff --git a/nixpkgs/nixos/modules/services/mail/opensmtpd.nix b/nixpkgs/nixos/modules/services/mail/opensmtpd.nix
index 6ad3386d2d4e..a65c8e05a9ce 100644
--- a/nixpkgs/nixos/modules/services/mail/opensmtpd.nix
+++ b/nixpkgs/nixos/modules/services/mail/opensmtpd.nix
@@ -31,12 +31,7 @@ in {
         description = lib.mdDoc "Whether to enable the OpenSMTPD server.";
       };
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.opensmtpd;
-        defaultText = literalExpression "pkgs.opensmtpd";
-        description = lib.mdDoc "The OpenSMTPD package to use.";
-      };
+      package = mkPackageOption pkgs "opensmtpd" { };
 
       setSendmail = mkOption {
         type = types.bool;
diff --git a/nixpkgs/nixos/modules/services/mail/public-inbox.nix b/nixpkgs/nixos/modules/services/mail/public-inbox.nix
index 0464b7164149..8b129b223761 100644
--- a/nixpkgs/nixos/modules/services/mail/public-inbox.nix
+++ b/nixpkgs/nixos/modules/services/mail/public-inbox.nix
@@ -144,12 +144,7 @@ in
 {
   options.services.public-inbox = {
     enable = mkEnableOption (lib.mdDoc "the public-inbox mail archiver");
-    package = mkOption {
-      type = types.package;
-      default = pkgs.public-inbox;
-      defaultText = literalExpression "pkgs.public-inbox";
-      description = lib.mdDoc "public-inbox package to use.";
-    };
+    package = mkPackageOption pkgs "public-inbox" { };
     path = mkOption {
       type = with types; listOf package;
       default = [];
diff --git a/nixpkgs/nixos/modules/services/mail/roundcube.nix b/nixpkgs/nixos/modules/services/mail/roundcube.nix
index 4e29f567ed92..c35ece8362f6 100644
--- a/nixpkgs/nixos/modules/services/mail/roundcube.nix
+++ b/nixpkgs/nixos/modules/services/mail/roundcube.nix
@@ -29,19 +29,8 @@ in
       description = lib.mdDoc "Hostname to use for the nginx vhost";
     };
 
-    package = mkOption {
-      type = types.package;
-      default = pkgs.roundcube;
-      defaultText = literalExpression "pkgs.roundcube";
-
-      example = literalExpression ''
-        roundcube.withPlugins (plugins: [ plugins.persistent_login ])
-      '';
-
-      description = lib.mdDoc ''
-        The package which contains roundcube's sources. Can be overridden to create
-        an environment which contains roundcube and third-party plugins.
-      '';
+    package = mkPackageOption pkgs "roundcube" {
+      example = "roundcube.withPlugins (plugins: [ plugins.persistent_login ])";
     };
 
     database = {
@@ -131,7 +120,7 @@ in
       ${lib.optionalString (!localDB) ''
         $password = file('${cfg.database.passwordFile}')[0];
         $password = preg_split('~\\\\.(*SKIP)(*FAIL)|\:~s', $password);
-        $password = end($password);
+        $password = rtrim(end($password));
         $password = str_replace("\\:", ":", $password);
         $password = str_replace("\\\\", "\\", $password);
       ''}
diff --git a/nixpkgs/nixos/modules/services/mail/stalwart-mail.nix b/nixpkgs/nixos/modules/services/mail/stalwart-mail.nix
index eb87d9f6f695..f576a426b318 100644
--- a/nixpkgs/nixos/modules/services/mail/stalwart-mail.nix
+++ b/nixpkgs/nixos/modules/services/mail/stalwart-mail.nix
@@ -11,7 +11,7 @@ let
 in {
   options.services.stalwart-mail = {
     enable = mkEnableOption (mdDoc "the Stalwart all-in-one email server");
-    package = mkPackageOptionMD pkgs "stalwart-mail" { };
+    package = mkPackageOption pkgs "stalwart-mail" { };
 
     settings = mkOption {
       inherit (configFormat) type;
diff --git a/nixpkgs/nixos/modules/services/matrix/appservice-discord.nix b/nixpkgs/nixos/modules/services/matrix/appservice-discord.nix
index 6ce8718c35d8..c2c3abb79f97 100644
--- a/nixpkgs/nixos/modules/services/matrix/appservice-discord.nix
+++ b/nixpkgs/nixos/modules/services/matrix/appservice-discord.nix
@@ -15,14 +15,7 @@ in {
     services.matrix-appservice-discord = {
       enable = mkEnableOption (lib.mdDoc "a bridge between Matrix and Discord");
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.matrix-appservice-discord;
-        defaultText = literalExpression "pkgs.matrix-appservice-discord";
-        description = lib.mdDoc ''
-          Which package of matrix-appservice-discord to use.
-        '';
-      };
+      package = mkPackageOption pkgs "matrix-appservice-discord" { };
 
       settings = mkOption rec {
         # TODO: switch to types.config.json as prescribed by RFC42 once it's implemented
diff --git a/nixpkgs/nixos/modules/services/matrix/conduit.nix b/nixpkgs/nixos/modules/services/matrix/conduit.nix
index 76af7ba22857..b0fc85dbda7b 100644
--- a/nixpkgs/nixos/modules/services/matrix/conduit.nix
+++ b/nixpkgs/nixos/modules/services/matrix/conduit.nix
@@ -20,14 +20,7 @@ in
         example = { RUST_BACKTRACE="yes"; };
       };
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.matrix-conduit;
-        defaultText = lib.literalExpression "pkgs.matrix-conduit";
-        description = lib.mdDoc ''
-          Package of the conduit matrix server to use.
-        '';
-      };
+      package = mkPackageOption pkgs "matrix-conduit" { };
 
       settings = mkOption {
         type = types.submodule {
diff --git a/nixpkgs/nixos/modules/services/matrix/matrix-sliding-sync.nix b/nixpkgs/nixos/modules/services/matrix/matrix-sliding-sync.nix
index 84bb38f35aeb..295be0c6bf16 100644
--- a/nixpkgs/nixos/modules/services/matrix/matrix-sliding-sync.nix
+++ b/nixpkgs/nixos/modules/services/matrix/matrix-sliding-sync.nix
@@ -7,7 +7,7 @@ in
   options.services.matrix-synapse.sliding-sync = {
     enable = lib.mkEnableOption (lib.mdDoc "sliding sync");
 
-    package = lib.mkPackageOptionMD pkgs "matrix-sliding-sync" { };
+    package = lib.mkPackageOption pkgs "matrix-sliding-sync" { };
 
     settings = lib.mkOption {
       type = lib.types.submodule {
diff --git a/nixpkgs/nixos/modules/services/matrix/maubot.md b/nixpkgs/nixos/modules/services/matrix/maubot.md
new file mode 100644
index 000000000000..f6a05db56caf
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/matrix/maubot.md
@@ -0,0 +1,103 @@
+# Maubot {#module-services-maubot}
+
+[Maubot](https://github.com/maubot/maubot) is a plugin-based bot
+framework for Matrix.
+
+## Configuration {#module-services-maubot-configuration}
+
+1. Set [](#opt-services.maubot.enable) to `true`. The service will use
+   SQLite by default.
+2. If you want to use PostgreSQL instead of SQLite, do this:
+
+   ```nix
+   services.maubot.settings.database = "postgresql://maubot@localhost/maubot";
+   ```
+
+   If the PostgreSQL connection requires a password, you will have to
+   add it later on step 8.
+3. If you plan to expose your Maubot interface to the web, do something
+   like this:
+   ```nix
+   services.nginx.virtualHosts."matrix.example.org".locations = {
+     "/_matrix/maubot/" = {
+       proxyPass = "http://127.0.0.1:${toString config.services.maubot.settings.server.port}";
+       proxyWebsockets = true;
+     };
+   };
+   services.maubot.settings.server.public_url = "matrix.example.org";
+   # do the following only if you want to use something other than /_matrix/maubot...
+   services.maubot.settings.server.ui_base_path = "/another/base/path";
+   ```
+4. Optionally, set `services.maubot.pythonPackages` to a list of python3
+   packages to make available for Maubot plugins.
+5. Optionally, set `services.maubot.plugins` to a list of Maubot
+   plugins (full list available at https://plugins.maubot.xyz/):
+   ```nix
+   services.maubot.plugins = with config.services.maubot.package.plugins; [
+     reactbot
+     # This will only change the default config! After you create a
+     # plugin instance, the default config will be copied into that
+     # instance's config in Maubot's database, and further base config
+     # changes won't affect the running plugin.
+     (rss.override {
+       base_config = {
+         update_interval = 60;
+         max_backoff = 7200;
+         spam_sleep = 2;
+         command_prefix = "rss";
+         admins = [ "@chayleaf:pavluk.org" ];
+       };
+     })
+   ];
+   # ...or...
+   services.maubot.plugins = config.services.maubot.package.plugins.allOfficialPlugins;
+   # ...or...
+   services.maubot.plugins = config.services.maubot.package.plugins.allPlugins;
+   # ...or...
+   services.maubot.plugins = with config.services.maubot.package.plugins; [
+     (weather.override {
+       # you can pass base_config as a string
+       base_config = ''
+         default_location: New York
+         default_units: M
+         default_language:
+         show_link: true
+         show_image: false
+       '';
+     })
+   ];
+   ```
+6. Start Maubot at least once before doing the following steps (it's
+   necessary to generate the initial config).
+7. If your PostgreSQL connection requires a password, add
+   `database: postgresql://user:password@localhost/maubot`
+   to `/var/lib/maubot/config.yaml`. This overrides the Nix-provided
+   config. Even then, don't remove the `database` line from Nix config
+   so the module knows you use PostgreSQL!
+8. To create a user account for logging into Maubot web UI and
+   configuring it, generate a password using the shell command
+   `mkpasswd -R 12 -m bcrypt`, and edit `/var/lib/maubot/config.yaml`
+   with the following:
+
+   ```yaml
+   admins:
+       admin_username: $2b$12$g.oIStUeUCvI58ebYoVMtO/vb9QZJo81PsmVOomHiNCFbh0dJpZVa
+   ```
+
+   Where `admin_username` is your username, and `$2b...` is the bcrypted
+   password.
+9. Optional: if you want to be able to register new users with the
+   Maubot CLI (`mbc`), and your homeserver is private, add your
+   homeserver's registration key to `/var/lib/maubot/config.yaml`:
+
+   ```yaml
+   homeservers:
+       matrix.example.org:
+           url: https://matrix.example.org
+           secret: your-very-secret-key
+   ```
+10. Restart Maubot after editing `/var/lib/maubot/config.yaml`,and
+    Maubot will be available at
+    `https://matrix.example.org/_matrix/maubot`. If you want to use the
+    `mbc` CLI, it's available using the `maubot` package (`nix-shell -p
+    maubot`).
diff --git a/nixpkgs/nixos/modules/services/matrix/maubot.nix b/nixpkgs/nixos/modules/services/matrix/maubot.nix
new file mode 100644
index 000000000000..7d392c22983b
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/matrix/maubot.nix
@@ -0,0 +1,459 @@
+{ lib
+, config
+, pkgs
+, ...
+}:
+
+let
+  cfg = config.services.maubot;
+
+  wrapper1 =
+    if cfg.plugins == [ ]
+    then cfg.package
+    else cfg.package.withPlugins (_: cfg.plugins);
+
+  wrapper2 =
+    if cfg.pythonPackages == [ ]
+    then wrapper1
+    else wrapper1.withPythonPackages (_: cfg.pythonPackages);
+
+  settings = lib.recursiveUpdate cfg.settings {
+    plugin_directories.trash =
+      if cfg.settings.plugin_directories.trash == null
+      then "delete"
+      else cfg.settings.plugin_directories.trash;
+    server.unshared_secret = "generate";
+  };
+
+  finalPackage = wrapper2.withBaseConfig settings;
+
+  isPostgresql = db: builtins.isString db && lib.hasPrefix "postgresql://" db;
+  isLocalPostgresDB = db: isPostgresql db && builtins.any (x: lib.hasInfix x db) [
+    "@127.0.0.1/"
+    "@::1/"
+    "@[::1]/"
+    "@localhost/"
+  ];
+  parsePostgresDB = db:
+    let
+      noSchema = lib.removePrefix "postgresql://" db;
+    in {
+      username = builtins.head (lib.splitString "@" noSchema);
+      database = lib.last (lib.splitString "/" noSchema);
+    };
+
+  postgresDBs = [
+    cfg.settings.database
+    cfg.settings.crypto_database
+    cfg.settings.plugin_databases.postgres
+  ];
+
+  localPostgresDBs = builtins.filter isLocalPostgresDB postgresDBs;
+
+  parsedLocalPostgresDBs = map parsePostgresDB localPostgresDBs;
+  parsedPostgresDBs = map parsePostgresDB postgresDBs;
+
+  hasLocalPostgresDB = localPostgresDBs != [ ];
+in
+{
+  options.services.maubot = with lib; {
+    enable = mkEnableOption (mdDoc "maubot");
+
+    package = lib.mkPackageOption pkgs "maubot" { };
+
+    plugins = mkOption {
+      type = types.listOf types.package;
+      default = [ ];
+      example = literalExpression ''
+        with config.services.maubot.package.plugins; [
+          xyz.maubot.reactbot
+          xyz.maubot.rss
+        ];
+      '';
+      description = mdDoc ''
+        List of additional maubot plugins to make available.
+      '';
+    };
+
+    pythonPackages = mkOption {
+      type = types.listOf types.package;
+      default = [ ];
+      example = literalExpression ''
+        with pkgs.python3Packages; [
+          aiohttp
+        ];
+      '';
+      description = mdDoc ''
+        List of additional Python packages to make available for maubot.
+      '';
+    };
+
+    dataDir = mkOption {
+      type = types.str;
+      default = "/var/lib/maubot";
+      description = mdDoc ''
+        The directory where maubot stores its stateful data.
+      '';
+    };
+
+    extraConfigFile = mkOption {
+      type = types.str;
+      default = "./config.yaml";
+      defaultText = literalExpression ''"''${config.services.maubot.dataDir}/config.yaml"'';
+      description = mdDoc ''
+        A file for storing secrets. You can pass homeserver registration keys here.
+        If it already exists, **it must contain `server.unshared_secret`** which is used for signing API keys.
+        If `configMutable` is not set to true, **maubot user must have write access to this file**.
+      '';
+    };
+
+    configMutable = mkOption {
+      type = types.bool;
+      default = false;
+      description = mdDoc ''
+        Whether maubot should write updated config into `extraConfigFile`. **This will make your Nix module settings have no effect besides the initial config, as extraConfigFile takes precedence over NixOS settings!**
+      '';
+    };
+
+    settings = mkOption {
+      default = { };
+      description = mdDoc ''
+        YAML settings for maubot. See the
+        [example configuration](https://github.com/maubot/maubot/blob/master/maubot/example-config.yaml)
+        for more info.
+
+        Secrets should be passed in by using `extraConfigFile`.
+      '';
+      type = with types; submodule {
+        options = {
+          database = mkOption {
+            type = str;
+            default = "sqlite:maubot.db";
+            example = "postgresql://username:password@hostname/dbname";
+            description = mdDoc ''
+              The full URI to the database. SQLite and Postgres are fully supported.
+              Other DBMSes supported by SQLAlchemy may or may not work.
+            '';
+          };
+
+          crypto_database = mkOption {
+            type = str;
+            default = "default";
+            example = "postgresql://username:password@hostname/dbname";
+            description = mdDoc ''
+              Separate database URL for the crypto database. By default, the regular database is also used for crypto.
+            '';
+          };
+
+          database_opts = mkOption {
+            type = types.attrs;
+            default = { };
+            description = mdDoc ''
+              Additional arguments for asyncpg.create_pool() or sqlite3.connect()
+            '';
+          };
+
+          plugin_directories = mkOption {
+            default = { };
+            description = mdDoc "Plugin directory paths";
+            type = submodule {
+              options = {
+                upload = mkOption {
+                  type = types.str;
+                  default = "./plugins";
+                  defaultText = literalExpression ''"''${config.services.maubot.dataDir}/plugins"'';
+                  description = mdDoc ''
+                    The directory where uploaded new plugins should be stored.
+                  '';
+                };
+                load = mkOption {
+                  type = types.listOf types.str;
+                  default = [ "./plugins" ];
+                  defaultText = literalExpression ''[ "''${config.services.maubot.dataDir}/plugins" ]'';
+                  description = mdDoc ''
+                    The directories from which plugins should be loaded. Duplicate plugin IDs will be moved to the trash.
+                  '';
+                };
+                trash = mkOption {
+                  type = with types; nullOr str;
+                  default = "./trash";
+                  defaultText = literalExpression ''"''${config.services.maubot.dataDir}/trash"'';
+                  description = mdDoc ''
+                    The directory where old plugin versions and conflicting plugins should be moved. Set to null to delete files immediately.
+                  '';
+                };
+              };
+            };
+          };
+
+          plugin_databases = mkOption {
+            description = mdDoc "Plugin database settings";
+            default = { };
+            type = submodule {
+              options = {
+                sqlite = mkOption {
+                  type = types.str;
+                  default = "./plugins";
+                  defaultText = literalExpression ''"''${config.services.maubot.dataDir}/plugins"'';
+                  description = mdDoc ''
+                    The directory where SQLite plugin databases should be stored.
+                  '';
+                };
+
+                postgres = mkOption {
+                  type = types.nullOr types.str;
+                  default = if isPostgresql cfg.settings.database then "default" else null;
+                  defaultText = literalExpression ''if isPostgresql config.services.maubot.settings.database then "default" else null'';
+                  description = mdDoc ''
+                    The connection URL for plugin database. See [example config](https://github.com/maubot/maubot/blob/master/maubot/example-config.yaml) for exact format.
+                  '';
+                };
+
+                postgres_max_conns_per_plugin = mkOption {
+                  type = types.nullOr types.int;
+                  default = 3;
+                  description = mdDoc ''
+                    Maximum number of connections per plugin instance.
+                  '';
+                };
+
+                postgres_opts = mkOption {
+                  type = types.attrs;
+                  default = { };
+                  description = mdDoc ''
+                    Overrides for the default database_opts when using a non-default postgres connection URL.
+                  '';
+                };
+              };
+            };
+          };
+
+          server = mkOption {
+            default = { };
+            description = mdDoc "Listener config";
+            type = submodule {
+              options = {
+                hostname = mkOption {
+                  type = types.str;
+                  default = "127.0.0.1";
+                  description = mdDoc ''
+                    The IP to listen on
+                  '';
+                };
+                port = mkOption {
+                  type = types.port;
+                  default = 29316;
+                  description = mdDoc ''
+                    The port to listen on
+                  '';
+                };
+                public_url = mkOption {
+                  type = types.str;
+                  default = "http://${cfg.settings.server.hostname}:${toString cfg.settings.server.port}";
+                  defaultText = literalExpression ''"http://''${config.services.maubot.settings.server.hostname}:''${toString config.services.maubot.settings.server.port}"'';
+                  description = mdDoc ''
+                    Public base URL where the server is visible.
+                  '';
+                };
+                ui_base_path = mkOption {
+                  type = types.str;
+                  default = "/_matrix/maubot";
+                  description = mdDoc ''
+                    The base path for the UI.
+                  '';
+                };
+                plugin_base_path = mkOption {
+                  type = types.str;
+                  default = "${config.services.maubot.settings.server.ui_base_path}/plugin/";
+                  defaultText = literalExpression ''
+                    "''${config.services.maubot.settings.server.ui_base_path}/plugin/"
+                  '';
+                  description = mdDoc ''
+                    The base path for plugin endpoints. The instance ID will be appended directly.
+                  '';
+                };
+                override_resource_path = mkOption {
+                  type = types.nullOr types.str;
+                  default = null;
+                  description = mdDoc ''
+                    Override path from where to load UI resources.
+                  '';
+                };
+              };
+            };
+          };
+
+          homeservers = mkOption {
+            type = types.attrsOf (types.submodule {
+              options = {
+                url = mkOption {
+                  type = types.str;
+                  description = mdDoc ''
+                    Client-server API URL
+                  '';
+                };
+              };
+            });
+            default = {
+              "matrix.org" = {
+                url = "https://matrix-client.matrix.org";
+              };
+            };
+            description = mdDoc ''
+              Known homeservers. This is required for the `mbc auth` command and also allows more convenient access from the management UI.
+              If you want to specify registration secrets, pass this via extraConfigFile instead.
+            '';
+          };
+
+          admins = mkOption {
+            type = types.attrsOf types.str;
+            default = { root = ""; };
+            description = mdDoc ''
+              List of administrator users. Plaintext passwords will be bcrypted on startup. Set empty password
+              to prevent normal login. Root is a special user that can't have a password and will always exist.
+            '';
+          };
+
+          api_features = mkOption {
+            type = types.attrsOf bool;
+            default = {
+              login = true;
+              plugin = true;
+              plugin_upload = true;
+              instance = true;
+              instance_database = true;
+              client = true;
+              client_proxy = true;
+              client_auth = true;
+              dev_open = true;
+              log = true;
+            };
+            description = mdDoc ''
+              API feature switches.
+            '';
+          };
+
+          logging = mkOption {
+            type = types.attrs;
+            description = mdDoc ''
+              Python logging configuration. See [section 16.7.2 of the Python
+              documentation](https://docs.python.org/3.6/library/logging.config.html#configuration-dictionary-schema)
+              for more info.
+            '';
+            default = {
+              version = 1;
+              formatters = {
+                colored = {
+                  "()" = "maubot.lib.color_log.ColorFormatter";
+                  format = "[%(asctime)s] [%(levelname)s@%(name)s] %(message)s";
+                };
+                normal = {
+                  format = "[%(asctime)s] [%(levelname)s@%(name)s] %(message)s";
+                };
+              };
+              handlers = {
+                file = {
+                  class = "logging.handlers.RotatingFileHandler";
+                  formatter = "normal";
+                  filename = "./maubot.log";
+                  maxBytes = 10485760;
+                  backupCount = 10;
+                };
+                console = {
+                  class = "logging.StreamHandler";
+                  formatter = "colored";
+                };
+              };
+              loggers = {
+                maubot = {
+                  level = "DEBUG";
+                };
+                mau = {
+                  level = "DEBUG";
+                };
+                aiohttp = {
+                  level = "INFO";
+                };
+              };
+              root = {
+                level = "DEBUG";
+                handlers = [ "file" "console" ];
+              };
+            };
+          };
+        };
+      };
+    };
+  };
+
+  config = lib.mkIf cfg.enable {
+    warnings = lib.optional (builtins.any (x: x.username != x.database) parsedLocalPostgresDBs) ''
+      The Maubot database username doesn't match the database name! This means the user won't be automatically
+      granted ownership of the database. Consider changing either the username or the database name.
+    '';
+    assertions = [
+      {
+        assertion = builtins.all (x: !lib.hasInfix ":" x.username) parsedPostgresDBs;
+        message = ''
+          Putting database passwords in your Nix config makes them world-readable. To securely put passwords
+          in your Maubot config, change /var/lib/maubot/config.yaml after running Maubot at least once as
+          described in the NixOS manual.
+        '';
+      }
+      {
+        assertion = hasLocalPostgresDB -> config.services.postgresql.enable;
+        message = ''
+          Cannot deploy maubot with a configuration for a local postgresql database and a missing postgresql service.
+        '';
+      }
+    ];
+
+    services.postgresql = lib.mkIf hasLocalPostgresDB {
+      enable = true;
+      ensureDatabases = map (x: x.database) parsedLocalPostgresDBs;
+      ensureUsers = lib.flip map parsedLocalPostgresDBs (x: {
+        name = x.username;
+        ensureDBOwnership = lib.mkIf (x.username == x.database) true;
+      });
+    };
+
+    users.users.maubot = {
+      group = "maubot";
+      home = cfg.dataDir;
+      # otherwise StateDirectory is enough
+      createHome = lib.mkIf (cfg.dataDir != "/var/lib/maubot") true;
+      isSystemUser = true;
+    };
+
+    users.groups.maubot = { };
+
+    systemd.services.maubot = rec {
+      description = "maubot - a plugin-based Matrix bot system written in Python";
+      after = [ "network.target" ] ++ wants ++ lib.optional hasLocalPostgresDB "postgresql.service";
+      # all plugins get automatically disabled if maubot starts before synapse
+      wants = lib.optional config.services.matrix-synapse.enable config.services.matrix-synapse.serviceUnit;
+      wantedBy = [ "multi-user.target" ];
+
+      preStart = ''
+        if [ ! -f "${cfg.extraConfigFile}" ]; then
+          echo "server:" > "${cfg.extraConfigFile}"
+          echo "    unshared_secret: $(head -c40 /dev/random | base32 | ${pkgs.gawk}/bin/awk '{print tolower($0)}')" > "${cfg.extraConfigFile}"
+          chmod 640 "${cfg.extraConfigFile}"
+        fi
+      '';
+
+      serviceConfig = {
+        ExecStart = "${finalPackage}/bin/maubot --config ${cfg.extraConfigFile}" + lib.optionalString (!cfg.configMutable) " --no-update";
+        User = "maubot";
+        Group = "maubot";
+        Restart = "on-failure";
+        RestartSec = "10s";
+        StateDirectory = lib.mkIf (cfg.dataDir == "/var/lib/maubot") "maubot";
+        WorkingDirectory = cfg.dataDir;
+      };
+    };
+  };
+
+  meta.maintainers = with lib.maintainers; [ chayleaf ];
+  meta.doc = ./maubot.md;
+}
diff --git a/nixpkgs/nixos/modules/services/misc/airsonic.nix b/nixpkgs/nixos/modules/services/misc/airsonic.nix
index b8e9dcaf4663..6ba6ff5ca3cb 100644
--- a/nixpkgs/nixos/modules/services/misc/airsonic.nix
+++ b/nixpkgs/nixos/modules/services/misc/airsonic.nix
@@ -85,15 +85,12 @@ in {
         '';
       };
 
-      jre = mkOption {
-        type = types.package;
-        default = pkgs.jre8;
-        defaultText = literalExpression "pkgs.jre8";
-        description = lib.mdDoc ''
-          JRE package to use.
-
+      jre = mkPackageOption pkgs "jre8" {
+        extraDescription = ''
+          ::: {.note}
           Airsonic only supports Java 8, airsonic-advanced requires at least
           Java 11.
+          :::
         '';
       };
 
diff --git a/nixpkgs/nixos/modules/services/misc/amazon-ssm-agent.nix b/nixpkgs/nixos/modules/services/misc/amazon-ssm-agent.nix
index 02e44c73d87a..20b836abe164 100644
--- a/nixpkgs/nixos/modules/services/misc/amazon-ssm-agent.nix
+++ b/nixpkgs/nixos/modules/services/misc/amazon-ssm-agent.nix
@@ -15,6 +15,11 @@ let
       -r) echo "${config.system.nixos.version}";;
     esac
   '';
+
+  sudoRule = {
+    users = [ "ssm-user" ];
+    commands = [ { command = "ALL"; options = [ "NOPASSWD" ]; } ];
+  };
 in {
   imports = [
     (mkRenamedOptionModule [ "services" "ssm-agent" "enable" ] [ "services" "amazon-ssm-agent" "enable" ])
@@ -54,17 +59,9 @@ in {
 
     # Add user that Session Manager needs, and give it sudo.
     # This is consistent with Amazon Linux 2 images.
-    security.sudo.extraRules = [
-      {
-        users = [ "ssm-user" ];
-        commands = [
-          {
-            command = "ALL";
-            options = [ "NOPASSWD" ];
-          }
-        ];
-      }
-    ];
+    security.sudo.extraRules = [ sudoRule ];
+    security.sudo-rs.extraRules = [ sudoRule ];
+
     # On Amazon Linux 2 images, the ssm-user user is pretty much a
     # normal user with its own group. We do the same.
     users.groups.ssm-user = {};
diff --git a/nixpkgs/nixos/modules/services/misc/ananicy.nix b/nixpkgs/nixos/modules/services/misc/ananicy.nix
index bc1b28efc0ba..01e1053c9e0e 100644
--- a/nixpkgs/nixos/modules/services/misc/ananicy.nix
+++ b/nixpkgs/nixos/modules/services/misc/ananicy.nix
@@ -15,21 +15,13 @@ in
     services.ananicy = {
       enable = mkEnableOption (lib.mdDoc "Ananicy, an auto nice daemon");
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.ananicy;
-        defaultText = literalExpression "pkgs.ananicy";
-        example = literalExpression "pkgs.ananicy-cpp";
-        description = lib.mdDoc ''
-          Which ananicy package to use.
-        '';
+      package = mkPackageOption pkgs "ananicy" {
+        example = "ananicy-cpp";
       };
 
-      rulesProvider = mkOption {
-        type = types.package;
-        default = pkgs.ananicy;
-        defaultText = literalExpression "pkgs.ananicy";
-        example = literalExpression "pkgs.ananicy-cpp";
+      rulesProvider = mkPackageOption pkgs "ananicy" {
+        example = "ananicy-cpp";
+      } // {
         description = lib.mdDoc ''
           Which package to copy default rules,types,cgroups from.
         '';
diff --git a/nixpkgs/nixos/modules/services/misc/anki-sync-server.md b/nixpkgs/nixos/modules/services/misc/anki-sync-server.md
new file mode 100644
index 000000000000..5d2b4da4d2fc
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/misc/anki-sync-server.md
@@ -0,0 +1,68 @@
+# Anki Sync Server {#module-services-anki-sync-server}
+
+[Anki Sync Server](https://docs.ankiweb.net/sync-server.html) is the built-in
+sync server, present in recent versions of Anki. Advanced users who cannot or
+do not wish to use AnkiWeb can use this sync server instead of AnkiWeb.
+
+This module is compatible only with Anki versions >=2.1.66, due to [recent
+enhancements to the Nix anki
+package](https://github.com/NixOS/nixpkgs/commit/05727304f8815825565c944d012f20a9a096838a).
+
+## Basic Usage {#module-services-anki-sync-server-basic-usage}
+
+By default, the module creates a
+[`systemd`](https://www.freedesktop.org/wiki/Software/systemd/)
+unit which runs the sync server with an isolated user using the systemd
+`DynamicUser` option.
+
+This can be done by enabling the `anki-sync-server` service:
+```
+{ ... }:
+
+{
+  services.anki-sync-server.enable = true;
+}
+```
+
+It is necessary to set at least one username-password pair under
+{option}`services.anki-sync-server.users`. For example
+
+```
+{
+  services.anki-sync-server.users = [
+    {
+      username = "user";
+      passwordFile = /etc/anki-sync-server/user;
+    }
+  ];
+}
+```
+
+Here, `passwordFile` is the path to a file containing just the password in
+plaintext. Make sure to set permissions to make this file unreadable to any
+user besides root.
+
+By default, the server listen address {option}`services.anki-sync-server.host`
+is set to localhost, listening on port
+{option}`services.anki-sync-server.port`, and does not open the firewall. This
+is suitable for purely local testing, or to be used behind a reverse proxy. If
+you want to expose the sync server directly to other computers (not recommended
+in most circumstances, because the sync server doesn't use HTTPS), then set the
+following options:
+
+```
+{
+  services.anki-sync-server.host = "0.0.0.0";
+  services.anki-sync-server.openFirewall = true;
+}
+```
+
+
+## Alternatives {#module-services-anki-sync-server-alternatives}
+
+The [`ankisyncd` NixOS
+module](https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/services/misc/ankisyncd.nix)
+provides similar functionality, but using a third-party implementation,
+[`anki-sync-server-rs`](https://github.com/ankicommunity/anki-sync-server-rs/).
+According to that project's README, it is "no longer maintained", and not
+recommended for Anki 2.1.64+.
diff --git a/nixpkgs/nixos/modules/services/misc/anki-sync-server.nix b/nixpkgs/nixos/modules/services/misc/anki-sync-server.nix
new file mode 100644
index 000000000000..a65382009417
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/misc/anki-sync-server.nix
@@ -0,0 +1,140 @@
+{
+  config,
+  lib,
+  pkgs,
+  ...
+}:
+with lib; let
+  cfg = config.services.anki-sync-server;
+  name = "anki-sync-server";
+  specEscape = replaceStrings ["%"] ["%%"];
+  usersWithIndexes =
+    lists.imap1 (i: user: {
+      i = i;
+      user = user;
+    })
+    cfg.users;
+  usersWithIndexesFile = filter (x: x.user.passwordFile != null) usersWithIndexes;
+  usersWithIndexesNoFile = filter (x: x.user.passwordFile == null && x.user.password != null) usersWithIndexes;
+  anki-sync-server-run = pkgs.writeShellScriptBin "anki-sync-server-run" ''
+    # When services.anki-sync-server.users.passwordFile is set,
+    # each password file is passed as a systemd credential, which is mounted in
+    # a file system exposed to the service. Here we read the passwords from
+    # the credential files to pass them as environment variables to the Anki
+    # sync server.
+    ${
+      concatMapStringsSep
+      "\n"
+      (x: ''export SYNC_USER${toString x.i}=${escapeShellArg x.user.username}:"''$(cat "''${CREDENTIALS_DIRECTORY}/"${escapeShellArg x.user.username})"'')
+      usersWithIndexesFile
+    }
+    # For users where services.anki-sync-server.users.password isn't set,
+    # export passwords in environment variables in plaintext.
+    ${
+      concatMapStringsSep
+      "\n"
+      (x: ''export SYNC_USER${toString x.i}=${escapeShellArg x.user.username}:${escapeShellArg x.user.password}'')
+      usersWithIndexesNoFile
+    }
+    exec ${cfg.package}/bin/anki-sync-server
+  '';
+in {
+  options.services.anki-sync-server = {
+    enable = mkEnableOption "anki-sync-server";
+
+    package = mkPackageOption pkgs "anki-sync-server" { };
+
+    address = mkOption {
+      type = types.str;
+      default = "::1";
+      description = ''
+        IP address anki-sync-server listens to.
+        Note host names are not resolved.
+      '';
+    };
+
+    port = mkOption {
+      type = types.port;
+      default = 27701;
+      description = "Port number anki-sync-server listens to.";
+    };
+
+    openFirewall = mkOption {
+      default = false;
+      type = types.bool;
+      description = "Whether to open the firewall for the specified port.";
+    };
+
+    users = mkOption {
+      type = with types;
+        listOf (submodule {
+          options = {
+            username = mkOption {
+              type = str;
+              description = "User name accepted by anki-sync-server.";
+            };
+            password = mkOption {
+              type = nullOr str;
+              default = null;
+              description = ''
+                Password accepted by anki-sync-server for the associated username.
+                **WARNING**: This option is **not secure**. This password will
+                be stored in *plaintext* and will be visible to *all users*.
+                See {option}`services.anki-sync-server.users.passwordFile` for
+                a more secure option.
+              '';
+            };
+            passwordFile = mkOption {
+              type = nullOr path;
+              default = null;
+              description = ''
+                File containing the password accepted by anki-sync-server for
+                the associated username.  Make sure to make readable only by
+                root.
+              '';
+            };
+          };
+        });
+      description = "List of user-password pairs to provide to the sync server.";
+    };
+  };
+
+  config = mkIf cfg.enable {
+    assertions = [
+      {
+        assertion = (builtins.length usersWithIndexesFile) + (builtins.length usersWithIndexesNoFile) > 0;
+        message = "At least one username-password pair must be set.";
+      }
+    ];
+    networking.firewall.allowedTCPPorts = mkIf cfg.openFirewall [cfg.port];
+
+    systemd.services.anki-sync-server = {
+      description = "anki-sync-server: Anki sync server built into Anki";
+      after = ["network.target"];
+      wantedBy = ["multi-user.target"];
+      path = [cfg.package];
+      environment = {
+        SYNC_BASE = "%S/%N";
+        SYNC_HOST = specEscape cfg.address;
+        SYNC_PORT = toString cfg.port;
+      };
+
+      serviceConfig = {
+        Type = "simple";
+        DynamicUser = true;
+        StateDirectory = name;
+        ExecStart = "${anki-sync-server-run}/bin/anki-sync-server-run";
+        Restart = "always";
+        LoadCredential =
+          map
+          (x: "${specEscape x.user.username}:${specEscape (toString x.user.passwordFile)}")
+          usersWithIndexesFile;
+      };
+    };
+  };
+
+  meta = {
+    maintainers = with maintainers; [telotortium];
+    doc = ./anki-sync-server.md;
+  };
+}
diff --git a/nixpkgs/nixos/modules/services/misc/ankisyncd.nix b/nixpkgs/nixos/modules/services/misc/ankisyncd.nix
index 7be8dc7dab8f..e4de46e19a8f 100644
--- a/nixpkgs/nixos/modules/services/misc/ankisyncd.nix
+++ b/nixpkgs/nixos/modules/services/misc/ankisyncd.nix
@@ -24,12 +24,7 @@ in
     options.services.ankisyncd = {
       enable = mkEnableOption (lib.mdDoc "ankisyncd");
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.ankisyncd;
-        defaultText = literalExpression "pkgs.ankisyncd";
-        description = lib.mdDoc "The package to use for the ankisyncd command.";
-      };
+      package = mkPackageOption pkgs "ankisyncd" { };
 
       host = mkOption {
         type = types.str;
diff --git a/nixpkgs/nixos/modules/services/misc/apache-kafka.nix b/nixpkgs/nixos/modules/services/misc/apache-kafka.nix
index 598907aaf1c6..b7281a0d9d5f 100644
--- a/nixpkgs/nixos/modules/services/misc/apache-kafka.nix
+++ b/nixpkgs/nixos/modules/services/misc/apache-kafka.nix
@@ -5,75 +5,117 @@ with lib;
 let
   cfg = config.services.apache-kafka;
 
-  serverProperties =
-    if cfg.serverProperties != null then
-      cfg.serverProperties
-    else
-      ''
-        # Generated by nixos
-        broker.id=${toString cfg.brokerId}
-        port=${toString cfg.port}
-        host.name=${cfg.hostname}
-        log.dirs=${concatStringsSep "," cfg.logDirs}
-        zookeeper.connect=${cfg.zookeeper}
-        ${toString cfg.extraProperties}
-      '';
+  # The `javaProperties` generator takes care of various escaping rules and
+  # generation of the properties file, but we'll handle stringly conversion
+  # ourselves in mkPropertySettings and stringlySettings, since we know more
+  # about the specifically allowed format eg. for lists of this type, and we
+  # don't want to coerce-downsample values to str too early by having the
+  # coercedTypes from javaProperties directly in our NixOS option types.
+  #
+  # Make sure every `freeformType` and any specific option type in `settings` is
+  # supported here.
+
+  mkPropertyString = let
+    render = {
+      bool = boolToString;
+      int = toString;
+      list = concatMapStringsSep "," mkPropertyString;
+      string = id;
+    };
+  in
+    v: render.${builtins.typeOf v} v;
 
-  serverConfig = pkgs.writeText "server.properties" serverProperties;
-  logConfig = pkgs.writeText "log4j.properties" cfg.log4jProperties;
+  stringlySettings = mapAttrs (_: mkPropertyString)
+    (filterAttrs (_: v:  v != null) cfg.settings);
 
+  generator = (pkgs.formats.javaProperties {}).generate;
 in {
 
   options.services.apache-kafka = {
-    enable = mkOption {
-      description = lib.mdDoc "Whether to enable Apache Kafka.";
-      default = false;
-      type = types.bool;
-    };
-
-    brokerId = mkOption {
-      description = lib.mdDoc "Broker ID.";
-      default = -1;
-      type = types.int;
-    };
+    enable = mkEnableOption (lib.mdDoc "Apache Kafka event streaming broker");
 
-    port = mkOption {
-      description = lib.mdDoc "Port number the broker should listen on.";
-      default = 9092;
-      type = types.port;
+    settings = mkOption {
+      description = lib.mdDoc ''
+        [Kafka broker configuration](https://kafka.apache.org/documentation.html#brokerconfigs)
+        {file}`server.properties`.
+
+        Note that .properties files contain mappings from string to string.
+        Keys with dots are NOT represented by nested attrs in these settings,
+        but instead as quoted strings (ie. `settings."broker.id"`, NOT
+        `settings.broker.id`).
+     '';
+      type = types.submodule {
+        freeformType = with types; let
+          primitive = oneOf [bool int str];
+        in lazyAttrsOf (nullOr (either primitive (listOf primitive)));
+
+        options = {
+          "broker.id" = mkOption {
+            description = lib.mdDoc "Broker ID. -1 or null to auto-allocate in zookeeper mode.";
+            default = null;
+            type = with types; nullOr int;
+          };
+
+          "log.dirs" = mkOption {
+            description = lib.mdDoc "Log file directories.";
+            # Deliberaly leave out old default and use the rewrite opportunity
+            # to have users choose a safer value -- /tmp might be volatile and is a
+            # slightly scary default choice.
+            # default = [ "/tmp/apache-kafka" ];
+            type = with types; listOf path;
+          };
+
+          "listeners" = mkOption {
+            description = lib.mdDoc ''
+              Kafka Listener List.
+              See [listeners](https://kafka.apache.org/documentation/#brokerconfigs_listeners).
+            '';
+            type = types.listOf types.str;
+            default = [ "PLAINTEXT://localhost:9092" ];
+          };
+        };
+      };
     };
 
-    hostname = mkOption {
-      description = lib.mdDoc "Hostname the broker should bind to.";
-      default = "localhost";
-      type = types.str;
+    clusterId = mkOption {
+      description = lib.mdDoc ''
+        KRaft mode ClusterId used for formatting log directories. Can be generated with `kafka-storage.sh random-uuid`
+      '';
+      type = with types; nullOr str;
+      default = null;
     };
 
-    logDirs = mkOption {
-      description = lib.mdDoc "Log file directories";
-      default = [ "/tmp/kafka-logs" ];
-      type = types.listOf types.path;
+    configFiles.serverProperties = mkOption {
+      description = lib.mdDoc ''
+        Kafka server.properties configuration file path.
+        Defaults to the rendered `settings`.
+      '';
+      type = types.path;
     };
 
-    zookeeper = mkOption {
-      description = lib.mdDoc "Zookeeper connection string";
-      default = "localhost:2181";
-      type = types.str;
+    configFiles.log4jProperties = mkOption {
+      description = lib.mdDoc "Kafka log4j property configuration file path";
+      type = types.path;
+      default = pkgs.writeText "log4j.properties" cfg.log4jProperties;
+      defaultText = ''pkgs.writeText "log4j.properties" cfg.log4jProperties'';
     };
 
-    extraProperties = mkOption {
-      description = lib.mdDoc "Extra properties for server.properties.";
-      type = types.nullOr types.lines;
-      default = null;
+    formatLogDirs = mkOption {
+      description = lib.mdDoc ''
+        Whether to format log dirs in KRaft mode if all log dirs are
+        unformatted, ie. they contain no meta.properties.
+      '';
+      type = types.bool;
+      default = false;
     };
 
-    serverProperties = mkOption {
+    formatLogDirsIgnoreFormatted = mkOption {
       description = lib.mdDoc ''
-        Complete server.properties content. Other server.properties config
-        options will be ignored if this option is used.
+        Whether to ignore already formatted log dirs when formatting log dirs,
+        instead of failing. Useful when replacing or adding disks.
       '';
-      type = types.nullOr types.lines;
-      default = null;
+      type = types.bool;
+      default = false;
     };
 
     log4jProperties = mkOption {
@@ -99,12 +141,7 @@ in {
       ];
     };
 
-    package = mkOption {
-      description = lib.mdDoc "The kafka package to use";
-      default = pkgs.apacheKafka;
-      defaultText = literalExpression "pkgs.apacheKafka";
-      type = types.package;
-    };
+    package = mkPackageOption pkgs "apacheKafka" { };
 
     jre = mkOption {
       description = lib.mdDoc "The JRE with which to run Kafka";
@@ -112,40 +149,70 @@ in {
       defaultText = literalExpression "pkgs.apacheKafka.passthru.jre";
       type = types.package;
     };
-
   };
 
-  config = mkIf cfg.enable {
+  imports = [
+    (mkRenamedOptionModule
+      [ "services" "apache-kafka" "brokerId" ]
+      [ "services" "apache-kafka" "settings" ''broker.id'' ])
+    (mkRenamedOptionModule
+      [ "services" "apache-kafka" "logDirs" ]
+      [ "services" "apache-kafka" "settings" ''log.dirs'' ])
+    (mkRenamedOptionModule
+      [ "services" "apache-kafka" "zookeeper" ]
+      [ "services" "apache-kafka" "settings" ''zookeeper.connect'' ])
+
+    (mkRemovedOptionModule [ "services" "apache-kafka" "port" ]
+      "Please see services.apache-kafka.settings.listeners and its documentation instead")
+    (mkRemovedOptionModule [ "services" "apache-kafka" "hostname" ]
+      "Please see services.apache-kafka.settings.listeners and its documentation instead")
+    (mkRemovedOptionModule [ "services" "apache-kafka" "extraProperties" ]
+      "Please see services.apache-kafka.settings and its documentation instead")
+    (mkRemovedOptionModule [ "services" "apache-kafka" "serverProperties" ]
+      "Please see services.apache-kafka.settings and its documentation instead")
+  ];
 
-    environment.systemPackages = [cfg.package];
+  config = mkIf cfg.enable {
+    services.apache-kafka.configFiles.serverProperties = generator "server.properties" stringlySettings;
 
     users.users.apache-kafka = {
       isSystemUser = true;
       group = "apache-kafka";
       description = "Apache Kafka daemon user";
-      home = head cfg.logDirs;
     };
     users.groups.apache-kafka = {};
 
-    systemd.tmpfiles.rules = map (logDir: "d '${logDir}' 0700 apache-kafka - - -") cfg.logDirs;
+    systemd.tmpfiles.rules = map (logDir: "d '${logDir}' 0700 apache-kafka - - -") cfg.settings."log.dirs";
 
     systemd.services.apache-kafka = {
       description = "Apache Kafka Daemon";
       wantedBy = [ "multi-user.target" ];
       after = [ "network.target" ];
+      preStart = mkIf cfg.formatLogDirs
+        (if cfg.formatLogDirsIgnoreFormatted then ''
+          ${cfg.package}/bin/kafka-storage.sh format -t "${cfg.clusterId}" -c ${cfg.configFiles.serverProperties} --ignore-formatted
+        '' else ''
+          if ${concatMapStringsSep " && " (l: ''[ ! -f "${l}/meta.properties" ]'') cfg.settings."log.dirs"}; then
+            ${cfg.package}/bin/kafka-storage.sh format -t "${cfg.clusterId}" -c ${cfg.configFiles.serverProperties}
+          fi
+        '');
       serviceConfig = {
         ExecStart = ''
           ${cfg.jre}/bin/java \
             -cp "${cfg.package}/libs/*" \
-            -Dlog4j.configuration=file:${logConfig} \
+            -Dlog4j.configuration=file:${cfg.configFiles.log4jProperties} \
             ${toString cfg.jvmOptions} \
             kafka.Kafka \
-            ${serverConfig}
+            ${cfg.configFiles.serverProperties}
         '';
         User = "apache-kafka";
         SuccessExitStatus = "0 143";
       };
     };
-
   };
+
+  meta.doc = ./kafka.md;
+  meta.maintainers = with lib.maintainers; [
+    srhb
+  ];
 }
diff --git a/nixpkgs/nixos/modules/services/misc/autosuspend.nix b/nixpkgs/nixos/modules/services/misc/autosuspend.nix
index b3e362533a09..28dfa12105ec 100644
--- a/nixpkgs/nixos/modules/services/misc/autosuspend.nix
+++ b/nixpkgs/nixos/modules/services/misc/autosuspend.nix
@@ -1,7 +1,7 @@
 { config, pkgs, lib, ... }:
 let
   inherit (lib) mapAttrs' nameValuePair filterAttrs types mkEnableOption
-    mdDoc mkPackageOptionMD mkOption literalExpression mkIf flatten
+    mdDoc mkPackageOption mkOption literalExpression mkIf flatten
     maintainers attrValues;
 
   cfg = config.services.autosuspend;
@@ -96,7 +96,7 @@ in
     services.autosuspend = {
       enable = mkEnableOption (mdDoc "the autosuspend daemon");
 
-      package = mkPackageOptionMD pkgs "autosuspend" { };
+      package = mkPackageOption pkgs "autosuspend" { };
 
       settings = mkOption {
         type = types.submodule {
diff --git a/nixpkgs/nixos/modules/services/misc/bcg.nix b/nixpkgs/nixos/modules/services/misc/bcg.nix
index 214c89dbfe72..9da4a879cdd0 100644
--- a/nixpkgs/nixos/modules/services/misc/bcg.nix
+++ b/nixpkgs/nixos/modules/services/misc/bcg.nix
@@ -26,12 +26,7 @@ in
   options = {
     services.bcg = {
       enable = mkEnableOption (mdDoc "BigClown gateway");
-      package = mkOption {
-        default = pkgs.python3Packages.bcg;
-        defaultText = literalExpression "pkgs.python3Packages.bcg";
-        description = mdDoc "Which bcg derivation to use.";
-        type = types.package;
-      };
+      package = mkPackageOption pkgs [ "python3Packages" "bcg" ] { };
       environmentFiles = mkOption {
         type = types.listOf types.path;
         default = [];
diff --git a/nixpkgs/nixos/modules/services/misc/calibre-server.nix b/nixpkgs/nixos/modules/services/misc/calibre-server.nix
index e1ddae1de1f8..66ae5fa91bb6 100644
--- a/nixpkgs/nixos/modules/services/misc/calibre-server.nix
+++ b/nixpkgs/nixos/modules/services/misc/calibre-server.nix
@@ -33,7 +33,7 @@ in
     services.calibre-server = {
 
       enable = mkEnableOption (lib.mdDoc "calibre-server");
-      package = lib.mkPackageOptionMD pkgs "calibre" { };
+      package = lib.mkPackageOption pkgs "calibre" { };
 
       libraries = mkOption {
         type = types.listOf types.path;
diff --git a/nixpkgs/nixos/modules/services/misc/cgminer.nix b/nixpkgs/nixos/modules/services/misc/cgminer.nix
index a6fbfee73bad..ad6cbf50918d 100644
--- a/nixpkgs/nixos/modules/services/misc/cgminer.nix
+++ b/nixpkgs/nixos/modules/services/misc/cgminer.nix
@@ -33,12 +33,7 @@ in
 
       enable = mkEnableOption (lib.mdDoc "cgminer, an ASIC/FPGA/GPU miner for bitcoin and litecoin");
 
-      package = mkOption {
-        default = pkgs.cgminer;
-        defaultText = literalExpression "pkgs.cgminer";
-        description = lib.mdDoc "Which cgminer derivation to use.";
-        type = types.package;
-      };
+      package = mkPackageOption pkgs "cgminer" { };
 
       user = mkOption {
         type = types.str;
diff --git a/nixpkgs/nixos/modules/services/misc/clipcat.nix b/nixpkgs/nixos/modules/services/misc/clipcat.nix
index 0129de3a9efb..fb6442709530 100644
--- a/nixpkgs/nixos/modules/services/misc/clipcat.nix
+++ b/nixpkgs/nixos/modules/services/misc/clipcat.nix
@@ -9,12 +9,7 @@ in {
   options.services.clipcat= {
     enable = mkEnableOption (lib.mdDoc "Clipcat clipboard daemon");
 
-    package = mkOption {
-      type = types.package;
-      default = pkgs.clipcat;
-      defaultText = literalExpression "pkgs.clipcat";
-      description = lib.mdDoc "clipcat derivation to use.";
-    };
+    package = mkPackageOption pkgs "clipcat" { };
   };
 
   config = mkIf cfg.enable {
diff --git a/nixpkgs/nixos/modules/services/misc/clipmenu.nix b/nixpkgs/nixos/modules/services/misc/clipmenu.nix
index 1cc8c4c47f7e..343167b1df2e 100644
--- a/nixpkgs/nixos/modules/services/misc/clipmenu.nix
+++ b/nixpkgs/nixos/modules/services/misc/clipmenu.nix
@@ -9,12 +9,7 @@ in {
   options.services.clipmenu = {
     enable = mkEnableOption (lib.mdDoc "clipmenu, the clipboard management daemon");
 
-    package = mkOption {
-      type = types.package;
-      default = pkgs.clipmenu;
-      defaultText = literalExpression "pkgs.clipmenu";
-      description = lib.mdDoc "clipmenu derivation to use.";
-    };
+    package = mkPackageOption pkgs "clipmenu" { };
   };
 
   config = mkIf cfg.enable {
diff --git a/nixpkgs/nixos/modules/services/misc/confd.nix b/nixpkgs/nixos/modules/services/misc/confd.nix
index 17c1be57ccbc..93731547ede8 100644
--- a/nixpkgs/nixos/modules/services/misc/confd.nix
+++ b/nixpkgs/nixos/modules/services/misc/confd.nix
@@ -61,12 +61,7 @@ in {
       type = types.path;
     };
 
-    package = mkOption {
-      description = lib.mdDoc "Confd package to use.";
-      default = pkgs.confd;
-      defaultText = literalExpression "pkgs.confd";
-      type = types.package;
-    };
+    package = mkPackageOption pkgs "confd" { };
   };
 
   config = mkIf cfg.enable {
diff --git a/nixpkgs/nixos/modules/services/misc/disnix.nix b/nixpkgs/nixos/modules/services/misc/disnix.nix
index 13c57ce6b85b..ee342cbc2e47 100644
--- a/nixpkgs/nixos/modules/services/misc/disnix.nix
+++ b/nixpkgs/nixos/modules/services/misc/disnix.nix
@@ -27,12 +27,7 @@ in
 
       useWebServiceInterface = mkEnableOption (lib.mdDoc "the DisnixWebService interface running on Apache Tomcat");
 
-      package = mkOption {
-        type = types.path;
-        description = lib.mdDoc "The Disnix package";
-        default = pkgs.disnix;
-        defaultText = literalExpression "pkgs.disnix";
-      };
+      package = mkPackageOption pkgs "disnix" {};
 
       enableProfilePath = mkEnableOption (lib.mdDoc "exposing the Disnix profiles in the system's PATH");
 
diff --git a/nixpkgs/nixos/modules/services/misc/docker-registry.nix b/nixpkgs/nixos/modules/services/misc/docker-registry.nix
index b0e910634637..e8fbc05423d3 100644
--- a/nixpkgs/nixos/modules/services/misc/docker-registry.nix
+++ b/nixpkgs/nixos/modules/services/misc/docker-registry.nix
@@ -47,12 +47,8 @@ in {
   options.services.dockerRegistry = {
     enable = mkEnableOption (lib.mdDoc "Docker Registry");
 
-    package = mkOption {
-      type = types.package;
-      description = mdDoc "Which Docker registry package to use.";
-      default = pkgs.docker-distribution;
-      defaultText = literalExpression "pkgs.docker-distribution";
-      example = literalExpression "pkgs.gitlab-container-registry";
+    package = mkPackageOption pkgs "docker-distribution" {
+      example = "gitlab-container-registry";
     };
 
     listenAddress = mkOption {
diff --git a/nixpkgs/nixos/modules/services/misc/dwm-status.nix b/nixpkgs/nixos/modules/services/misc/dwm-status.nix
index de3e28c41d27..351adf31d922 100644
--- a/nixpkgs/nixos/modules/services/misc/dwm-status.nix
+++ b/nixpkgs/nixos/modules/services/misc/dwm-status.nix
@@ -24,14 +24,8 @@ in
 
       enable = mkEnableOption (lib.mdDoc "dwm-status user service");
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.dwm-status;
-        defaultText = literalExpression "pkgs.dwm-status";
-        example = literalExpression "pkgs.dwm-status.override { enableAlsaUtils = false; }";
-        description = lib.mdDoc ''
-          Which dwm-status package to use.
-        '';
+      package = mkPackageOption pkgs "dwm-status" {
+        example = "dwm-status.override { enableAlsaUtils = false; }";
       };
 
       order = mkOption {
diff --git a/nixpkgs/nixos/modules/services/misc/etcd.nix b/nixpkgs/nixos/modules/services/misc/etcd.nix
index 7bc7a9499113..73bdeb3b0afd 100644
--- a/nixpkgs/nixos/modules/services/misc/etcd.nix
+++ b/nixpkgs/nixos/modules/services/misc/etcd.nix
@@ -15,7 +15,7 @@ in {
       type = types.bool;
     };
 
-    package = mkPackageOptionMD pkgs "etcd" { };
+    package = mkPackageOption pkgs "etcd" { };
 
     name = mkOption {
       description = lib.mdDoc "Etcd unique node name.";
diff --git a/nixpkgs/nixos/modules/services/misc/forgejo.md b/nixpkgs/nixos/modules/services/misc/forgejo.md
index 3df8bc20976a..14b21933e6b0 100644
--- a/nixpkgs/nixos/modules/services/misc/forgejo.md
+++ b/nixpkgs/nixos/modules/services/misc/forgejo.md
@@ -20,7 +20,7 @@ If you experience issues with your instance using `services.gitea`,
 
 ::: {.note}
 Migrating is, while not strictly necessary at this point, highly recommended.
-Both modules and projects are likely to divide further with each release.
+Both modules and projects are likely to diverge further with each release.
 Which might lead to an even more involved migration.
 :::
 
diff --git a/nixpkgs/nixos/modules/services/misc/forgejo.nix b/nixpkgs/nixos/modules/services/misc/forgejo.nix
index 454febda5893..08cddc3a0710 100644
--- a/nixpkgs/nixos/modules/services/misc/forgejo.nix
+++ b/nixpkgs/nixos/modules/services/misc/forgejo.nix
@@ -21,7 +21,7 @@ let
     mkIf
     mkMerge
     mkOption
-    mkPackageOptionMD
+    mkPackageOption
     mkRemovedOptionModule
     mkRenamedOptionModule
     optionalAttrs
@@ -57,7 +57,7 @@ in
     services.forgejo = {
       enable = mkEnableOption (mdDoc "Forgejo");
 
-      package = mkPackageOptionMD pkgs "forgejo" { };
+      package = mkPackageOption pkgs "forgejo" { };
 
       useWizard = mkOption {
         default = false;
diff --git a/nixpkgs/nixos/modules/services/misc/freeswitch.nix b/nixpkgs/nixos/modules/services/misc/freeswitch.nix
index b8b81e586944..a8f7b3d0c3ae 100644
--- a/nixpkgs/nixos/modules/services/misc/freeswitch.nix
+++ b/nixpkgs/nixos/modules/services/misc/freeswitch.nix
@@ -58,14 +58,7 @@ in {
           Also check available templates in [FreeSWITCH repository](https://github.com/signalwire/freeswitch/tree/master/conf).
         '';
       };
-      package = mkOption {
-        type = types.package;
-        default = pkgs.freeswitch;
-        defaultText = literalExpression "pkgs.freeswitch";
-        description = lib.mdDoc ''
-          FreeSWITCH package.
-        '';
-      };
+      package = mkPackageOption pkgs "freeswitch" { };
     };
   };
   config = mkIf cfg.enable {
diff --git a/nixpkgs/nixos/modules/services/misc/gitea.nix b/nixpkgs/nixos/modules/services/misc/gitea.nix
index be528a298991..f4305bea2ad7 100644
--- a/nixpkgs/nixos/modules/services/misc/gitea.nix
+++ b/nixpkgs/nixos/modules/services/misc/gitea.nix
@@ -51,12 +51,7 @@ in
         description = lib.mdDoc "Enable Gitea Service.";
       };
 
-      package = mkOption {
-        default = pkgs.gitea;
-        type = types.package;
-        defaultText = literalExpression "pkgs.gitea";
-        description = lib.mdDoc "gitea derivation to use";
-      };
+      package = mkPackageOption pkgs "gitea" { };
 
       useWizard = mkOption {
         default = false;
diff --git a/nixpkgs/nixos/modules/services/misc/gitlab.nix b/nixpkgs/nixos/modules/services/misc/gitlab.nix
index b399ccc38f58..6756d59cf367 100644
--- a/nixpkgs/nixos/modules/services/misc/gitlab.nix
+++ b/nixpkgs/nixos/modules/services/misc/gitlab.nix
@@ -258,41 +258,17 @@ in {
         '';
       };
 
-      packages.gitlab = mkOption {
-        type = types.package;
-        default = pkgs.gitlab;
-        defaultText = literalExpression "pkgs.gitlab";
-        description = lib.mdDoc "Reference to the gitlab package";
-        example = literalExpression "pkgs.gitlab-ee";
+      packages.gitlab = mkPackageOption pkgs "gitlab" {
+        example = "gitlab-ee";
       };
 
-      packages.gitlab-shell = mkOption {
-        type = types.package;
-        default = pkgs.gitlab-shell;
-        defaultText = literalExpression "pkgs.gitlab-shell";
-        description = lib.mdDoc "Reference to the gitlab-shell package";
-      };
+      packages.gitlab-shell = mkPackageOption pkgs "gitlab-shell" { };
 
-      packages.gitlab-workhorse = mkOption {
-        type = types.package;
-        default = pkgs.gitlab-workhorse;
-        defaultText = literalExpression "pkgs.gitlab-workhorse";
-        description = lib.mdDoc "Reference to the gitlab-workhorse package";
-      };
+      packages.gitlab-workhorse = mkPackageOption pkgs "gitlab-workhorse" { };
 
-      packages.gitaly = mkOption {
-        type = types.package;
-        default = pkgs.gitaly;
-        defaultText = literalExpression "pkgs.gitaly";
-        description = lib.mdDoc "Reference to the gitaly package";
-      };
+      packages.gitaly = mkPackageOption pkgs "gitaly" { };
 
-      packages.pages = mkOption {
-        type = types.package;
-        default = pkgs.gitlab-pages;
-        defaultText = literalExpression "pkgs.gitlab-pages";
-        description = lib.mdDoc "Reference to the gitlab-pages package";
-      };
+      packages.pages = mkPackageOption pkgs "gitlab-pages" { };
 
       statePath = mkOption {
         type = types.str;
diff --git a/nixpkgs/nixos/modules/services/misc/gollum.nix b/nixpkgs/nixos/modules/services/misc/gollum.nix
index b73528abaf65..e31eeaf8a30a 100644
--- a/nixpkgs/nixos/modules/services/misc/gollum.nix
+++ b/nixpkgs/nixos/modules/services/misc/gollum.nix
@@ -83,14 +83,7 @@ in
       description = lib.mdDoc "Specifies the path of the repository directory. If it does not exist, Gollum will create it on startup.";
     };
 
-    package = mkOption {
-      type = types.package;
-      default = pkgs.gollum;
-      defaultText = literalExpression "pkgs.gollum";
-      description = lib.mdDoc ''
-        The package used in the service
-      '';
-    };
+    package = mkPackageOption pkgs "gollum" { };
 
     user = mkOption {
       type = types.str;
diff --git a/nixpkgs/nixos/modules/services/misc/greenclip.nix b/nixpkgs/nixos/modules/services/misc/greenclip.nix
index 45847af71141..ecfb864ab2b7 100644
--- a/nixpkgs/nixos/modules/services/misc/greenclip.nix
+++ b/nixpkgs/nixos/modules/services/misc/greenclip.nix
@@ -9,12 +9,7 @@ in {
   options.services.greenclip = {
     enable = mkEnableOption (lib.mdDoc "Greenclip daemon");
 
-    package = mkOption {
-      type = types.package;
-      default = pkgs.haskellPackages.greenclip;
-      defaultText = literalExpression "pkgs.haskellPackages.greenclip";
-      description = lib.mdDoc "greenclip derivation to use.";
-    };
+    package = mkPackageOption pkgs [ "haskellPackages" "greenclip" ] { };
   };
 
   config = mkIf cfg.enable {
diff --git a/nixpkgs/nixos/modules/services/misc/heisenbridge.nix b/nixpkgs/nixos/modules/services/misc/heisenbridge.nix
index 822a09d7cd4d..d7ce9c605c9e 100644
--- a/nixpkgs/nixos/modules/services/misc/heisenbridge.nix
+++ b/nixpkgs/nixos/modules/services/misc/heisenbridge.nix
@@ -25,14 +25,7 @@ in
   options.services.heisenbridge = {
     enable = mkEnableOption (lib.mdDoc "the Matrix to IRC bridge");
 
-    package = mkOption {
-      type = types.package;
-      default = pkgs.heisenbridge;
-      defaultText = lib.literalExpression "pkgs.heisenbridge";
-      description = lib.mdDoc ''
-        Package of the application to run, exposed for overriding purposes.
-      '';
-    };
+    package = mkPackageOption pkgs "heisenbridge" { };
 
     homeserver = mkOption {
       type = types.str;
diff --git a/nixpkgs/nixos/modules/services/misc/homepage-dashboard.nix b/nixpkgs/nixos/modules/services/misc/homepage-dashboard.nix
index e68571253433..07a09e2b6bbf 100644
--- a/nixpkgs/nixos/modules/services/misc/homepage-dashboard.nix
+++ b/nixpkgs/nixos/modules/services/misc/homepage-dashboard.nix
@@ -12,7 +12,7 @@ in
     services.homepage-dashboard = {
       enable = lib.mkEnableOption (lib.mdDoc "Homepage Dashboard");
 
-      package = lib.mkPackageOptionMD pkgs "homepage-dashboard" { };
+      package = lib.mkPackageOption pkgs "homepage-dashboard" { };
 
       openFirewall = lib.mkOption {
         type = lib.types.bool;
diff --git a/nixpkgs/nixos/modules/services/misc/input-remapper.nix b/nixpkgs/nixos/modules/services/misc/input-remapper.nix
index 3f6d97f85738..5b9f16e019d8 100644
--- a/nixpkgs/nixos/modules/services/misc/input-remapper.nix
+++ b/nixpkgs/nixos/modules/services/misc/input-remapper.nix
@@ -7,7 +7,7 @@ let cfg = config.services.input-remapper; in
   options = {
     services.input-remapper = {
       enable = mkEnableOption (lib.mdDoc "input-remapper, an easy to use tool to change the mapping of your input device buttons");
-      package = mkPackageOptionMD pkgs "input-remapper" { };
+      package = mkPackageOption pkgs "input-remapper" { };
       enableUdevRules = mkEnableOption (lib.mdDoc "udev rules added by input-remapper to handle hotplugged devices. Currently disabled by default due to https://github.com/sezanzeb/input-remapper/issues/140");
       serviceWantedBy = mkOption {
         default = [ "graphical.target" ];
diff --git a/nixpkgs/nixos/modules/services/misc/jackett.nix b/nixpkgs/nixos/modules/services/misc/jackett.nix
index b0edf0d18da4..c0bb0a575f01 100644
--- a/nixpkgs/nixos/modules/services/misc/jackett.nix
+++ b/nixpkgs/nixos/modules/services/misc/jackett.nix
@@ -35,12 +35,7 @@ in
         description = lib.mdDoc "Group under which Jackett runs.";
       };
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.jackett;
-        defaultText = literalExpression "pkgs.jackett";
-        description = lib.mdDoc "Jackett package to use.";
-      };
+      package = mkPackageOption pkgs "jackett" { };
     };
   };
 
diff --git a/nixpkgs/nixos/modules/services/misc/jellyfin.nix b/nixpkgs/nixos/modules/services/misc/jellyfin.nix
index 43fdc09f4559..7042b491ffa4 100644
--- a/nixpkgs/nixos/modules/services/misc/jellyfin.nix
+++ b/nixpkgs/nixos/modules/services/misc/jellyfin.nix
@@ -16,14 +16,7 @@ in
         description = lib.mdDoc "User account under which Jellyfin runs.";
       };
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.jellyfin;
-        defaultText = literalExpression "pkgs.jellyfin";
-        description = lib.mdDoc ''
-          Jellyfin package to use.
-        '';
-      };
+      package = mkPackageOption pkgs "jellyfin" { };
 
       group = mkOption {
         type = types.str;
diff --git a/nixpkgs/nixos/modules/services/misc/kafka.md b/nixpkgs/nixos/modules/services/misc/kafka.md
new file mode 100644
index 000000000000..370bb3b482d2
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/misc/kafka.md
@@ -0,0 +1,63 @@
+# Apache Kafka {#module-services-apache-kafka}
+
+[Apache Kafka](https://kafka.apache.org/) is an open-source distributed event
+streaming platform
+
+## Basic Usage {#module-services-apache-kafka-basic-usage}
+
+The Apache Kafka service is configured almost exclusively through its
+[settings](#opt-services.apache-kafka.settings) option, with each attribute
+corresponding to the [upstream configuration
+manual](https://kafka.apache.org/documentation/#configuration) broker settings.
+
+## KRaft {#module-services-apache-kafka-kraft}
+
+Unlike in Zookeeper mode, Kafka in
+[KRaft](https://kafka.apache.org/documentation/#kraft) mode requires each log
+dir to be "formatted" (which means a cluster-specific a metadata file must
+exist in each log dir)
+
+The upstream intention is for users to execute the [storage
+tool](https://kafka.apache.org/documentation/#kraft_storage) to achieve this,
+but this module contains a few extra options to automate this:
+
+- [](#opt-services.apache-kafka.clusterId)
+- [](#opt-services.apache-kafka.formatLogDirs)
+- [](#opt-services.apache-kafka.formatLogDirsIgnoreFormatted)
+
+## Migrating to settings {#module-services-apache-kafka-migrating-to-settings}
+
+Migrating a cluster to the new `settings`-based changes requires adapting removed options to the corresponding upstream settings.
+
+This means that the upstream [Broker Configs documentation](https://kafka.apache.org/documentation/#brokerconfigs) should be followed closely.
+
+Note that dotted options in the upstream docs do _not_ correspond to nested Nix attrsets, but instead as quoted top level `settings` attributes, as in `services.apache-kafka.settings."broker.id"`, *NOT* `services.apache-kafka.settings.broker.id`.
+
+Care should be taken, especially when migrating clusters from the old module, to ensure that the same intended configuration is reproduced faithfully via `settings`.
+
+To assist in the comparison, the final config can be inspected by building the config file itself, ie. with: `nix-build <nixpkgs/nixos> -A config.services.apache-kafka.configFiles.serverProperties`.
+
+Notable changes to be aware of include:
+
+- Removal of `services.apache-kafka.extraProperties` and `services.apache-kafka.serverProperties`
+  - Translate using arbitrary properties using [](#opt-services.apache-kafka.settings)
+  - [Upstream docs](https://kafka.apache.org/documentation.html#brokerconfigs)
+  - The intention is for all broker properties to be fully representable via [](#opt-services.apache-kafka.settings).
+  - If this is not the case, please do consider raising an issue.
+  - Until it can be remedied, you *can* bail out by using [](#opt-services.apache-kafka.configFiles.serverProperties) to the path of a fully rendered properties file.
+
+- Removal of `services.apache-kafka.hostname` and `services.apache-kafka.port`
+  - Translate using: `services.apache-kafka.settings.listeners`
+  - [Upstream docs](https://kafka.apache.org/documentation.html#brokerconfigs_listeners)
+
+- Removal of `services.apache-kafka.logDirs`
+  - Translate using: `services.apache-kafka.settings."log.dirs"`
+  - [Upstream docs](https://kafka.apache.org/documentation.html#brokerconfigs_log.dirs)
+
+- Removal of `services.apache-kafka.brokerId`
+  - Translate using: `services.apache-kafka.settings."broker.id"`
+  - [Upstream docs](https://kafka.apache.org/documentation.html#brokerconfigs_broker.id)
+
+- Removal of `services.apache-kafka.zookeeper`
+  - Translate using: `services.apache-kafka.settings."zookeeper.connect"`
+  - [Upstream docs](https://kafka.apache.org/documentation.html#brokerconfigs_zookeeper.connect)
diff --git a/nixpkgs/nixos/modules/services/misc/klipper.nix b/nixpkgs/nixos/modules/services/misc/klipper.nix
index 9eb2fdb46593..a0eb409599b5 100644
--- a/nixpkgs/nixos/modules/services/misc/klipper.nix
+++ b/nixpkgs/nixos/modules/services/misc/klipper.nix
@@ -16,12 +16,7 @@ in
     services.klipper = {
       enable = mkEnableOption (lib.mdDoc "Klipper, the 3D printer firmware");
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.klipper;
-        defaultText = literalExpression "pkgs.klipper";
-        description = lib.mdDoc "The Klipper package.";
-      };
+      package = mkPackageOption pkgs "klipper" { };
 
       logFile = mkOption {
         type = types.nullOr types.path;
diff --git a/nixpkgs/nixos/modules/services/misc/libreddit.nix b/nixpkgs/nixos/modules/services/misc/libreddit.nix
index fd58928d2821..02d71c198e78 100644
--- a/nixpkgs/nixos/modules/services/misc/libreddit.nix
+++ b/nixpkgs/nixos/modules/services/misc/libreddit.nix
@@ -15,12 +15,7 @@ in
     services.libreddit = {
       enable = mkEnableOption (lib.mdDoc "Private front-end for Reddit");
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.libreddit;
-        defaultText = literalExpression "pkgs.libreddit";
-        description = lib.mdDoc "Libreddit package to use.";
-      };
+      package = mkPackageOption pkgs "libreddit" { };
 
       address = mkOption {
         default = "0.0.0.0";
diff --git a/nixpkgs/nixos/modules/services/misc/lidarr.nix b/nixpkgs/nixos/modules/services/misc/lidarr.nix
index 92b00054bdff..4dc0fc63863b 100644
--- a/nixpkgs/nixos/modules/services/misc/lidarr.nix
+++ b/nixpkgs/nixos/modules/services/misc/lidarr.nix
@@ -16,12 +16,7 @@ in
         description = lib.mdDoc "The directory where Lidarr stores its data files.";
       };
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.lidarr;
-        defaultText = literalExpression "pkgs.lidarr";
-        description = lib.mdDoc "The Lidarr package to use";
-      };
+      package = mkPackageOption pkgs "lidarr" { };
 
       openFirewall = mkOption {
         type = types.bool;
diff --git a/nixpkgs/nixos/modules/services/misc/mbpfan.nix b/nixpkgs/nixos/modules/services/misc/mbpfan.nix
index 8f64fb2d9c52..ef56ea49d1a9 100644
--- a/nixpkgs/nixos/modules/services/misc/mbpfan.nix
+++ b/nixpkgs/nixos/modules/services/misc/mbpfan.nix
@@ -11,12 +11,7 @@ in {
   options.services.mbpfan = {
     enable = mkEnableOption (lib.mdDoc "mbpfan, fan controller daemon for Apple Macs and MacBooks");
 
-    package = mkOption {
-      type = types.package;
-      default = pkgs.mbpfan;
-      defaultText = literalExpression "pkgs.mbpfan";
-      description = lib.mdDoc "The package used for the mbpfan daemon.";
-    };
+    package = mkPackageOption pkgs "mbpfan" { };
 
     verbose = mkOption {
       type = types.bool;
diff --git a/nixpkgs/nixos/modules/services/misc/mediatomb.nix b/nixpkgs/nixos/modules/services/misc/mediatomb.nix
index 335b1b684b1a..d421d74c53ad 100644
--- a/nixpkgs/nixos/modules/services/misc/mediatomb.nix
+++ b/nixpkgs/nixos/modules/services/misc/mediatomb.nix
@@ -215,14 +215,7 @@ in {
         '';
       };
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.gerbera;
-        defaultText = literalExpression "pkgs.gerbera";
-        description = lib.mdDoc ''
-          Underlying package to be used with the module.
-        '';
-      };
+      package = mkPackageOption pkgs "gerbera" { };
 
       ps3Support = mkOption {
         type = types.bool;
diff --git a/nixpkgs/nixos/modules/services/misc/moonraker.nix b/nixpkgs/nixos/modules/services/misc/moonraker.nix
index 797e145c47a6..0ee7e898cf76 100644
--- a/nixpkgs/nixos/modules/services/misc/moonraker.nix
+++ b/nixpkgs/nixos/modules/services/misc/moonraker.nix
@@ -18,12 +18,9 @@ in {
     services.moonraker = {
       enable = mkEnableOption (lib.mdDoc "Moonraker, an API web server for Klipper");
 
-      package = mkOption {
-        type = with types; nullOr package;
-        default = pkgs.moonraker;
-        defaultText = literalExpression "pkgs.moonraker";
-        example = literalExpression "pkgs.moonraker.override { useGpiod = true; }";
-        description = lib.mdDoc "Moonraker package to use";
+      package = mkPackageOption pkgs "moonraker" {
+        nullable = true;
+        example = "moonraker.override { useGpiod = true; }";
       };
 
       klipperSocket = mkOption {
diff --git a/nixpkgs/nixos/modules/services/misc/nitter.nix b/nixpkgs/nixos/modules/services/misc/nitter.nix
index 77f5459d117c..c2c462d46bb5 100644
--- a/nixpkgs/nixos/modules/services/misc/nitter.nix
+++ b/nixpkgs/nixos/modules/services/misc/nitter.nix
@@ -54,12 +54,7 @@ in
     services.nitter = {
       enable = mkEnableOption (lib.mdDoc "Nitter");
 
-      package = mkOption {
-        default = pkgs.nitter;
-        type = types.package;
-        defaultText = literalExpression "pkgs.nitter";
-        description = lib.mdDoc "The nitter derivation to use.";
-      };
+      package = mkPackageOption pkgs "nitter" { };
 
       server = {
         address = mkOption {
diff --git a/nixpkgs/nixos/modules/services/misc/ntfy-sh.nix b/nixpkgs/nixos/modules/services/misc/ntfy-sh.nix
index 8fc1df93afb1..98134e94eeed 100644
--- a/nixpkgs/nixos/modules/services/misc/ntfy-sh.nix
+++ b/nixpkgs/nixos/modules/services/misc/ntfy-sh.nix
@@ -12,12 +12,7 @@ in
   options.services.ntfy-sh = {
     enable = mkEnableOption (mdDoc "[ntfy-sh](https://ntfy.sh), a push notification service");
 
-    package = mkOption {
-      type = types.package;
-      default = pkgs.ntfy-sh;
-      defaultText = literalExpression "pkgs.ntfy-sh";
-      description = mdDoc "The ntfy.sh package to use.";
-    };
+    package = mkPackageOption pkgs "ntfy-sh" { };
 
     user = mkOption {
       default = "ntfy-sh";
diff --git a/nixpkgs/nixos/modules/services/misc/nzbhydra2.nix b/nixpkgs/nixos/modules/services/misc/nzbhydra2.nix
index 47d08135f57e..536a4e4b0075 100644
--- a/nixpkgs/nixos/modules/services/misc/nzbhydra2.nix
+++ b/nixpkgs/nixos/modules/services/misc/nzbhydra2.nix
@@ -22,12 +22,7 @@ in {
           lib.mdDoc "Open ports in the firewall for the NZBHydra2 web interface.";
       };
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.nzbhydra2;
-        defaultText = literalExpression "pkgs.nzbhydra2";
-        description = lib.mdDoc "NZBHydra2 package to use.";
-      };
+      package = mkPackageOption pkgs "nzbhydra2" { };
     };
   };
 
diff --git a/nixpkgs/nixos/modules/services/misc/paperless.nix b/nixpkgs/nixos/modules/services/misc/paperless.nix
index 1e0a8d0f928e..b3bc7d89009d 100644
--- a/nixpkgs/nixos/modules/services/misc/paperless.nix
+++ b/nixpkgs/nixos/modules/services/misc/paperless.nix
@@ -194,12 +194,7 @@ in
       description = lib.mdDoc "User under which Paperless runs.";
     };
 
-    package = mkOption {
-      type = types.package;
-      default = pkgs.paperless-ngx;
-      defaultText = literalExpression "pkgs.paperless-ngx";
-      description = lib.mdDoc "The Paperless package to use.";
-    };
+    package = mkPackageOption pkgs "paperless-ngx" { };
   };
 
   config = mkIf cfg.enable {
diff --git a/nixpkgs/nixos/modules/services/misc/plex.nix b/nixpkgs/nixos/modules/services/misc/plex.nix
index 7fc76028c02a..164801605713 100644
--- a/nixpkgs/nixos/modules/services/misc/plex.nix
+++ b/nixpkgs/nixos/modules/services/misc/plex.nix
@@ -93,13 +93,10 @@ in
         '';
       };
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.plex;
-        defaultText = literalExpression "pkgs.plex";
-        description = lib.mdDoc ''
-          The Plex package to use. Plex subscribers may wish to use their own
-          package here, pointing to subscriber-only server versions.
+      package = mkPackageOption pkgs "plex" {
+        extraDescription = ''
+          Plex subscribers may wish to use their own package here,
+          pointing to subscriber-only server versions.
         '';
       };
     };
diff --git a/nixpkgs/nixos/modules/services/misc/polaris.nix b/nixpkgs/nixos/modules/services/misc/polaris.nix
index 70f097f02840..83da486083b4 100644
--- a/nixpkgs/nixos/modules/services/misc/polaris.nix
+++ b/nixpkgs/nixos/modules/services/misc/polaris.nix
@@ -13,7 +13,7 @@ in
     services.polaris = {
       enable = mkEnableOption (lib.mdDoc "Polaris Music Server");
 
-      package = mkPackageOptionMD pkgs "polaris" { };
+      package = mkPackageOption pkgs "polaris" { };
 
       user = mkOption {
         type = types.str;
diff --git a/nixpkgs/nixos/modules/services/misc/portunus.nix b/nixpkgs/nixos/modules/services/misc/portunus.nix
index d18881986970..3299b6404c2b 100644
--- a/nixpkgs/nixos/modules/services/misc/portunus.nix
+++ b/nixpkgs/nixos/modules/services/misc/portunus.nix
@@ -26,12 +26,7 @@ in
       '';
     };
 
-    package = mkOption {
-      type = types.package;
-      default = pkgs.portunus;
-      defaultText = lib.literalExpression "pkgs.portunus";
-      description = lib.mdDoc "The Portunus package to use.";
-    };
+    package = mkPackageOption pkgs "portunus" { };
 
     seedPath = mkOption {
       type = types.nullOr types.path;
diff --git a/nixpkgs/nixos/modules/services/misc/preload.nix b/nixpkgs/nixos/modules/services/misc/preload.nix
new file mode 100644
index 000000000000..19b2531087dd
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/misc/preload.nix
@@ -0,0 +1,31 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.services.preload;
+in {
+  meta = { maintainers = pkgs.preload.meta.maintainers; };
+
+  options.services.preload = {
+    enable = mkEnableOption "preload";
+    package = mkPackageOption pkgs "preload" { };
+  };
+
+  config = mkIf cfg.enable {
+    systemd.services.preload = {
+      description = "Loads data into ram during idle time of CPU.";
+      wantedBy = [ "multi-user.target" ];
+
+      serviceConfig = {
+        EnvironmentFile = "${cfg.package}/etc/conf.d/preload";
+        ExecStart = "${getExe cfg.package} --foreground $PRELOAD_OPTS";
+        Type = "simple";
+        # Only preload data during CPU idle time
+        IOSchedulingClass = 3;
+        DynamicUser = true;
+        StateDirectory = "preload";
+      };
+    };
+  };
+}
diff --git a/nixpkgs/nixos/modules/services/misc/prowlarr.nix b/nixpkgs/nixos/modules/services/misc/prowlarr.nix
index 836280d3e5fe..84d365003992 100644
--- a/nixpkgs/nixos/modules/services/misc/prowlarr.nix
+++ b/nixpkgs/nixos/modules/services/misc/prowlarr.nix
@@ -11,7 +11,7 @@ in
     services.prowlarr = {
       enable = mkEnableOption (lib.mdDoc "Prowlarr");
 
-      package = mkPackageOptionMD pkgs "prowlarr" { };
+      package = mkPackageOption pkgs "prowlarr" { };
 
       openFirewall = mkOption {
         type = types.bool;
diff --git a/nixpkgs/nixos/modules/services/misc/pufferpanel.nix b/nixpkgs/nixos/modules/services/misc/pufferpanel.nix
index 2022406c8325..b951d60cc5b9 100644
--- a/nixpkgs/nixos/modules/services/misc/pufferpanel.nix
+++ b/nixpkgs/nixos/modules/services/misc/pufferpanel.nix
@@ -33,7 +33,7 @@ in
       '';
     };
 
-    package = lib.mkPackageOptionMD pkgs "pufferpanel" { };
+    package = lib.mkPackageOption pkgs "pufferpanel" { };
 
     extraGroups = lib.mkOption {
       type = lib.types.listOf lib.types.str;
diff --git a/nixpkgs/nixos/modules/services/misc/radarr.nix b/nixpkgs/nixos/modules/services/misc/radarr.nix
index 834b092c0d14..618341cf614f 100644
--- a/nixpkgs/nixos/modules/services/misc/radarr.nix
+++ b/nixpkgs/nixos/modules/services/misc/radarr.nix
@@ -11,13 +11,7 @@ in
     services.radarr = {
       enable = mkEnableOption (lib.mdDoc "Radarr");
 
-      package = mkOption {
-        description = lib.mdDoc "Radarr package to use";
-        default = pkgs.radarr;
-        defaultText = literalExpression "pkgs.radarr";
-        example = literalExpression "pkgs.radarr";
-        type = types.package;
-      };
+      package = mkPackageOption pkgs "radarr" { };
 
       dataDir = mkOption {
         type = types.str;
diff --git a/nixpkgs/nixos/modules/services/misc/readarr.nix b/nixpkgs/nixos/modules/services/misc/readarr.nix
index dd4fef6e598d..3c84b13485a4 100644
--- a/nixpkgs/nixos/modules/services/misc/readarr.nix
+++ b/nixpkgs/nixos/modules/services/misc/readarr.nix
@@ -16,12 +16,7 @@ in
         description = lib.mdDoc "The directory where Readarr stores its data files.";
       };
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.readarr;
-        defaultText = literalExpression "pkgs.readarr";
-        description = lib.mdDoc "The Readarr package to use";
-      };
+      package = mkPackageOption pkgs "readarr" { };
 
       openFirewall = mkOption {
         type = types.bool;
diff --git a/nixpkgs/nixos/modules/services/misc/redmine.nix b/nixpkgs/nixos/modules/services/misc/redmine.nix
index 20fa71507b6b..e3941d2e29de 100644
--- a/nixpkgs/nixos/modules/services/misc/redmine.nix
+++ b/nixpkgs/nixos/modules/services/misc/redmine.nix
@@ -1,7 +1,8 @@
 { config, lib, pkgs, ... }:
 
 let
-  inherit (lib) mkBefore mkDefault mkEnableOption mkIf mkOption mkRemovedOptionModule types;
+  inherit (lib) mkBefore mkDefault mkEnableOption mkPackageOption
+                mkIf mkOption mkRemovedOptionModule types;
   inherit (lib) concatStringsSep literalExpression mapAttrsToList;
   inherit (lib) optional optionalAttrs optionalString;
 
@@ -51,12 +52,8 @@ in
     services.redmine = {
       enable = mkEnableOption (lib.mdDoc "Redmine");
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.redmine;
-        defaultText = literalExpression "pkgs.redmine";
-        description = lib.mdDoc "Which Redmine package to use.";
-        example = literalExpression "pkgs.redmine.override { ruby = pkgs.ruby_2_7; }";
+      package = mkPackageOption pkgs "redmine" {
+        example = "redmine.override { ruby = pkgs.ruby_2_7; }";
       };
 
       user = mkOption {
diff --git a/nixpkgs/nixos/modules/services/misc/rippled.nix b/nixpkgs/nixos/modules/services/misc/rippled.nix
index d14b6421b742..68a831894250 100644
--- a/nixpkgs/nixos/modules/services/misc/rippled.nix
+++ b/nixpkgs/nixos/modules/services/misc/rippled.nix
@@ -209,12 +209,7 @@ in
     services.rippled = {
       enable = mkEnableOption (lib.mdDoc "rippled");
 
-      package = mkOption {
-        description = lib.mdDoc "Which rippled package to use.";
-        type = types.package;
-        default = pkgs.rippled;
-        defaultText = literalExpression "pkgs.rippled";
-      };
+      package = mkPackageOption pkgs "rippled" { };
 
       ports = mkOption {
         description = lib.mdDoc "Ports exposed by rippled";
diff --git a/nixpkgs/nixos/modules/services/misc/rmfakecloud.nix b/nixpkgs/nixos/modules/services/misc/rmfakecloud.nix
index 1cdfdeceabcd..979f4f14d383 100644
--- a/nixpkgs/nixos/modules/services/misc/rmfakecloud.nix
+++ b/nixpkgs/nixos/modules/services/misc/rmfakecloud.nix
@@ -11,14 +11,11 @@ in {
     services.rmfakecloud = {
       enable = mkEnableOption (lib.mdDoc "rmfakecloud remarkable self-hosted cloud");
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.rmfakecloud;
-        defaultText = literalExpression "pkgs.rmfakecloud";
-        description = lib.mdDoc ''
-          rmfakecloud package to use.
-
+      package = mkPackageOption pkgs "rmfakecloud" {
+        extraDescription = ''
+          ::: {.note}
           The default does not include the web user interface.
+          :::
         '';
       };
 
diff --git a/nixpkgs/nixos/modules/services/misc/rshim.nix b/nixpkgs/nixos/modules/services/misc/rshim.nix
index 706cf9136b00..ae13f7d208f6 100644
--- a/nixpkgs/nixos/modules/services/misc/rshim.nix
+++ b/nixpkgs/nixos/modules/services/misc/rshim.nix
@@ -14,7 +14,7 @@ in
   options.services.rshim = {
     enable = lib.mkEnableOption (lib.mdDoc "user-space rshim driver for the BlueField SoC");
 
-    package = lib.mkPackageOptionMD pkgs "rshim-user-space" { };
+    package = lib.mkPackageOption pkgs "rshim-user-space" { };
 
     backend = lib.mkOption {
       type = with lib.types; nullOr (enum [ "usb" "pcie" "pcie_lf" ]);
diff --git a/nixpkgs/nixos/modules/services/misc/sickbeard.nix b/nixpkgs/nixos/modules/services/misc/sickbeard.nix
index bd8d8d8fa7cc..f141660ced86 100644
--- a/nixpkgs/nixos/modules/services/misc/sickbeard.nix
+++ b/nixpkgs/nixos/modules/services/misc/sickbeard.nix
@@ -22,12 +22,9 @@ in
         default = false;
         description = lib.mdDoc "Whether to enable the sickbeard server.";
       };
-      package = mkOption {
-        type = types.package;
-        default = pkgs.sickbeard;
-        defaultText = literalExpression "pkgs.sickbeard";
-        example = literalExpression "pkgs.sickrage";
-        description =lib.mdDoc ''
+      package = mkPackageOption pkgs "sickbeard" {
+        example = "sickrage";
+        extraDescription = ''
           Enable `pkgs.sickrage` or `pkgs.sickgear`
           as an alternative to SickBeard
         '';
diff --git a/nixpkgs/nixos/modules/services/misc/sonarr.nix b/nixpkgs/nixos/modules/services/misc/sonarr.nix
index 65c51d9677d9..ec59988d2b9a 100644
--- a/nixpkgs/nixos/modules/services/misc/sonarr.nix
+++ b/nixpkgs/nixos/modules/services/misc/sonarr.nix
@@ -36,14 +36,7 @@ in
         description = lib.mdDoc "Group under which Sonaar runs.";
       };
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.sonarr;
-        defaultText = literalExpression "pkgs.sonarr";
-        description = lib.mdDoc ''
-          Sonarr package to use.
-        '';
-      };
+      package = mkPackageOption pkgs "sonarr" { };
     };
   };
 
diff --git a/nixpkgs/nixos/modules/services/misc/sourcehut/default.nix b/nixpkgs/nixos/modules/services/misc/sourcehut/default.nix
index f2b09f4bc4b6..aa803d3bb693 100644
--- a/nixpkgs/nixos/modules/services/misc/sourcehut/default.nix
+++ b/nixpkgs/nixos/modules/services/misc/sourcehut/default.nix
@@ -1,6 +1,15 @@
 { config, pkgs, lib, ... }:
-with lib;
+
 let
+  inherit (builtins) head tail;
+  inherit (lib) generators maintainers types;
+  inherit (lib.attrsets) attrValues filterAttrs mapAttrs mapAttrsToList recursiveUpdate;
+  inherit (lib.lists) flatten optional optionals;
+  inherit (lib.options) literalExpression mkEnableOption mkOption mkPackageOption;
+  inherit (lib.strings) concatMapStringsSep concatStringsSep optionalString versionOlder;
+  inherit (lib.trivial) mapNullable;
+  inherit (lib.modules) mkBefore mkDefault mkForce mkIf mkMerge
+    mkRemovedOptionModule mkRenamedOptionModule;
   inherit (config.services) nginx postfix postgresql redis;
   inherit (config.users) users groups;
   cfg = config.services.sourcehut;
@@ -671,14 +680,8 @@ in
     };
 
     git = {
-      package = mkOption {
-        type = types.package;
-        default = pkgs.git;
-        defaultText = literalExpression "pkgs.git";
-        example = literalExpression "pkgs.gitFull";
-        description = lib.mdDoc ''
-          Git package for git.sr.ht. This can help silence collisions.
-        '';
+      package = mkPackageOption pkgs "git" {
+        example = "gitFull";
       };
       fcgiwrap.preforkProcess = mkOption {
         description = lib.mdDoc "Number of fcgiwrap processes to prefork.";
@@ -688,14 +691,7 @@ in
     };
 
     hg = {
-      package = mkOption {
-        type = types.package;
-        default = pkgs.mercurial;
-        defaultText = literalExpression "pkgs.mercurial";
-        description = lib.mdDoc ''
-          Mercurial package for hg.sr.ht. This can help silence collisions.
-        '';
-      };
+      package = mkPackageOption pkgs "mercurial" { };
       cloneBundles = mkOption {
         type = types.bool;
         default = false;
@@ -1316,6 +1312,11 @@ in
     (import ./service.nix "paste" {
       inherit configIniOfService;
       port = 5011;
+      extraServices.pastesrht-api = {
+        serviceConfig.Restart = "always";
+        serviceConfig.RestartSec = "5s";
+        serviceConfig.ExecStart = "${pkgs.sourcehut.pastesrht}/bin/pastesrht-api -b ${cfg.listenAddress}:${toString (cfg.paste.port + 100)}";
+      };
     })
 
     (import ./service.nix "todo" {
@@ -1369,5 +1370,5 @@ in
   ];
 
   meta.doc = ./default.md;
-  meta.maintainers = with maintainers; [ tomberek ];
+  meta.maintainers = with maintainers; [ tomberek nessdoor ];
 }
diff --git a/nixpkgs/nixos/modules/services/misc/sourcehut/service.nix b/nixpkgs/nixos/modules/services/misc/sourcehut/service.nix
index f08d5eb46871..4a8289b4d403 100644
--- a/nixpkgs/nixos/modules/services/misc/sourcehut/service.nix
+++ b/nixpkgs/nixos/modules/services/misc/sourcehut/service.nix
@@ -3,117 +3,133 @@ srv:
 , srvsrht ? "${srv}srht" # Because "buildsrht" does not follow that pattern (missing an "s").
 , iniKey ? "${srv}.sr.ht"
 , webhooks ? false
-, extraTimers ? {}
-, mainService ? {}
-, extraServices ? {}
-, extraConfig ? {}
+, extraTimers ? { }
+, mainService ? { }
+, extraServices ? { }
+, extraConfig ? { }
 , port
 }:
 { config, lib, pkgs, ... }:
 
-with lib;
 let
+  inherit (lib) types;
+  inherit (lib.attrsets) mapAttrs optionalAttrs;
+  inherit (lib.lists) optional;
+  inherit (lib.modules) mkBefore mkDefault mkForce mkIf mkMerge;
+  inherit (lib.options) mkEnableOption mkOption;
+  inherit (lib.strings) concatStringsSep hasSuffix optionalString;
   inherit (config.services) postgresql;
   redis = config.services.redis.servers."sourcehut-${srvsrht}";
   inherit (config.users) users;
   cfg = config.services.sourcehut;
   configIni = configIniOfService srv;
   srvCfg = cfg.${srv};
-  baseService = serviceName: { allowStripe ? false }: extraService: let
-    runDir = "/run/sourcehut/${serviceName}";
-    rootDir = "/run/sourcehut/chroots/${serviceName}";
+  baseService = serviceName: { allowStripe ? false }: extraService:
+    let
+      runDir = "/run/sourcehut/${serviceName}";
+      rootDir = "/run/sourcehut/chroots/${serviceName}";
     in
-    mkMerge [ extraService {
-    after = [ "network.target" ] ++
-      optional cfg.postgresql.enable "postgresql.service" ++
-      optional cfg.redis.enable "redis-sourcehut-${srvsrht}.service";
-    requires =
-      optional cfg.postgresql.enable "postgresql.service" ++
-      optional cfg.redis.enable "redis-sourcehut-${srvsrht}.service";
-    path = [ pkgs.gawk ];
-    environment.HOME = runDir;
-    serviceConfig = {
-      User = mkDefault srvCfg.user;
-      Group = mkDefault srvCfg.group;
-      RuntimeDirectory = [
-        "sourcehut/${serviceName}"
-        # Used by *srht-keys which reads ../config.ini
-        "sourcehut/${serviceName}/subdir"
-        "sourcehut/chroots/${serviceName}"
-      ];
-      RuntimeDirectoryMode = "2750";
-      # No need for the chroot path once inside the chroot
-      InaccessiblePaths = [ "-+${rootDir}" ];
-      # g+rx is for group members (eg. fcgiwrap or nginx)
-      # to read Git/Mercurial repositories, buildlogs, etc.
-      # o+x is for intermediate directories created by BindPaths= and like,
-      # as they're owned by root:root.
-      UMask = "0026";
-      RootDirectory = rootDir;
-      RootDirectoryStartOnly = true;
-      PrivateTmp = true;
-      MountAPIVFS = true;
-      # config.ini is looked up in there, before /etc/srht/config.ini
-      # Note that it fails to be set in ExecStartPre=
-      WorkingDirectory = mkDefault ("-"+runDir);
-      BindReadOnlyPaths = [
-        builtins.storeDir
-        "/etc"
-        "/run/booted-system"
-        "/run/current-system"
-        "/run/systemd"
-        ] ++
-        optional cfg.postgresql.enable "/run/postgresql" ++
-        optional cfg.redis.enable "/run/redis-sourcehut-${srvsrht}";
-      # LoadCredential= are unfortunately not available in ExecStartPre=
-      # Hence this one is run as root (the +) with RootDirectoryStartOnly=
-      # to reach credentials wherever they are.
-      # Note that each systemd service gets its own ${runDir}/config.ini file.
-      ExecStartPre = mkBefore [("+"+pkgs.writeShellScript "${serviceName}-credentials" ''
-        set -x
-        # Replace values beginning with a '<' by the content of the file whose name is after.
-        gawk '{ if (match($0,/^([^=]+=)<(.+)/,m)) { getline f < m[2]; print m[1] f } else print $0 }' ${configIni} |
-        ${optionalString (!allowStripe) "gawk '!/^stripe-secret-key=/' |"}
-        install -o ${srvCfg.user} -g root -m 400 /dev/stdin ${runDir}/config.ini
-      '')];
-      # The following options are only for optimizing:
-      # systemd-analyze security
-      AmbientCapabilities = "";
-      CapabilityBoundingSet = "";
-      # ProtectClock= adds DeviceAllow=char-rtc r
-      DeviceAllow = "";
-      LockPersonality = true;
-      MemoryDenyWriteExecute = true;
-      NoNewPrivileges = true;
-      PrivateDevices = true;
-      PrivateMounts = true;
-      PrivateNetwork = mkDefault false;
-      PrivateUsers = true;
-      ProcSubset = "pid";
-      ProtectClock = true;
-      ProtectControlGroups = true;
-      ProtectHome = true;
-      ProtectHostname = true;
-      ProtectKernelLogs = true;
-      ProtectKernelModules = true;
-      ProtectKernelTunables = true;
-      ProtectProc = "invisible";
-      ProtectSystem = "strict";
-      RemoveIPC = true;
-      RestrictAddressFamilies = [ "AF_UNIX" "AF_INET" "AF_INET6" ];
-      RestrictNamespaces = true;
-      RestrictRealtime = true;
-      RestrictSUIDSGID = true;
-      #SocketBindAllow = [ "tcp:${toString srvCfg.port}" "tcp:${toString srvCfg.prometheusPort}" ];
-      #SocketBindDeny = "any";
-      SystemCallFilter = [
-        "@system-service"
-        "~@aio" "~@keyring" "~@memlock" "~@privileged" "~@timer"
-        "@chown" "@setuid"
-      ];
-      SystemCallArchitectures = "native";
-    };
-  } ];
+    mkMerge [
+      extraService
+      {
+        after = [ "network.target" ] ++
+          optional cfg.postgresql.enable "postgresql.service" ++
+          optional cfg.redis.enable "redis-sourcehut-${srvsrht}.service";
+        requires =
+          optional cfg.postgresql.enable "postgresql.service" ++
+          optional cfg.redis.enable "redis-sourcehut-${srvsrht}.service";
+        path = [ pkgs.gawk ];
+        environment.HOME = runDir;
+        serviceConfig = {
+          User = mkDefault srvCfg.user;
+          Group = mkDefault srvCfg.group;
+          RuntimeDirectory = [
+            "sourcehut/${serviceName}"
+            # Used by *srht-keys which reads ../config.ini
+            "sourcehut/${serviceName}/subdir"
+            "sourcehut/chroots/${serviceName}"
+          ];
+          RuntimeDirectoryMode = "2750";
+          # No need for the chroot path once inside the chroot
+          InaccessiblePaths = [ "-+${rootDir}" ];
+          # g+rx is for group members (eg. fcgiwrap or nginx)
+          # to read Git/Mercurial repositories, buildlogs, etc.
+          # o+x is for intermediate directories created by BindPaths= and like,
+          # as they're owned by root:root.
+          UMask = "0026";
+          RootDirectory = rootDir;
+          RootDirectoryStartOnly = true;
+          PrivateTmp = true;
+          MountAPIVFS = true;
+          # config.ini is looked up in there, before /etc/srht/config.ini
+          # Note that it fails to be set in ExecStartPre=
+          WorkingDirectory = mkDefault ("-" + runDir);
+          BindReadOnlyPaths = [
+            builtins.storeDir
+            "/etc"
+            "/run/booted-system"
+            "/run/current-system"
+            "/run/systemd"
+          ] ++
+          optional cfg.postgresql.enable "/run/postgresql" ++
+          optional cfg.redis.enable "/run/redis-sourcehut-${srvsrht}";
+          # LoadCredential= are unfortunately not available in ExecStartPre=
+          # Hence this one is run as root (the +) with RootDirectoryStartOnly=
+          # to reach credentials wherever they are.
+          # Note that each systemd service gets its own ${runDir}/config.ini file.
+          ExecStartPre = mkBefore [
+            ("+" + pkgs.writeShellScript "${serviceName}-credentials" ''
+              set -x
+              # Replace values beginning with a '<' by the content of the file whose name is after.
+              gawk '{ if (match($0,/^([^=]+=)<(.+)/,m)) { getline f < m[2]; print m[1] f } else print $0 }' ${configIni} |
+              ${optionalString (!allowStripe) "gawk '!/^stripe-secret-key=/' |"}
+              install -o ${srvCfg.user} -g root -m 400 /dev/stdin ${runDir}/config.ini
+            '')
+          ];
+          # The following options are only for optimizing:
+          # systemd-analyze security
+          AmbientCapabilities = "";
+          CapabilityBoundingSet = "";
+          # ProtectClock= adds DeviceAllow=char-rtc r
+          DeviceAllow = "";
+          LockPersonality = true;
+          MemoryDenyWriteExecute = true;
+          NoNewPrivileges = true;
+          PrivateDevices = true;
+          PrivateMounts = true;
+          PrivateNetwork = mkDefault false;
+          PrivateUsers = true;
+          ProcSubset = "pid";
+          ProtectClock = true;
+          ProtectControlGroups = true;
+          ProtectHome = true;
+          ProtectHostname = true;
+          ProtectKernelLogs = true;
+          ProtectKernelModules = true;
+          ProtectKernelTunables = true;
+          ProtectProc = "invisible";
+          ProtectSystem = "strict";
+          RemoveIPC = true;
+          RestrictAddressFamilies = [ "AF_UNIX" "AF_INET" "AF_INET6" ];
+          RestrictNamespaces = true;
+          RestrictRealtime = true;
+          RestrictSUIDSGID = true;
+          #SocketBindAllow = [ "tcp:${toString srvCfg.port}" "tcp:${toString srvCfg.prometheusPort}" ];
+          #SocketBindDeny = "any";
+          SystemCallFilter = [
+            "@system-service"
+            "~@aio"
+            "~@keyring"
+            "~@memlock"
+            "~@privileged"
+            "~@timer"
+            "@chown"
+            "@setuid"
+          ];
+          SystemCallArchitectures = "native";
+        };
+      }
+    ];
 in
 {
   options.services.sourcehut.${srv} = {
@@ -173,7 +189,7 @@ in
     gunicorn = {
       extraArgs = mkOption {
         type = with types; listOf str;
-        default = ["--timeout 120" "--workers 1" "--log-level=info"];
+        default = [ "--timeout 120" "--workers 1" "--log-level=info" ];
         description = lib.mdDoc "Extra arguments passed to Gunicorn.";
       };
     };
@@ -181,7 +197,7 @@ in
     webhooks = {
       extraArgs = mkOption {
         type = with types; listOf str;
-        default = ["--loglevel DEBUG" "--pool eventlet" "--without-heartbeat"];
+        default = [ "--loglevel DEBUG" "--pool eventlet" "--without-heartbeat" ];
         description = lib.mdDoc "Extra arguments passed to the Celery responsible for webhooks.";
       };
       celeryConfig = mkOption {
@@ -192,216 +208,237 @@ in
     };
   };
 
-  config = lib.mkIf (cfg.enable && srvCfg.enable) (mkMerge [ extraConfig {
-    users = {
+  config = lib.mkIf (cfg.enable && srvCfg.enable) (mkMerge [
+    extraConfig
+    {
       users = {
-        "${srvCfg.user}" = {
-          isSystemUser = true;
-          group = mkDefault srvCfg.group;
-          description = mkDefault "sourcehut user for ${srv}.sr.ht";
+        users = {
+          "${srvCfg.user}" = {
+            isSystemUser = true;
+            group = mkDefault srvCfg.group;
+            description = mkDefault "sourcehut user for ${srv}.sr.ht";
+          };
         };
+        groups = {
+          "${srvCfg.group}" = { };
+        } // optionalAttrs
+          (cfg.postgresql.enable
+            && hasSuffix "0" (postgresql.settings.unix_socket_permissions or ""))
+          {
+            "postgres".members = [ srvCfg.user ];
+          } // optionalAttrs
+          (cfg.redis.enable
+            && hasSuffix "0" (redis.settings.unixsocketperm or ""))
+          {
+            "redis-sourcehut-${srvsrht}".members = [ srvCfg.user ];
+          };
       };
-      groups = {
-        "${srvCfg.group}" = { };
-      } // optionalAttrs (cfg.postgresql.enable
-        && hasSuffix "0" (postgresql.settings.unix_socket_permissions or "")) {
-        "postgres".members = [ srvCfg.user ];
-      } // optionalAttrs (cfg.redis.enable
-        && hasSuffix "0" (redis.settings.unixsocketperm or "")) {
-        "redis-sourcehut-${srvsrht}".members = [ srvCfg.user ];
-      };
-    };
 
-    services.nginx = mkIf cfg.nginx.enable {
-      virtualHosts."${srv}.${cfg.settings."sr.ht".global-domain}" = mkMerge [ {
-        forceSSL = mkDefault true;
-        locations."/".proxyPass = "http://${cfg.listenAddress}:${toString srvCfg.port}";
-        locations."/static" = {
-          root = "${pkgs.sourcehut.${srvsrht}}/${pkgs.sourcehut.python.sitePackages}/${srvsrht}";
-          extraConfig = mkDefault ''
-            expires 30d;
-          '';
-        };
-        locations."/query" = mkIf (cfg.settings.${iniKey} ? api-origin) {
-          proxyPass = cfg.settings.${iniKey}.api-origin;
-          extraConfig = ''
-            add_header 'Access-Control-Allow-Origin' '*';
-            add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
-            add_header 'Access-Control-Allow-Headers' 'User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
+      services.nginx = mkIf cfg.nginx.enable {
+        virtualHosts."${srv}.${cfg.settings."sr.ht".global-domain}" = mkMerge [{
+          forceSSL = mkDefault true;
+          locations."/".proxyPass = "http://${cfg.listenAddress}:${toString srvCfg.port}";
+          locations."/static" = {
+            root = "${pkgs.sourcehut.${srvsrht}}/${pkgs.sourcehut.python.sitePackages}/${srvsrht}";
+            extraConfig = mkDefault ''
+              expires 30d;
+            '';
+          };
+          locations."/query" = mkIf (cfg.settings.${iniKey} ? api-origin) {
+            proxyPass = cfg.settings.${iniKey}.api-origin;
+            extraConfig = ''
+              add_header 'Access-Control-Allow-Origin' '*';
+              add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
+              add_header 'Access-Control-Allow-Headers' 'User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
 
-            if ($request_method = 'OPTIONS') {
-              add_header 'Access-Control-Max-Age' 1728000;
-              add_header 'Content-Type' 'text/plain; charset=utf-8';
-              add_header 'Content-Length' 0;
-              return 204;
-            }
+              if ($request_method = 'OPTIONS') {
+                add_header 'Access-Control-Max-Age' 1728000;
+                add_header 'Content-Type' 'text/plain; charset=utf-8';
+                add_header 'Content-Length' 0;
+                return 204;
+              }
 
-            add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
-          '';
-        };
-      } cfg.nginx.virtualHost ];
-    };
+              add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
+            '';
+          };
+        }
+          cfg.nginx.virtualHost];
+      };
 
-    services.postgresql = mkIf cfg.postgresql.enable {
-      authentication = ''
-        local ${srvCfg.postgresql.database} ${srvCfg.user} trust
-      '';
-      ensureDatabases = [ srvCfg.postgresql.database ];
-      ensureUsers = map (name: {
-          inherit name;
-          # We don't use it because we have a special default database name with dots.
-          # TODO(for maintainers of sourcehut): migrate away from custom preStart script.
-          ensureDBOwnership = false;
-        }) [srvCfg.user];
-    };
+      services.postgresql = mkIf cfg.postgresql.enable {
+        authentication = ''
+          local ${srvCfg.postgresql.database} ${srvCfg.user} trust
+        '';
+        ensureDatabases = [ srvCfg.postgresql.database ];
+        ensureUsers = map
+          (name: {
+            inherit name;
+            # We don't use it because we have a special default database name with dots.
+            # TODO(for maintainers of sourcehut): migrate away from custom preStart script.
+            ensureDBOwnership = false;
+          }) [ srvCfg.user ];
+      };
 
 
-    services.sourcehut.settings = mkMerge [
-      {
-        "${srv}.sr.ht".origin = mkDefault "https://${srv}.${cfg.settings."sr.ht".global-domain}";
-      }
+      services.sourcehut.settings = mkMerge [
+        {
+          "${srv}.sr.ht".origin = mkDefault "https://${srv}.${cfg.settings."sr.ht".global-domain}";
+        }
 
-      (mkIf cfg.postgresql.enable {
-        "${srv}.sr.ht".connection-string = mkDefault "postgresql:///${srvCfg.postgresql.database}?user=${srvCfg.user}&host=/run/postgresql";
-      })
-    ];
+        (mkIf cfg.postgresql.enable {
+          "${srv}.sr.ht".connection-string = mkDefault "postgresql:///${srvCfg.postgresql.database}?user=${srvCfg.user}&host=/run/postgresql";
+        })
+      ];
 
-    services.redis.servers."sourcehut-${srvsrht}" = mkIf cfg.redis.enable {
-      enable = true;
-      databases = 3;
-      syslog = true;
-      # TODO: set a more informed value
-      save = mkDefault [ [1800 10] [300 100] ];
-      settings = {
+      services.redis.servers."sourcehut-${srvsrht}" = mkIf cfg.redis.enable {
+        enable = true;
+        databases = 3;
+        syslog = true;
         # TODO: set a more informed value
-        maxmemory = "128MB";
-        maxmemory-policy = "volatile-ttl";
+        save = mkDefault [ [ 1800 10 ] [ 300 100 ] ];
+        settings = {
+          # TODO: set a more informed value
+          maxmemory = "128MB";
+          maxmemory-policy = "volatile-ttl";
+        };
       };
-    };
 
-    systemd.services = mkMerge [
-      {
-        "${srvsrht}" = baseService srvsrht { allowStripe = srv == "meta"; } (mkMerge [
+      systemd.services = mkMerge [
         {
-          description = "sourcehut ${srv}.sr.ht website service";
-          before = optional cfg.nginx.enable "nginx.service";
-          wants = optional cfg.nginx.enable "nginx.service";
-          wantedBy = [ "multi-user.target" ];
-          path = optional cfg.postgresql.enable postgresql.package;
-          # Beware: change in credentials' content will not trigger restart.
-          restartTriggers = [ configIni ];
-          serviceConfig = {
-            Type = "simple";
-            Restart = mkDefault "always";
-            #RestartSec = mkDefault "2min";
-            StateDirectory = [ "sourcehut/${srvsrht}" ];
-            StateDirectoryMode = "2750";
-            ExecStart = "${cfg.python}/bin/gunicorn ${srvsrht}.app:app --name ${srvsrht} --bind ${cfg.listenAddress}:${toString srvCfg.port} " + concatStringsSep " " srvCfg.gunicorn.extraArgs;
-          };
-          preStart = let
-            version = pkgs.sourcehut.${srvsrht}.version;
-            stateDir = "/var/lib/sourcehut/${srvsrht}";
-            in mkBefore ''
-            set -x
-            # Use the /run/sourcehut/${srvsrht}/config.ini
-            # installed by a previous ExecStartPre= in baseService
-            cd /run/sourcehut/${srvsrht}
+          "${srvsrht}" = baseService srvsrht { allowStripe = srv == "meta"; } (mkMerge [
+            {
+              description = "sourcehut ${srv}.sr.ht website service";
+              before = optional cfg.nginx.enable "nginx.service";
+              wants = optional cfg.nginx.enable "nginx.service";
+              wantedBy = [ "multi-user.target" ];
+              path = optional cfg.postgresql.enable postgresql.package;
+              # Beware: change in credentials' content will not trigger restart.
+              restartTriggers = [ configIni ];
+              serviceConfig = {
+                Type = "simple";
+                Restart = mkDefault "always";
+                #RestartSec = mkDefault "2min";
+                StateDirectory = [ "sourcehut/${srvsrht}" ];
+                StateDirectoryMode = "2750";
+                ExecStart = "${cfg.python}/bin/gunicorn ${srvsrht}.app:app --name ${srvsrht} --bind ${cfg.listenAddress}:${toString srvCfg.port} " + concatStringsSep " " srvCfg.gunicorn.extraArgs;
+              };
+              preStart =
+                let
+                  version = pkgs.sourcehut.${srvsrht}.version;
+                  stateDir = "/var/lib/sourcehut/${srvsrht}";
+                in
+                mkBefore ''
+                  set -x
+                  # Use the /run/sourcehut/${srvsrht}/config.ini
+                  # installed by a previous ExecStartPre= in baseService
+                  cd /run/sourcehut/${srvsrht}
 
-            if test ! -e ${stateDir}/db; then
-              # Setup the initial database.
-              # Note that it stamps the alembic head afterward
-              ${cfg.python}/bin/${srvsrht}-initdb
-              echo ${version} >${stateDir}/db
-            fi
+                  if test ! -e ${stateDir}/db; then
+                    # Setup the initial database.
+                    # Note that it stamps the alembic head afterward
+                    ${cfg.python}/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
-                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
+                      echo ${version} >${stateDir}/db
+                    fi
+                  ''}
 
-            # Update copy of each users' profile to the latest
-            # See https://lists.sr.ht/~sircmpwn/sr.ht-admins/<20190302181207.GA13778%40cirno.my.domain>
-            if test ! -e ${stateDir}/webhook; then
-              # Update ${iniKey}'s users' profile copy to the latest
-              ${cfg.python}/bin/srht-update-profiles ${iniKey}
-              touch ${stateDir}/webhook
-            fi
-          '';
-        } mainService ]);
-      }
+                  # Update copy of each users' profile to the latest
+                  # See https://lists.sr.ht/~sircmpwn/sr.ht-admins/<20190302181207.GA13778%40cirno.my.domain>
+                  if test ! -e ${stateDir}/webhook; then
+                    # Update ${iniKey}'s users' profile copy to the latest
+                    ${cfg.python}/bin/srht-update-profiles ${iniKey}
+                    touch ${stateDir}/webhook
+                  fi
+                '';
+            }
+            mainService
+          ]);
+        }
 
-      (mkIf webhooks {
-        "${srvsrht}-webhooks" = baseService "${srvsrht}-webhooks" {}
-          {
-            description = "sourcehut ${srv}.sr.ht webhooks service";
-            after = [ "${srvsrht}.service" ];
-            wantedBy = [ "${srvsrht}.service" ];
-            partOf = [ "${srvsrht}.service" ];
-            preStart = ''
-              cp ${pkgs.writeText "${srvsrht}-webhooks-celeryconfig.py" srvCfg.webhooks.celeryConfig} \
-                 /run/sourcehut/${srvsrht}-webhooks/celeryconfig.py
-            '';
-            serviceConfig = {
-              Type = "simple";
-              Restart = "always";
-              ExecStart = "${cfg.python}/bin/celery --app ${srvsrht}.webhooks worker --hostname ${srvsrht}-webhooks@%%h " + concatStringsSep " " srvCfg.webhooks.extraArgs;
-              # Avoid crashing: os.getloadavg()
-              ProcSubset = mkForce "all";
+        (mkIf webhooks {
+          "${srvsrht}-webhooks" = baseService "${srvsrht}-webhooks" { }
+            {
+              description = "sourcehut ${srv}.sr.ht webhooks service";
+              after = [ "${srvsrht}.service" ];
+              wantedBy = [ "${srvsrht}.service" ];
+              partOf = [ "${srvsrht}.service" ];
+              preStart = ''
+                cp ${pkgs.writeText "${srvsrht}-webhooks-celeryconfig.py" srvCfg.webhooks.celeryConfig} \
+                   /run/sourcehut/${srvsrht}-webhooks/celeryconfig.py
+              '';
+              serviceConfig = {
+                Type = "simple";
+                Restart = "always";
+                ExecStart = "${cfg.python}/bin/celery --app ${srvsrht}.webhooks worker --hostname ${srvsrht}-webhooks@%%h " + concatStringsSep " " srvCfg.webhooks.extraArgs;
+                # Avoid crashing: os.getloadavg()
+                ProcSubset = mkForce "all";
+              };
             };
-          };
-      })
+        })
 
-      (mapAttrs (timerName: timer: (baseService timerName {} (mkMerge [
-        {
-          description = "sourcehut ${timerName} service";
-          after = [ "network.target" "${srvsrht}.service" ];
-          serviceConfig = {
-            Type = "oneshot";
-            ExecStart = "${cfg.python}/bin/${timerName}";
-          };
-        }
-        (timer.service or {})
-      ]))) extraTimers)
+        (mapAttrs
+          (timerName: timer: (baseService timerName { } (mkMerge [
+            {
+              description = "sourcehut ${timerName} service";
+              after = [ "network.target" "${srvsrht}.service" ];
+              serviceConfig = {
+                Type = "oneshot";
+                ExecStart = "${cfg.python}/bin/${timerName}";
+              };
+            }
+            (timer.service or { })
+          ])))
+          extraTimers)
 
-      (mapAttrs (serviceName: extraService: baseService serviceName {} (mkMerge [
-        {
-          description = "sourcehut ${serviceName} service";
-          # So that extraServices have the PostgreSQL database initialized.
-          after = [ "${srvsrht}.service" ];
-          wantedBy = [ "${srvsrht}.service" ];
-          partOf = [ "${srvsrht}.service" ];
-          serviceConfig = {
-            Type = "simple";
-            Restart = mkDefault "always";
-          };
-        }
-        extraService
-      ])) extraServices)
+        (mapAttrs
+          (serviceName: extraService: baseService serviceName { } (mkMerge [
+            {
+              description = "sourcehut ${serviceName} service";
+              # So that extraServices have the PostgreSQL database initialized.
+              after = [ "${srvsrht}.service" ];
+              wantedBy = [ "${srvsrht}.service" ];
+              partOf = [ "${srvsrht}.service" ];
+              serviceConfig = {
+                Type = "simple";
+                Restart = mkDefault "always";
+              };
+            }
+            extraService
+          ]))
+          extraServices)
 
-      # Work around 'pq: permission denied for schema public' with postgres v15.
-      # See https://github.com/NixOS/nixpkgs/issues/216989
-      # Workaround taken from nixos/forgejo: https://github.com/NixOS/nixpkgs/pull/262741
-      # TODO(to maintainers of sourcehut): please migrate away from this workaround
-      # by migrating away from database name defaults with dots.
-      (lib.mkIf (
-          cfg.postgresql.enable
-          && lib.strings.versionAtLeast config.services.postgresql.package.version "15.0"
-        ) {
-          postgresql.postStart = (lib.mkAfter ''
-            $PSQL -tAc 'ALTER DATABASE "${srvCfg.postgresql.database}" OWNER TO "${srvCfg.user}";'
-          '');
-        }
-      )
-    ];
+        # Work around 'pq: permission denied for schema public' with postgres v15.
+        # See https://github.com/NixOS/nixpkgs/issues/216989
+        # Workaround taken from nixos/forgejo: https://github.com/NixOS/nixpkgs/pull/262741
+        # TODO(to maintainers of sourcehut): please migrate away from this workaround
+        # by migrating away from database name defaults with dots.
+        (lib.mkIf
+          (
+            cfg.postgresql.enable
+            && lib.strings.versionAtLeast config.services.postgresql.package.version "15.0"
+          )
+          {
+            postgresql.postStart = (lib.mkAfter ''
+              $PSQL -tAc 'ALTER DATABASE "${srvCfg.postgresql.database}" OWNER TO "${srvCfg.user}";'
+            '');
+          }
+        )
+      ];
 
-    systemd.timers = mapAttrs (timerName: timer:
-      {
-        description = "sourcehut timer for ${timerName}";
-        wantedBy = [ "timers.target" ];
-        inherit (timer) timerConfig;
-      }) extraTimers;
-  } ]);
+      systemd.timers = mapAttrs
+        (timerName: timer:
+          {
+            description = "sourcehut timer for ${timerName}";
+            wantedBy = [ "timers.target" ];
+            inherit (timer) timerConfig;
+          })
+        extraTimers;
+    }
+  ]);
 }
diff --git a/nixpkgs/nixos/modules/services/misc/spice-autorandr.nix b/nixpkgs/nixos/modules/services/misc/spice-autorandr.nix
index 8437441c752a..0d8830dbd5be 100644
--- a/nixpkgs/nixos/modules/services/misc/spice-autorandr.nix
+++ b/nixpkgs/nixos/modules/services/misc/spice-autorandr.nix
@@ -7,7 +7,7 @@ in
   options = {
     services.spice-autorandr = {
       enable = lib.mkEnableOption (lib.mdDoc "spice-autorandr service that will automatically resize display to match SPICE client window size.");
-      package = lib.mkPackageOptionMD pkgs "spice-autorandr" { };
+      package = lib.mkPackageOption pkgs "spice-autorandr" { };
     };
   };
 
diff --git a/nixpkgs/nixos/modules/services/misc/spice-webdavd.nix b/nixpkgs/nixos/modules/services/misc/spice-webdavd.nix
index 6c817e429ac6..2b4304365618 100644
--- a/nixpkgs/nixos/modules/services/misc/spice-webdavd.nix
+++ b/nixpkgs/nixos/modules/services/misc/spice-webdavd.nix
@@ -9,12 +9,7 @@ in
     services.spice-webdavd = {
       enable = mkEnableOption (lib.mdDoc "the spice guest webdav proxy daemon");
 
-      package = mkOption {
-        default = pkgs.phodav;
-        defaultText = literalExpression "pkgs.phodav";
-        type = types.package;
-        description = lib.mdDoc "spice-webdavd provider package to use.";
-      };
+      package = mkPackageOption pkgs "phodav" { };
     };
   };
 
diff --git a/nixpkgs/nixos/modules/services/misc/tandoor-recipes.nix b/nixpkgs/nixos/modules/services/misc/tandoor-recipes.nix
index 63d3e3d2a857..2d7d29b2e717 100644
--- a/nixpkgs/nixos/modules/services/misc/tandoor-recipes.nix
+++ b/nixpkgs/nixos/modules/services/misc/tandoor-recipes.nix
@@ -71,12 +71,7 @@ in
       };
     };
 
-    package = mkOption {
-      type = types.package;
-      default = pkgs.tandoor-recipes;
-      defaultText = literalExpression "pkgs.tandoor-recipes";
-      description = lib.mdDoc "The Tandoor Recipes package to use.";
-    };
+    package = mkPackageOption pkgs "tandoor-recipes" { };
   };
 
   config = mkIf cfg.enable {
diff --git a/nixpkgs/nixos/modules/services/misc/tautulli.nix b/nixpkgs/nixos/modules/services/misc/tautulli.nix
index b29e9dc0c8d5..e379628c8ce6 100644
--- a/nixpkgs/nixos/modules/services/misc/tautulli.nix
+++ b/nixpkgs/nixos/modules/services/misc/tautulli.nix
@@ -50,14 +50,7 @@ in
         description = lib.mdDoc "Group under which Tautulli runs.";
       };
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.tautulli;
-        defaultText = literalExpression "pkgs.tautulli";
-        description = lib.mdDoc ''
-          The Tautulli package to use.
-        '';
-      };
+      package = mkPackageOption pkgs "tautulli" { };
     };
   };
 
diff --git a/nixpkgs/nixos/modules/services/misc/tp-auto-kbbl.nix b/nixpkgs/nixos/modules/services/misc/tp-auto-kbbl.nix
index 1076c814e86c..f6f2d49733e6 100644
--- a/nixpkgs/nixos/modules/services/misc/tp-auto-kbbl.nix
+++ b/nixpkgs/nixos/modules/services/misc/tp-auto-kbbl.nix
@@ -11,12 +11,7 @@ in {
     services.tp-auto-kbbl = {
       enable = mkEnableOption (lib.mdDoc "auto toggle keyboard back-lighting on Thinkpads (and maybe other laptops) for Linux");
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.tp-auto-kbbl;
-        defaultText = literalExpression "pkgs.tp-auto-kbbl";
-        description = lib.mdDoc "Package providing {command}`tp-auto-kbbl`.";
-      };
+      package = mkPackageOption pkgs "tp-auto-kbbl" { };
 
       arguments = mkOption {
         type = types.listOf types.str;
diff --git a/nixpkgs/nixos/modules/services/misc/xmrig.nix b/nixpkgs/nixos/modules/services/misc/xmrig.nix
index f75b47ffeced..8ad2d049f8a9 100644
--- a/nixpkgs/nixos/modules/services/misc/xmrig.nix
+++ b/nixpkgs/nixos/modules/services/misc/xmrig.nix
@@ -15,12 +15,8 @@ with lib;
     services.xmrig = {
       enable = mkEnableOption (lib.mdDoc "XMRig Mining Software");
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.xmrig;
-        defaultText = literalExpression "pkgs.xmrig";
-        example = literalExpression "pkgs.xmrig-mo";
-        description = lib.mdDoc "XMRig package to use.";
+      package = mkPackageOption pkgs "xmrig" {
+        example = "xmrig-mo";
       };
 
       settings = mkOption {
diff --git a/nixpkgs/nixos/modules/services/misc/zookeeper.nix b/nixpkgs/nixos/modules/services/misc/zookeeper.nix
index fb51be698e72..b1c0b80648c6 100644
--- a/nixpkgs/nixos/modules/services/misc/zookeeper.nix
+++ b/nixpkgs/nixos/modules/services/misc/zookeeper.nix
@@ -103,12 +103,7 @@ in {
       '';
     };
 
-    package = mkOption {
-      description = lib.mdDoc "The zookeeper package to use";
-      default = pkgs.zookeeper;
-      defaultText = literalExpression "pkgs.zookeeper";
-      type = types.package;
-    };
+    package = mkPackageOption pkgs "zookeeper" { };
 
     jre = mkOption {
       description = lib.mdDoc "The JRE with which to run Zookeeper";
diff --git a/nixpkgs/nixos/modules/services/monitoring/arbtt.nix b/nixpkgs/nixos/modules/services/monitoring/arbtt.nix
index f07ecc5d5dd0..a1a228d6e420 100644
--- a/nixpkgs/nixos/modules/services/monitoring/arbtt.nix
+++ b/nixpkgs/nixos/modules/services/monitoring/arbtt.nix
@@ -9,14 +9,7 @@ in {
     services.arbtt = {
       enable = mkEnableOption (lib.mdDoc "Arbtt statistics capture service");
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.haskellPackages.arbtt;
-        defaultText = literalExpression "pkgs.haskellPackages.arbtt";
-        description = lib.mdDoc ''
-          The package to use for the arbtt binaries.
-        '';
-      };
+      package = mkPackageOption pkgs [ "haskellPackages" "arbtt" ] { };
 
       logFile = mkOption {
         type = types.str;
diff --git a/nixpkgs/nixos/modules/services/monitoring/bosun.nix b/nixpkgs/nixos/modules/services/monitoring/bosun.nix
index 1dc19743461b..fb412d43ec27 100644
--- a/nixpkgs/nixos/modules/services/monitoring/bosun.nix
+++ b/nixpkgs/nixos/modules/services/monitoring/bosun.nix
@@ -24,14 +24,7 @@ in {
 
       enable = mkEnableOption (lib.mdDoc "bosun");
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.bosun;
-        defaultText = literalExpression "pkgs.bosun";
-        description = lib.mdDoc ''
-          bosun binary to use.
-        '';
-      };
+      package = mkPackageOption pkgs "bosun" { };
 
       user = mkOption {
         type = types.str;
diff --git a/nixpkgs/nixos/modules/services/monitoring/certspotter.nix b/nixpkgs/nixos/modules/services/monitoring/certspotter.nix
index aafa29daa872..5551f0e37c51 100644
--- a/nixpkgs/nixos/modules/services/monitoring/certspotter.nix
+++ b/nixpkgs/nixos/modules/services/monitoring/certspotter.nix
@@ -28,7 +28,7 @@ in
   options.services.certspotter = {
     enable = lib.mkEnableOption "Cert Spotter, a Certificate Transparency log monitor";
 
-    package = lib.mkPackageOptionMD pkgs "certspotter" { };
+    package = lib.mkPackageOption pkgs "certspotter" { };
 
     startAtEnd = lib.mkOption {
       type = lib.types.bool;
diff --git a/nixpkgs/nixos/modules/services/monitoring/cockpit.nix b/nixpkgs/nixos/modules/services/monitoring/cockpit.nix
index 2947b4d80120..45389a3174e1 100644
--- a/nixpkgs/nixos/modules/services/monitoring/cockpit.nix
+++ b/nixpkgs/nixos/modules/services/monitoring/cockpit.nix
@@ -2,14 +2,14 @@
 
 let
   cfg = config.services.cockpit;
-  inherit (lib) types mkEnableOption mkOption mkIf mdDoc literalMD mkPackageOptionMD;
+  inherit (lib) types mkEnableOption mkOption mkIf mdDoc literalMD mkPackageOption;
   settingsFormat = pkgs.formats.ini {};
 in {
   options = {
     services.cockpit = {
       enable = mkEnableOption (mdDoc "Cockpit");
 
-      package = mkPackageOptionMD pkgs "Cockpit" {
+      package = mkPackageOption pkgs "Cockpit" {
         default = [ "cockpit" ];
       };
 
diff --git a/nixpkgs/nixos/modules/services/monitoring/collectd.nix b/nixpkgs/nixos/modules/services/monitoring/collectd.nix
index 5d525995c67a..3e62ef422bad 100644
--- a/nixpkgs/nixos/modules/services/monitoring/collectd.nix
+++ b/nixpkgs/nixos/modules/services/monitoring/collectd.nix
@@ -41,14 +41,7 @@ in {
       type = types.bool;
     };
 
-    package = mkOption {
-      default = pkgs.collectd;
-      defaultText = literalExpression "pkgs.collectd";
-      description = lib.mdDoc ''
-        Which collectd package to use.
-      '';
-      type = types.package;
-    };
+    package = mkPackageOption pkgs "collectd" { };
 
     buildMinimalPackage = mkOption {
       default = false;
diff --git a/nixpkgs/nixos/modules/services/monitoring/datadog-agent.nix b/nixpkgs/nixos/modules/services/monitoring/datadog-agent.nix
index 1736b0c088a3..7b07c80c8d7b 100644
--- a/nixpkgs/nixos/modules/services/monitoring/datadog-agent.nix
+++ b/nixpkgs/nixos/modules/services/monitoring/datadog-agent.nix
@@ -51,16 +51,13 @@ in {
   options.services.datadog-agent = {
     enable = mkEnableOption (lib.mdDoc "Datadog-agent v7 monitoring service");
 
-    package = mkOption {
-      default = pkgs.datadog-agent;
-      defaultText = literalExpression "pkgs.datadog-agent";
-      description = lib.mdDoc ''
-        Which DataDog v7 agent package to use. Note that the provided
-        package is expected to have an overridable `pythonPackages`-attribute
-        which configures the Python environment with the Datadog
-        checks.
+    package = mkPackageOption pkgs "datadog-agent" {
+      extraDescription = ''
+        ::: {.note}
+        The provided package is expected to have an overridable `pythonPackages`-attribute
+        which configures the Python environment with the Datadog checks.
+        :::
       '';
-      type = types.package;
     };
 
     apiKeyFile = mkOption {
diff --git a/nixpkgs/nixos/modules/services/monitoring/goss.nix b/nixpkgs/nixos/modules/services/monitoring/goss.nix
index 64a8dad0703e..1b973bbbf45c 100644
--- a/nixpkgs/nixos/modules/services/monitoring/goss.nix
+++ b/nixpkgs/nixos/modules/services/monitoring/goss.nix
@@ -16,7 +16,7 @@ in {
     services.goss = {
       enable = lib.mkEnableOption (lib.mdDoc "Goss daemon");
 
-      package = lib.mkPackageOptionMD pkgs "goss" { };
+      package = lib.mkPackageOption pkgs "goss" { };
 
       environment = lib.mkOption {
         type = lib.types.attrsOf lib.types.str;
diff --git a/nixpkgs/nixos/modules/services/monitoring/grafana-agent.nix b/nixpkgs/nixos/modules/services/monitoring/grafana-agent.nix
index 13604ff77c68..e8d38a453176 100644
--- a/nixpkgs/nixos/modules/services/monitoring/grafana-agent.nix
+++ b/nixpkgs/nixos/modules/services/monitoring/grafana-agent.nix
@@ -13,7 +13,7 @@ in
   options.services.grafana-agent = {
     enable = mkEnableOption (lib.mdDoc "grafana-agent");
 
-    package = mkPackageOptionMD pkgs "grafana-agent" { };
+    package = mkPackageOption pkgs "grafana-agent" { };
 
     credentials = mkOption {
       description = lib.mdDoc ''
diff --git a/nixpkgs/nixos/modules/services/monitoring/grafana.nix b/nixpkgs/nixos/modules/services/monitoring/grafana.nix
index f84d677f14d8..62c50490ee99 100644
--- a/nixpkgs/nixos/modules/services/monitoring/grafana.nix
+++ b/nixpkgs/nixos/modules/services/monitoring/grafana.nix
@@ -310,12 +310,7 @@ in
       apply = x: if isList x then lib.unique x else x;
     };
 
-    package = mkOption {
-      description = lib.mdDoc "Package to use.";
-      default = pkgs.grafana;
-      defaultText = literalExpression "pkgs.grafana";
-      type = types.package;
-    };
+    package = mkPackageOption pkgs "grafana" { };
 
     dataDir = mkOption {
       description = lib.mdDoc "Data directory.";
diff --git a/nixpkgs/nixos/modules/services/monitoring/heapster.nix b/nixpkgs/nixos/modules/services/monitoring/heapster.nix
index fc63276b62f7..9f9c24949fc9 100644
--- a/nixpkgs/nixos/modules/services/monitoring/heapster.nix
+++ b/nixpkgs/nixos/modules/services/monitoring/heapster.nix
@@ -26,12 +26,7 @@ in {
       type = types.separatedString " ";
     };
 
-    package = mkOption {
-      description = lib.mdDoc "Package to use by heapster";
-      default = pkgs.heapster;
-      defaultText = literalExpression "pkgs.heapster";
-      type = types.package;
-    };
+    package = mkPackageOption pkgs "heapster" { };
   };
 
   config = mkIf cfg.enable {
diff --git a/nixpkgs/nixos/modules/services/monitoring/karma.nix b/nixpkgs/nixos/modules/services/monitoring/karma.nix
index 85dbc81f443f..9883ec4fe841 100644
--- a/nixpkgs/nixos/modules/services/monitoring/karma.nix
+++ b/nixpkgs/nixos/modules/services/monitoring/karma.nix
@@ -8,14 +8,7 @@ in
   options.services.karma = {
     enable = mkEnableOption (mdDoc "the Karma dashboard service");
 
-    package = mkOption {
-      type = types.package;
-      default = pkgs.karma;
-      defaultText = literalExpression "pkgs.karma";
-      description = mdDoc ''
-        The Karma package that should be used.
-      '';
-    };
+    package = mkPackageOption pkgs "karma" { };
 
     configFile = mkOption {
       type = types.path;
diff --git a/nixpkgs/nixos/modules/services/monitoring/kthxbye.nix b/nixpkgs/nixos/modules/services/monitoring/kthxbye.nix
index 3f988dcb722f..3be002445722 100644
--- a/nixpkgs/nixos/modules/services/monitoring/kthxbye.nix
+++ b/nixpkgs/nixos/modules/services/monitoring/kthxbye.nix
@@ -9,14 +9,7 @@ in
   options.services.kthxbye = {
     enable = mkEnableOption (mdDoc "kthxbye alert acknowledgement management daemon");
 
-    package = mkOption {
-      type = types.package;
-      default = pkgs.kthxbye;
-      defaultText = literalExpression "pkgs.kthxbye";
-      description = mdDoc ''
-        The kthxbye package that should be used.
-      '';
-    };
+    package = mkPackageOption pkgs "kthxbye" { };
 
     openFirewall = mkOption {
       type = types.bool;
diff --git a/nixpkgs/nixos/modules/services/monitoring/loki.nix b/nixpkgs/nixos/modules/services/monitoring/loki.nix
index f3b97e9151ea..fade3c4fbad3 100644
--- a/nixpkgs/nixos/modules/services/monitoring/loki.nix
+++ b/nixpkgs/nixos/modules/services/monitoring/loki.nix
@@ -22,7 +22,7 @@ in {
       '';
     };
 
-    package = lib.mkPackageOptionMD pkgs "grafana-loki" { };
+    package = lib.mkPackageOption pkgs "grafana-loki" { };
 
     group = mkOption {
       type = types.str;
diff --git a/nixpkgs/nixos/modules/services/monitoring/metricbeat.nix b/nixpkgs/nixos/modules/services/monitoring/metricbeat.nix
index 310c9d8ed509..c3320f695564 100644
--- a/nixpkgs/nixos/modules/services/monitoring/metricbeat.nix
+++ b/nixpkgs/nixos/modules/services/monitoring/metricbeat.nix
@@ -5,6 +5,7 @@ let
     attrValues
     literalExpression
     mkEnableOption
+    mkPackageOption
     mkIf
     mkOption
     types
@@ -21,14 +22,8 @@ in
 
       enable = mkEnableOption (lib.mdDoc "metricbeat");
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.metricbeat;
-        defaultText = literalExpression "pkgs.metricbeat";
-        example = literalExpression "pkgs.metricbeat7";
-        description = lib.mdDoc ''
-          The metricbeat package to use
-        '';
+      package = mkPackageOption pkgs "metricbeat" {
+        example = "metricbeat7";
       };
 
       modules = mkOption {
diff --git a/nixpkgs/nixos/modules/services/monitoring/mimir.nix b/nixpkgs/nixos/modules/services/monitoring/mimir.nix
index 6ed139b22974..117cbf6a4a8c 100644
--- a/nixpkgs/nixos/modules/services/monitoring/mimir.nix
+++ b/nixpkgs/nixos/modules/services/monitoring/mimir.nix
@@ -1,7 +1,7 @@
 { config, lib, pkgs, ... }:
 
 let
-  inherit (lib) escapeShellArgs mkEnableOption mkIf mkOption types;
+  inherit (lib) escapeShellArgs mkEnableOption mkPackageOption mkIf mkOption types;
 
   cfg = config.services.mimir;
 
@@ -26,12 +26,7 @@ in {
       '';
     };
 
-    package = mkOption {
-      default = pkgs.mimir;
-      defaultText = lib.literalExpression "pkgs.mimir";
-      type = types.package;
-      description = lib.mdDoc ''Mimir package to use.'';
-    };
+    package = mkPackageOption pkgs "mimir" { };
 
     extraFlags = mkOption {
       type = types.listOf types.str;
diff --git a/nixpkgs/nixos/modules/services/monitoring/netdata.nix b/nixpkgs/nixos/modules/services/monitoring/netdata.nix
index de0e044453ee..78b12537e27f 100644
--- a/nixpkgs/nixos/modules/services/monitoring/netdata.nix
+++ b/nixpkgs/nixos/modules/services/monitoring/netdata.nix
@@ -52,12 +52,7 @@ in {
     services.netdata = {
       enable = mkEnableOption (lib.mdDoc "netdata");
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.netdata;
-        defaultText = literalExpression "pkgs.netdata";
-        description = lib.mdDoc "Netdata package to use.";
-      };
+      package = mkPackageOption pkgs "netdata" { };
 
       user = mkOption {
         type = types.str;
diff --git a/nixpkgs/nixos/modules/services/monitoring/ocsinventory-agent.nix b/nixpkgs/nixos/modules/services/monitoring/ocsinventory-agent.nix
index 7585ae863750..a36375587759 100644
--- a/nixpkgs/nixos/modules/services/monitoring/ocsinventory-agent.nix
+++ b/nixpkgs/nixos/modules/services/monitoring/ocsinventory-agent.nix
@@ -18,7 +18,7 @@ in
     services.ocsinventory-agent = {
       enable = lib.mkEnableOption (lib.mdDoc "OCS Inventory Agent");
 
-      package = lib.mkPackageOptionMD pkgs "ocsinventory-agent" { };
+      package = lib.mkPackageOption pkgs "ocsinventory-agent" { };
 
       settings = lib.mkOption {
         type = lib.types.submodule {
diff --git a/nixpkgs/nixos/modules/services/monitoring/opentelemetry-collector.nix b/nixpkgs/nixos/modules/services/monitoring/opentelemetry-collector.nix
index 1d211b689777..83ad550dcdf3 100644
--- a/nixpkgs/nixos/modules/services/monitoring/opentelemetry-collector.nix
+++ b/nixpkgs/nixos/modules/services/monitoring/opentelemetry-collector.nix
@@ -1,7 +1,7 @@
 { config, lib, pkgs, ... }:
 
 let
-  inherit (lib) mkEnableOption mkIf mkOption types getExe;
+  inherit (lib) mkEnableOption mkPackageOption mkIf mkOption types getExe;
 
   cfg = config.services.opentelemetry-collector;
   opentelemetry-collector = cfg.package;
@@ -11,12 +11,7 @@ in {
   options.services.opentelemetry-collector = {
     enable = mkEnableOption (lib.mdDoc "Opentelemetry Collector");
 
-    package = mkOption {
-      type = types.package;
-      default = pkgs.opentelemetry-collector;
-      defaultText = lib.literalExpression "pkgs.opentelemetry-collector";
-      description = lib.mdDoc "The opentelemetry-collector package to use.";
-    };
+    package = mkPackageOption pkgs "opentelemetry-collector" { };
 
     settings = mkOption {
       type = settingsFormat.type;
diff --git a/nixpkgs/nixos/modules/services/monitoring/prometheus/alertmanager-irc-relay.nix b/nixpkgs/nixos/modules/services/monitoring/prometheus/alertmanager-irc-relay.nix
index b81d5f6db5e0..9b9bafa09441 100644
--- a/nixpkgs/nixos/modules/services/monitoring/prometheus/alertmanager-irc-relay.nix
+++ b/nixpkgs/nixos/modules/services/monitoring/prometheus/alertmanager-irc-relay.nix
@@ -12,12 +12,7 @@ in
   options.services.prometheus.alertmanagerIrcRelay = {
     enable = mkEnableOption (mdDoc "Alertmanager IRC Relay");
 
-    package = mkOption {
-      type = types.package;
-      default = pkgs.alertmanager-irc-relay;
-      defaultText = literalExpression "pkgs.alertmanager-irc-relay";
-      description = mdDoc "Alertmanager IRC Relay package to use.";
-    };
+    package = mkPackageOption pkgs "alertmanager-irc-relay" { };
 
     extraFlags = mkOption {
       type = types.listOf types.str;
diff --git a/nixpkgs/nixos/modules/services/monitoring/prometheus/alertmanager.nix b/nixpkgs/nixos/modules/services/monitoring/prometheus/alertmanager.nix
index 5fb543ec6195..4fd630015f35 100644
--- a/nixpkgs/nixos/modules/services/monitoring/prometheus/alertmanager.nix
+++ b/nixpkgs/nixos/modules/services/monitoring/prometheus/alertmanager.nix
@@ -44,14 +44,7 @@ in {
     services.prometheus.alertmanager = {
       enable = mkEnableOption (lib.mdDoc "Prometheus Alertmanager");
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.prometheus-alertmanager;
-        defaultText = literalExpression "pkgs.alertmanager";
-        description = lib.mdDoc ''
-          Package that should be used for alertmanager.
-        '';
-      };
+      package = mkPackageOption pkgs "prometheus-alertmanager" { };
 
       configuration = mkOption {
         type = types.nullOr types.attrs;
diff --git a/nixpkgs/nixos/modules/services/monitoring/prometheus/default.nix b/nixpkgs/nixos/modules/services/monitoring/prometheus/default.nix
index a38855ccd408..90ea56658b02 100644
--- a/nixpkgs/nixos/modules/services/monitoring/prometheus/default.nix
+++ b/nixpkgs/nixos/modules/services/monitoring/prometheus/default.nix
@@ -1564,14 +1564,7 @@ in
 
     enable = mkEnableOption (lib.mdDoc "Prometheus monitoring daemon");
 
-    package = mkOption {
-      type = types.package;
-      default = pkgs.prometheus;
-      defaultText = literalExpression "pkgs.prometheus";
-      description = lib.mdDoc ''
-        The prometheus package that should be used.
-      '';
-    };
+    package = mkPackageOption pkgs "prometheus" { };
 
     port = mkOption {
       type = types.port;
diff --git a/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters.nix b/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters.nix
index f89522c09864..39abd293b2d1 100644
--- a/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters.nix
+++ b/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters.nix
@@ -52,6 +52,7 @@ let
     "mikrotik"
     "minio"
     "modemmanager"
+    "mongodb"
     "mysqld"
     "nextcloud"
     "nginx"
diff --git a/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/exportarr.nix b/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/exportarr.nix
index 132209335410..8511abbee1bd 100644
--- a/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/exportarr.nix
+++ b/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/exportarr.nix
@@ -29,7 +29,7 @@ in
       '';
     };
 
-    package = lib.mkPackageOptionMD pkgs "exportarr" { };
+    package = lib.mkPackageOption pkgs "exportarr" { };
 
     environment = lib.mkOption {
       type = lib.types.attrsOf lib.types.str;
diff --git a/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/mongodb.nix b/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/mongodb.nix
new file mode 100644
index 000000000000..db5c4d15be66
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/mongodb.nix
@@ -0,0 +1,68 @@
+{ config, lib, pkgs, options }:
+
+with lib;
+
+let
+  cfg = config.services.prometheus.exporters.mongodb;
+in
+{
+  port = 9216;
+  extraOpts = {
+    uri = mkOption {
+      type = types.str;
+      default = "mongodb://localhost:27017/test";
+      example = "mongodb://localhost:27017/test";
+      description = lib.mdDoc "MongoDB URI to connect to.";
+    };
+    collStats = mkOption {
+      type = types.listOf types.str;
+      default = [ ];
+      example = [ "db1.coll1" "db2" ];
+      description = lib.mdDoc ''
+        List of comma separared databases.collections to get $collStats
+      '';
+    };
+    indexStats = mkOption {
+      type = types.listOf types.str;
+      default = [ ];
+      example = [ "db1.coll1" "db2" ];
+      description = lib.mdDoc ''
+        List of comma separared databases.collections to get $indexStats
+      '';
+    };
+    collector = mkOption {
+      type = types.listOf types.str;
+      default = [ ];
+      example = [ "diagnosticdata" "replicasetstatus" "dbstats" "topmetrics" "currentopmetrics" "indexstats" "dbstats" "profile" ];
+      description = lib.mdDoc "Enabled collectors";
+    };
+    collectAll = mkOption {
+      type = types.bool;
+      default = false;
+      description = lib.mdDoc ''
+        Enable all collectors. Same as specifying all --collector.<name>
+      '';
+    };
+    telemetryPath = mkOption {
+      type = types.str;
+      default = "/metrics";
+      example = "/metrics";
+      description = lib.mdDoc "Metrics expose path";
+    };
+  };
+  serviceOpts = {
+    serviceConfig = {
+      RuntimeDirectory = "prometheus-mongodb-exporter";
+      ExecStart = ''
+        ${getExe pkgs.prometheus-mongodb-exporter} \
+          --mongodb.uri=${cfg.uri}
+          ${if cfg.collectAll then "--collect-all" else concatMapStringsSep " " (x: "--collect.${x}") cfg.collector} \
+          --collector.collstats=${concatStringsSep "," cfg.collStats} \
+          --collector.indexstats=${concatStringsSep "," cfg.indexStats} \
+          --web.listen-address=${cfg.listenAddress}:${toString cfg.port} \
+          --web.telemetry-path=${cfg.telemetryPath} \
+          ${escapeShellArgs cfg.extraFlags}
+      '';
+    };
+  };
+}
diff --git a/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/php-fpm.nix b/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/php-fpm.nix
index 8f6942002f79..8238f1ac1856 100644
--- a/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/php-fpm.nix
+++ b/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/php-fpm.nix
@@ -10,7 +10,7 @@ let
 in {
   port = 9253;
   extraOpts = {
-    package = lib.mkPackageOptionMD pkgs "prometheus-php-fpm-exporter" {};
+    package = lib.mkPackageOption pkgs "prometheus-php-fpm-exporter" {};
 
     telemetryPath = lib.mkOption {
       type = lib.types.str;
diff --git a/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/pve.nix b/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/pve.nix
index f95412efd7dd..20ee2e4b3238 100644
--- a/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/pve.nix
+++ b/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/pve.nix
@@ -15,15 +15,7 @@ in
 {
   port = 9221;
   extraOpts = {
-    package = mkOption {
-      type = types.package;
-      default = pkgs.prometheus-pve-exporter;
-      defaultText = literalExpression "pkgs.prometheus-pve-exporter";
-      example = literalExpression "pkgs.prometheus-pve-exporter";
-      description = lib.mdDoc ''
-        The package to use for prometheus-pve-exporter
-      '';
-    };
+    package = mkPackageOption pkgs "prometheus-pve-exporter" { };
 
     environmentFile = mkOption {
       type = with types; nullOr path;
diff --git a/nixpkgs/nixos/modules/services/monitoring/prometheus/pushgateway.nix b/nixpkgs/nixos/modules/services/monitoring/prometheus/pushgateway.nix
index f5c114c92752..e93924e4fba8 100644
--- a/nixpkgs/nixos/modules/services/monitoring/prometheus/pushgateway.nix
+++ b/nixpkgs/nixos/modules/services/monitoring/prometheus/pushgateway.nix
@@ -23,14 +23,7 @@ in {
     services.prometheus.pushgateway = {
       enable = mkEnableOption (lib.mdDoc "Prometheus Pushgateway");
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.prometheus-pushgateway;
-        defaultText = literalExpression "pkgs.prometheus-pushgateway";
-        description = lib.mdDoc ''
-          Package that should be used for the prometheus pushgateway.
-        '';
-      };
+      package = mkPackageOption pkgs "prometheus-pushgateway" { };
 
       web.listen-address = mkOption {
         type = types.nullOr types.str;
diff --git a/nixpkgs/nixos/modules/services/monitoring/scollector.nix b/nixpkgs/nixos/modules/services/monitoring/scollector.nix
index 48be309c9599..0011d56a066a 100644
--- a/nixpkgs/nixos/modules/services/monitoring/scollector.nix
+++ b/nixpkgs/nixos/modules/services/monitoring/scollector.nix
@@ -40,14 +40,7 @@ in {
         '';
       };
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.scollector;
-        defaultText = literalExpression "pkgs.scollector";
-        description = lib.mdDoc ''
-          scollector binary to use.
-        '';
-      };
+      package = mkPackageOption pkgs "scollector" { };
 
       user = mkOption {
         type = types.str;
diff --git a/nixpkgs/nixos/modules/services/monitoring/telegraf.nix b/nixpkgs/nixos/modules/services/monitoring/telegraf.nix
index 913e599c189a..ee28ee03adf3 100644
--- a/nixpkgs/nixos/modules/services/monitoring/telegraf.nix
+++ b/nixpkgs/nixos/modules/services/monitoring/telegraf.nix
@@ -13,12 +13,7 @@ in {
     services.telegraf = {
       enable = mkEnableOption (lib.mdDoc "telegraf server");
 
-      package = mkOption {
-        default = pkgs.telegraf;
-        defaultText = literalExpression "pkgs.telegraf";
-        description = lib.mdDoc "Which telegraf derivation to use";
-        type = types.package;
-      };
+      package = mkPackageOption pkgs "telegraf" { };
 
       environmentFiles = mkOption {
         type = types.listOf types.path;
@@ -53,6 +48,10 @@ in {
 
   ###### implementation
   config = mkIf config.services.telegraf.enable {
+    services.telegraf.extraConfig = {
+      inputs = {};
+      outputs = {};
+    };
     systemd.services.telegraf = let
       finalConfigFile = if config.services.telegraf.environmentFiles == []
                         then configFile
@@ -61,6 +60,7 @@ in {
       description = "Telegraf Agent";
       wantedBy = [ "multi-user.target" ];
       after = [ "network-online.target" ];
+      path = lib.optional (config.services.telegraf.extraConfig.inputs ? procstat) pkgs.procps;
       serviceConfig = {
         EnvironmentFile = config.services.telegraf.environmentFiles;
         ExecStartPre = lib.optional (config.services.telegraf.environmentFiles != [])
diff --git a/nixpkgs/nixos/modules/services/monitoring/thanos.nix b/nixpkgs/nixos/modules/services/monitoring/thanos.nix
index db8641aa6146..5baa0d8446e5 100644
--- a/nixpkgs/nixos/modules/services/monitoring/thanos.nix
+++ b/nixpkgs/nixos/modules/services/monitoring/thanos.nix
@@ -19,7 +19,7 @@ let
     mkIf
     mkMerge
     mkOption
-    mkPackageOptionMD
+    mkPackageOption
     optional
     optionalAttrs
     optionalString
@@ -682,7 +682,7 @@ in {
 
   options.services.thanos = {
 
-    package = mkPackageOptionMD pkgs "thanos" {};
+    package = mkPackageOption pkgs "thanos" {};
 
     sidecar = paramsToOptions params.sidecar // {
       enable = mkEnableOption
diff --git a/nixpkgs/nixos/modules/services/monitoring/uptime-kuma.nix b/nixpkgs/nixos/modules/services/monitoring/uptime-kuma.nix
index 7027046b2425..f3a41de7536a 100644
--- a/nixpkgs/nixos/modules/services/monitoring/uptime-kuma.nix
+++ b/nixpkgs/nixos/modules/services/monitoring/uptime-kuma.nix
@@ -13,12 +13,7 @@ in
     services.uptime-kuma = {
       enable = mkEnableOption (mdDoc "Uptime Kuma, this assumes a reverse proxy to be set");
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.uptime-kuma;
-        defaultText = literalExpression "pkgs.uptime-kuma";
-        description = lib.mdDoc "Uptime Kuma package to use.";
-      };
+      package = mkPackageOption pkgs "uptime-kuma" { };
 
       appriseSupport = mkEnableOption (mdDoc "apprise support for notifications");
 
diff --git a/nixpkgs/nixos/modules/services/monitoring/vmagent.nix b/nixpkgs/nixos/modules/services/monitoring/vmagent.nix
index 0e2ffb31c57c..bd3ef756959d 100644
--- a/nixpkgs/nixos/modules/services/monitoring/vmagent.nix
+++ b/nixpkgs/nixos/modules/services/monitoring/vmagent.nix
@@ -23,14 +23,7 @@ in {
       '';
     };
 
-    package = mkOption {
-      default = pkgs.vmagent;
-      defaultText = lib.literalMD "pkgs.vmagent";
-      type = types.package;
-      description = lib.mdDoc ''
-        vmagent package to use.
-      '';
-    };
+    package = mkPackageOption pkgs "vmagent" { };
 
     dataDir = mkOption {
       type = types.str;
diff --git a/nixpkgs/nixos/modules/services/monitoring/vmalert.nix b/nixpkgs/nixos/modules/services/monitoring/vmalert.nix
index 27fb34e199b5..1c64f7e100fa 100644
--- a/nixpkgs/nixos/modules/services/monitoring/vmalert.nix
+++ b/nixpkgs/nixos/modules/services/monitoring/vmalert.nix
@@ -22,14 +22,7 @@ in
   options.services.vmalert = {
     enable = mkEnableOption (mdDoc "vmalert");
 
-    package = mkOption {
-      type = types.package;
-      default = pkgs.victoriametrics;
-      defaultText = "pkgs.victoriametrics";
-      description = mdDoc ''
-        The VictoriaMetrics derivation to use.
-      '';
-    };
+    package = mkPackageOption pkgs "victoriametrics" { };
 
     settings = mkOption {
       type = types.submodule {
diff --git a/nixpkgs/nixos/modules/services/monitoring/zabbix-agent.nix b/nixpkgs/nixos/modules/services/monitoring/zabbix-agent.nix
index b497ecbcdb6c..b195366123ab 100644
--- a/nixpkgs/nixos/modules/services/monitoring/zabbix-agent.nix
+++ b/nixpkgs/nixos/modules/services/monitoring/zabbix-agent.nix
@@ -3,7 +3,7 @@
 let
   cfg = config.services.zabbixAgent;
 
-  inherit (lib) mkDefault mkEnableOption mkIf mkMerge mkOption;
+  inherit (lib) mkDefault mkEnableOption mkPackageOption mkIf mkMerge mkOption;
   inherit (lib) attrValues concatMapStringsSep literalExpression optionalString types;
   inherit (lib.generators) toKeyValue;
 
@@ -31,12 +31,7 @@ in
     services.zabbixAgent = {
       enable = mkEnableOption (lib.mdDoc "the Zabbix Agent");
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.zabbix.agent;
-        defaultText = literalExpression "pkgs.zabbix.agent";
-        description = lib.mdDoc "The Zabbix package to use.";
-      };
+      package = mkPackageOption pkgs [ "zabbix" "agent" ] { };
 
       extraPackages = mkOption {
         type = types.listOf types.package;
diff --git a/nixpkgs/nixos/modules/services/network-filesystems/ceph.nix b/nixpkgs/nixos/modules/services/network-filesystems/ceph.nix
index aad03728b203..222905223b59 100644
--- a/nixpkgs/nixos/modules/services/network-filesystems/ceph.nix
+++ b/nixpkgs/nixos/modules/services/network-filesystems/ceph.nix
@@ -210,7 +210,7 @@ in
           to the id part in ceph i.e. [ "name1" ] would result in mgr.name1
         '';
       };
-      package = mkPackageOptionMD pkgs "ceph" { };
+      package = mkPackageOption pkgs "ceph" { };
       extraConfig = mkOption {
         type = with types; attrsOf str;
         default = {};
@@ -231,7 +231,7 @@ in
           to the id part in ceph i.e. [ "name1" ] would result in mon.name1
         '';
       };
-      package = mkPackageOptionMD pkgs "ceph" { };
+      package = mkPackageOption pkgs "ceph" { };
       extraConfig = mkOption {
         type = with types; attrsOf str;
         default = {};
@@ -252,7 +252,7 @@ in
           to the id part in ceph i.e. [ "name1" ] would result in osd.name1
         '';
       };
-      package = mkPackageOptionMD pkgs "ceph" { };
+      package = mkPackageOption pkgs "ceph" { };
       extraConfig = mkOption {
         type = with types; attrsOf str;
         default = {
@@ -280,7 +280,7 @@ in
           to the id part in ceph i.e. [ "name1" ] would result in mds.name1
         '';
       };
-      package = mkPackageOptionMD pkgs "ceph" { };
+      package = mkPackageOption pkgs "ceph" { };
       extraConfig = mkOption {
         type = with types; attrsOf str;
         default = {};
@@ -292,7 +292,7 @@ in
 
     rgw = {
       enable = mkEnableOption (lib.mdDoc "Ceph RadosGW daemon");
-      package = mkPackageOptionMD pkgs "ceph" { };
+      package = mkPackageOption pkgs "ceph" { };
       daemons = mkOption {
         type = with types; listOf str;
         default = [];
diff --git a/nixpkgs/nixos/modules/services/network-filesystems/kubo.nix b/nixpkgs/nixos/modules/services/network-filesystems/kubo.nix
index bc746bed31f2..fbf9b32a2b25 100644
--- a/nixpkgs/nixos/modules/services/network-filesystems/kubo.nix
+++ b/nixpkgs/nixos/modules/services/network-filesystems/kubo.nix
@@ -101,12 +101,7 @@ in
 
       enable = mkEnableOption (lib.mdDoc "Interplanetary File System (WARNING: may cause severe network degradation)");
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.kubo;
-        defaultText = literalExpression "pkgs.kubo";
-        description = lib.mdDoc "Which Kubo package to use.";
-      };
+      package = mkPackageOption pkgs "kubo" { };
 
       user = mkOption {
         type = types.str;
diff --git a/nixpkgs/nixos/modules/services/network-filesystems/litestream/default.nix b/nixpkgs/nixos/modules/services/network-filesystems/litestream/default.nix
index 6e2ec1ccaa3c..afc38fcebcff 100644
--- a/nixpkgs/nixos/modules/services/network-filesystems/litestream/default.nix
+++ b/nixpkgs/nixos/modules/services/network-filesystems/litestream/default.nix
@@ -10,12 +10,7 @@ in
   options.services.litestream = {
     enable = mkEnableOption (lib.mdDoc "litestream");
 
-    package = mkOption {
-      description = lib.mdDoc "Package to use.";
-      default = pkgs.litestream;
-      defaultText = literalExpression "pkgs.litestream";
-      type = types.package;
-    };
+    package = mkPackageOption pkgs "litestream" { };
 
     settings = mkOption {
       description = lib.mdDoc ''
diff --git a/nixpkgs/nixos/modules/services/network-filesystems/openafs/server.nix b/nixpkgs/nixos/modules/services/network-filesystems/openafs/server.nix
index fbaa7cfc1929..14bdf2f33865 100644
--- a/nixpkgs/nixos/modules/services/network-filesystems/openafs/server.nix
+++ b/nixpkgs/nixos/modules/services/network-filesystems/openafs/server.nix
@@ -5,7 +5,7 @@ with import ./lib.nix { inherit config lib pkgs; };
 
 let
   inherit (lib) concatStringsSep literalExpression mkIf mkOption mkEnableOption
-  optionalString types;
+  mkPackageOption optionalString types;
 
   bosConfig = pkgs.writeText "BosConfig" (''
     restrictmode 1
@@ -101,12 +101,7 @@ in {
         description = lib.mdDoc "Definition of all cell-local database server machines.";
       };
 
-      package = mkOption {
-        default = pkgs.openafs;
-        defaultText = literalExpression "pkgs.openafs";
-        type = types.package;
-        description = lib.mdDoc "OpenAFS package for the server binaries";
-      };
+      package = mkPackageOption pkgs "openafs" { };
 
       roles = {
         fileserver = {
diff --git a/nixpkgs/nixos/modules/services/network-filesystems/samba.nix b/nixpkgs/nixos/modules/services/network-filesystems/samba.nix
index 0b22302c0b6d..5d02eac8e9f1 100644
--- a/nixpkgs/nixos/modules/services/network-filesystems/samba.nix
+++ b/nixpkgs/nixos/modules/services/network-filesystems/samba.nix
@@ -120,14 +120,8 @@ in
         '';
       };
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.samba;
-        defaultText = literalExpression "pkgs.samba";
-        example = literalExpression "pkgs.samba4Full";
-        description = lib.mdDoc ''
-          Defines which package should be used for the samba server.
-        '';
+      package = mkPackageOption pkgs "samba" {
+        example = "samba4Full";
       };
 
       invalidUsers = mkOption {
diff --git a/nixpkgs/nixos/modules/services/network-filesystems/tahoe.nix b/nixpkgs/nixos/modules/services/network-filesystems/tahoe.nix
index 14c0a3d4725f..d016d4a38fb9 100644
--- a/nixpkgs/nixos/modules/services/network-filesystems/tahoe.nix
+++ b/nixpkgs/nixos/modules/services/network-filesystems/tahoe.nix
@@ -32,14 +32,7 @@ in
                 If specified, the port should be included.
               '';
             };
-            package = mkOption {
-              default = pkgs.tahoelafs;
-              defaultText = literalExpression "pkgs.tahoelafs";
-              type = types.package;
-              description = lib.mdDoc ''
-                The package to use for the Tahoe LAFS daemon.
-              '';
-            };
+            package = mkPackageOption pkgs "tahoelafs" { };
           };
         });
         description = lib.mdDoc ''
@@ -176,14 +169,7 @@ in
                 URL of the accounts server.
               '';
             };
-            package = mkOption {
-              default = pkgs.tahoelafs;
-              defaultText = literalExpression "pkgs.tahoelafs";
-              type = types.package;
-              description = lib.mdDoc ''
-                The package to use for the Tahoe LAFS daemon.
-              '';
-            };
+            package = mkPackageOption pkgs "tahoelafs" { };
           };
         });
         description = lib.mdDoc ''
diff --git a/nixpkgs/nixos/modules/services/networking/acme-dns.nix b/nixpkgs/nixos/modules/services/networking/acme-dns.nix
index 5c53fa2cc4f1..08fde65e4ca4 100644
--- a/nixpkgs/nixos/modules/services/networking/acme-dns.nix
+++ b/nixpkgs/nixos/modules/services/networking/acme-dns.nix
@@ -12,7 +12,7 @@ let
     mdDoc
     mkEnableOption
     mkOption
-    mkPackageOptionMD
+    mkPackageOption
     types
     ;
   domain = "acme-dns.example.com";
@@ -21,7 +21,7 @@ in
   options.services.acme-dns = {
     enable = mkEnableOption (mdDoc "acme-dns");
 
-    package = mkPackageOptionMD pkgs "acme-dns" { };
+    package = mkPackageOption pkgs "acme-dns" { };
 
     settings = mkOption {
       description = mdDoc ''
diff --git a/nixpkgs/nixos/modules/services/networking/alice-lg.nix b/nixpkgs/nixos/modules/services/networking/alice-lg.nix
index 06b9ac89f12f..fbf127d9410f 100644
--- a/nixpkgs/nixos/modules/services/networking/alice-lg.nix
+++ b/nixpkgs/nixos/modules/services/networking/alice-lg.nix
@@ -11,7 +11,7 @@ in
     services.alice-lg = {
       enable = mkEnableOption (lib.mdDoc "Alice Looking Glass");
 
-      package = mkPackageOptionMD pkgs "alice-lg" { };
+      package = mkPackageOption pkgs "alice-lg" { };
 
       settings = mkOption {
         type = settingsFormat.type;
diff --git a/nixpkgs/nixos/modules/services/networking/asterisk.nix b/nixpkgs/nixos/modules/services/networking/asterisk.nix
index 279927781edc..78a69efc86af 100644
--- a/nixpkgs/nixos/modules/services/networking/asterisk.nix
+++ b/nixpkgs/nixos/modules/services/networking/asterisk.nix
@@ -163,12 +163,7 @@ in
           Additional command line arguments to pass to Asterisk.
         '';
       };
-      package = mkOption {
-        type = types.package;
-        default = pkgs.asterisk;
-        defaultText = literalExpression "pkgs.asterisk";
-        description = lib.mdDoc "The Asterisk package to use.";
-      };
+      package = mkPackageOption pkgs "asterisk" { };
     };
   };
 
diff --git a/nixpkgs/nixos/modules/services/networking/avahi-daemon.nix b/nixpkgs/nixos/modules/services/networking/avahi-daemon.nix
index bdbf9aad9acc..de51843ba6f9 100644
--- a/nixpkgs/nixos/modules/services/networking/avahi-daemon.nix
+++ b/nixpkgs/nixos/modules/services/networking/avahi-daemon.nix
@@ -56,14 +56,7 @@ in
       '';
     };
 
-    package = mkOption {
-      type = types.package;
-      default = pkgs.avahi;
-      defaultText = literalExpression "pkgs.avahi";
-      description = lib.mdDoc ''
-        The avahi package to use for running the daemon.
-      '';
-    };
+    package = mkPackageOption pkgs "avahi" { };
 
     hostName = mkOption {
       type = types.str;
diff --git a/nixpkgs/nixos/modules/services/networking/bee.nix b/nixpkgs/nixos/modules/services/networking/bee.nix
index add9861ebfcd..962cfd30c3fe 100644
--- a/nixpkgs/nixos/modules/services/networking/bee.nix
+++ b/nixpkgs/nixos/modules/services/networking/bee.nix
@@ -17,12 +17,8 @@ in {
     services.bee = {
       enable = mkEnableOption (lib.mdDoc "Ethereum Swarm Bee");
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.bee;
-        defaultText = literalExpression "pkgs.bee";
-        example = literalExpression "pkgs.bee-unstable";
-        description = lib.mdDoc "The package providing the bee binary for the service.";
+      package = mkPackageOption pkgs "bee" {
+        example = "bee-unstable";
       };
 
       settings = mkOption {
diff --git a/nixpkgs/nixos/modules/services/networking/bind.nix b/nixpkgs/nixos/modules/services/networking/bind.nix
index f1829747bb1e..da8633d5066f 100644
--- a/nixpkgs/nixos/modules/services/networking/bind.nix
+++ b/nixpkgs/nixos/modules/services/networking/bind.nix
@@ -118,12 +118,7 @@ in
       enable = mkEnableOption (lib.mdDoc "BIND domain name server");
 
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.bind;
-        defaultText = literalExpression "pkgs.bind";
-        description = lib.mdDoc "The BIND package to use.";
-      };
+      package = mkPackageOption pkgs "bind" { };
 
       cacheNetworks = mkOption {
         default = [ "127.0.0.0/24" ];
diff --git a/nixpkgs/nixos/modules/services/networking/bird-lg.nix b/nixpkgs/nixos/modules/services/networking/bird-lg.nix
index dc861dbfd11b..be9f4101e6ab 100644
--- a/nixpkgs/nixos/modules/services/networking/bird-lg.nix
+++ b/nixpkgs/nixos/modules/services/networking/bird-lg.nix
@@ -51,12 +51,7 @@ in
 {
   options = {
     services.bird-lg = {
-      package = mkOption {
-        type = types.package;
-        default = pkgs.bird-lg;
-        defaultText = literalExpression "pkgs.bird-lg";
-        description = lib.mdDoc "The Bird Looking Glass package to use.";
-      };
+      package = mkPackageOption pkgs "bird-lg" { };
 
       user = mkOption {
         type = types.str;
diff --git a/nixpkgs/nixos/modules/services/networking/birdwatcher.nix b/nixpkgs/nixos/modules/services/networking/birdwatcher.nix
index a129b7a2b4cf..c8ebb2269764 100644
--- a/nixpkgs/nixos/modules/services/networking/birdwatcher.nix
+++ b/nixpkgs/nixos/modules/services/networking/birdwatcher.nix
@@ -8,12 +8,7 @@ in
 {
   options = {
     services.birdwatcher = {
-      package = mkOption {
-        type = types.package;
-        default = pkgs.birdwatcher;
-        defaultText = literalExpression "pkgs.birdwatcher";
-        description = lib.mdDoc "The Birdwatcher package to use.";
-      };
+      package = mkPackageOption pkgs "birdwatcher" { };
       enable = mkEnableOption (lib.mdDoc "Birdwatcher");
       flags = mkOption {
         default = [ ];
diff --git a/nixpkgs/nixos/modules/services/networking/bitcoind.nix b/nixpkgs/nixos/modules/services/networking/bitcoind.nix
index a48066b43b16..4512e666ba5b 100644
--- a/nixpkgs/nixos/modules/services/networking/bitcoind.nix
+++ b/nixpkgs/nixos/modules/services/networking/bitcoind.nix
@@ -36,12 +36,7 @@ let
 
       enable = mkEnableOption (lib.mdDoc "Bitcoin daemon");
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.bitcoind;
-        defaultText = literalExpression "pkgs.bitcoind";
-        description = lib.mdDoc "The package providing bitcoin binaries.";
-      };
+      package = mkPackageOption pkgs "bitcoind" { };
 
       configFile = mkOption {
         type = types.nullOr types.path;
diff --git a/nixpkgs/nixos/modules/services/networking/blockbook-frontend.nix b/nixpkgs/nixos/modules/services/networking/blockbook-frontend.nix
index 46b26195d211..bf476d814140 100644
--- a/nixpkgs/nixos/modules/services/networking/blockbook-frontend.nix
+++ b/nixpkgs/nixos/modules/services/networking/blockbook-frontend.nix
@@ -12,12 +12,7 @@ let
 
       enable = mkEnableOption (lib.mdDoc "blockbook-frontend application");
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.blockbook;
-        defaultText = literalExpression "pkgs.blockbook";
-        description = lib.mdDoc "Which blockbook package to use.";
-      };
+      package = mkPackageOption pkgs "blockbook" { };
 
       user = mkOption {
         type = types.str;
diff --git a/nixpkgs/nixos/modules/services/networking/centrifugo.nix b/nixpkgs/nixos/modules/services/networking/centrifugo.nix
new file mode 100644
index 000000000000..7c6c9a362fd2
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/networking/centrifugo.nix
@@ -0,0 +1,123 @@
+{ config, lib, pkgs, ... }:
+let
+  cfg = config.services.centrifugo;
+
+  settingsFormat = pkgs.formats.json { };
+
+  configFile = settingsFormat.generate "centrifugo.json" cfg.settings;
+in
+{
+  options.services.centrifugo = {
+    enable = lib.mkEnableOption (lib.mdDoc "Centrifugo messaging server");
+
+    package = lib.mkPackageOption pkgs "centrifugo" { };
+
+    settings = lib.mkOption {
+      type = settingsFormat.type;
+      default = { };
+      description = lib.mdDoc ''
+        Declarative Centrifugo configuration. See the [Centrifugo
+        documentation] for a list of options.
+
+        [Centrifugo documentation]: https://centrifugal.dev/docs/server/configuration
+      '';
+    };
+
+    credentials = lib.mkOption {
+      type = lib.types.attrsOf lib.types.path;
+      default = { };
+      example = {
+        CENTRIFUGO_UNI_GRPC_TLS_KEY = "/run/keys/centrifugo-uni-grpc-tls.key";
+      };
+      description = lib.mdDoc ''
+        Environment variables with absolute paths to credentials files to load
+        on service startup.
+      '';
+    };
+
+    environmentFiles = lib.mkOption {
+      type = lib.types.listOf lib.types.path;
+      default = [ ];
+      description = lib.mdDoc ''
+        Files to load environment variables from. Options set via environment
+        variables take precedence over {option}`settings`.
+
+        See the [Centrifugo documentation] for the environment variable name
+        format.
+
+        [Centrifugo documentation]: https://centrifugal.dev/docs/server/configuration#os-environment-variables
+      '';
+    };
+
+    extraGroups = lib.mkOption {
+      type = lib.types.listOf lib.types.str;
+      default = [ ];
+      example = [ "redis-centrifugo" ];
+      description = lib.mdDoc ''
+        Additional groups for the systemd service.
+      '';
+    };
+  };
+
+  config = lib.mkIf cfg.enable {
+    systemd.services.centrifugo = {
+      description = "Centrifugo messaging server";
+      wantedBy = [ "multi-user.target" ];
+      after = [ "network.target" ];
+
+      serviceConfig = {
+        Type = "exec";
+
+        ExecStartPre = "${lib.getExe cfg.package} checkconfig --config ${configFile}";
+        ExecStart = "${lib.getExe cfg.package} --config ${configFile}";
+        ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
+
+        Restart = "always";
+        RestartSec = "1s";
+
+        # Copy files to the credentials directory with file name being the
+        # environment variable name. Note that "%d" specifier expands to the
+        # path of the credentials directory.
+        LoadCredential = lib.mapAttrsToList (name: value: "${name}:${value}") cfg.credentials;
+        Environment = lib.mapAttrsToList (name: _: "${name}=%d/${name}") cfg.credentials;
+
+        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"
+          "~@privileged"
+        ];
+      };
+    };
+  };
+}
diff --git a/nixpkgs/nixos/modules/services/networking/cgit.nix b/nixpkgs/nixos/modules/services/networking/cgit.nix
index 7d1f12fa9146..3de2eb192ed1 100644
--- a/nixpkgs/nixos/modules/services/networking/cgit.nix
+++ b/nixpkgs/nixos/modules/services/networking/cgit.nix
@@ -102,7 +102,7 @@ in
         options = {
           enable = mkEnableOption (mdDoc "cgit");
 
-          package = mkPackageOptionMD pkgs "cgit" {};
+          package = mkPackageOption pkgs "cgit" {};
 
           nginx.virtualHost = mkOption {
             description = mdDoc "VirtualHost to serve cgit on, defaults to the attribute name.";
diff --git a/nixpkgs/nixos/modules/services/networking/cloudflared.nix b/nixpkgs/nixos/modules/services/networking/cloudflared.nix
index b3f0e37d8e9e..80c60fdb8013 100644
--- a/nixpkgs/nixos/modules/services/networking/cloudflared.nix
+++ b/nixpkgs/nixos/modules/services/networking/cloudflared.nix
@@ -152,12 +152,7 @@ in
       description = lib.mdDoc "Group under which cloudflared runs.";
     };
 
-    package = mkOption {
-      type = types.package;
-      default = pkgs.cloudflared;
-      defaultText = "pkgs.cloudflared";
-      description = lib.mdDoc "The package to use for Cloudflared.";
-    };
+    package = mkPackageOption pkgs "cloudflared" { };
 
     tunnels = mkOption {
       description = lib.mdDoc ''
diff --git a/nixpkgs/nixos/modules/services/networking/consul.nix b/nixpkgs/nixos/modules/services/networking/consul.nix
index 955463b9031e..1a0910fc9344 100644
--- a/nixpkgs/nixos/modules/services/networking/consul.nix
+++ b/nixpkgs/nixos/modules/services/networking/consul.nix
@@ -33,15 +33,7 @@ in
         '';
       };
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.consul;
-        defaultText = literalExpression "pkgs.consul";
-        description = lib.mdDoc ''
-          The package used for the Consul agent and CLI.
-        '';
-      };
-
+      package = mkPackageOption pkgs "consul" { };
 
       webUi = mkOption {
         type = types.bool;
@@ -128,12 +120,7 @@ in
       alerts = {
         enable = mkEnableOption (lib.mdDoc "consul-alerts");
 
-        package = mkOption {
-          description = lib.mdDoc "Package to use for consul-alerts.";
-          default = pkgs.consul-alerts;
-          defaultText = literalExpression "pkgs.consul-alerts";
-          type = types.package;
-        };
+        package = mkPackageOption pkgs "consul-alerts" { };
 
         listenAddr = mkOption {
           description = lib.mdDoc "Api listening address.";
diff --git a/nixpkgs/nixos/modules/services/networking/coredns.nix b/nixpkgs/nixos/modules/services/networking/coredns.nix
index f1fe7b2f1241..f6eec2f962dd 100644
--- a/nixpkgs/nixos/modules/services/networking/coredns.nix
+++ b/nixpkgs/nixos/modules/services/networking/coredns.nix
@@ -23,12 +23,7 @@ in {
       '';
     };
 
-    package = mkOption {
-      default = pkgs.coredns;
-      defaultText = literalExpression "pkgs.coredns";
-      type = types.package;
-      description = lib.mdDoc "Coredns package to use.";
-    };
+    package = mkPackageOption pkgs "coredns" { };
 
     extraArgs = mkOption {
       default = [];
diff --git a/nixpkgs/nixos/modules/services/networking/corerad.nix b/nixpkgs/nixos/modules/services/networking/corerad.nix
index 0c6fb7a17cab..33ea2862174e 100644
--- a/nixpkgs/nixos/modules/services/networking/corerad.nix
+++ b/nixpkgs/nixos/modules/services/networking/corerad.nix
@@ -48,12 +48,7 @@ in {
       description = lib.mdDoc "Path to CoreRAD TOML configuration file.";
     };
 
-    package = mkOption {
-      default = pkgs.corerad;
-      defaultText = literalExpression "pkgs.corerad";
-      type = types.package;
-      description = lib.mdDoc "CoreRAD package to use.";
-    };
+    package = mkPackageOption pkgs "corerad" { };
   };
 
   config = mkIf cfg.enable {
diff --git a/nixpkgs/nixos/modules/services/networking/dae.nix b/nixpkgs/nixos/modules/services/networking/dae.nix
index cf3fead19be5..404ce59741f8 100644
--- a/nixpkgs/nixos/modules/services/networking/dae.nix
+++ b/nixpkgs/nixos/modules/services/networking/dae.nix
@@ -16,7 +16,7 @@ in
       enable = mkEnableOption
         (mdDoc "dae, a Linux high-performance transparent proxy solution based on eBPF");
 
-      package = mkPackageOptionMD pkgs "dae" { };
+      package = mkPackageOption pkgs "dae" { };
 
 
       assets = mkOption {
diff --git a/nixpkgs/nixos/modules/services/networking/dnsmasq.nix b/nixpkgs/nixos/modules/services/networking/dnsmasq.nix
index 14bbe334e50d..8d1ca36c38ed 100644
--- a/nixpkgs/nixos/modules/services/networking/dnsmasq.nix
+++ b/nixpkgs/nixos/modules/services/networking/dnsmasq.nix
@@ -53,7 +53,7 @@ in
         '';
       };
 
-      package = mkPackageOptionMD pkgs "dnsmasq" {};
+      package = mkPackageOption pkgs "dnsmasq" {};
 
       resolveLocalQueries = mkOption {
         type = types.bool;
diff --git a/nixpkgs/nixos/modules/services/networking/ejabberd.nix b/nixpkgs/nixos/modules/services/networking/ejabberd.nix
index 3feafc3bb3bd..b10a3d9f21df 100644
--- a/nixpkgs/nixos/modules/services/networking/ejabberd.nix
+++ b/nixpkgs/nixos/modules/services/networking/ejabberd.nix
@@ -29,12 +29,7 @@ in {
         description = lib.mdDoc "Whether to enable ejabberd server";
       };
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.ejabberd;
-        defaultText = literalExpression "pkgs.ejabberd";
-        description = lib.mdDoc "ejabberd server package to use";
-      };
+      package = mkPackageOption pkgs "ejabberd" { };
 
       user = mkOption {
         type = types.str;
diff --git a/nixpkgs/nixos/modules/services/networking/envoy.nix b/nixpkgs/nixos/modules/services/networking/envoy.nix
index c68ceab9619c..779c77ff6c81 100644
--- a/nixpkgs/nixos/modules/services/networking/envoy.nix
+++ b/nixpkgs/nixos/modules/services/networking/envoy.nix
@@ -17,7 +17,7 @@ in
   options.services.envoy = {
     enable = mkEnableOption (lib.mdDoc "Envoy reverse proxy");
 
-    package = mkPackageOptionMD pkgs "envoy" { };
+    package = mkPackageOption pkgs "envoy" { };
 
     requireValidConfig = mkOption {
       type = types.bool;
diff --git a/nixpkgs/nixos/modules/services/networking/epmd.nix b/nixpkgs/nixos/modules/services/networking/epmd.nix
index 0bc8c71f4eaa..318e325944b5 100644
--- a/nixpkgs/nixos/modules/services/networking/epmd.nix
+++ b/nixpkgs/nixos/modules/services/networking/epmd.nix
@@ -17,15 +17,7 @@ in
         Erlang computations.
       '';
     };
-    package = mkOption {
-      type = types.package;
-      default = pkgs.erlang;
-      defaultText = literalExpression "pkgs.erlang";
-      description = lib.mdDoc ''
-        The Erlang package to use to get epmd binary. That way you can re-use
-        an Erlang runtime that is already installed for other purposes.
-      '';
-    };
+    package = mkPackageOption pkgs "erlang" { };
     listenStream = mkOption
       {
         type = types.str;
diff --git a/nixpkgs/nixos/modules/services/networking/ferm.nix b/nixpkgs/nixos/modules/services/networking/ferm.nix
index 09151eb0b544..5ebf7aacb4db 100644
--- a/nixpkgs/nixos/modules/services/networking/ferm.nix
+++ b/nixpkgs/nixos/modules/services/networking/ferm.nix
@@ -33,12 +33,7 @@ in {
         defaultText = literalMD "empty firewall, allows any traffic";
         type = types.lines;
       };
-      package = mkOption {
-        description = lib.mdDoc "The ferm package.";
-        type = types.package;
-        default = pkgs.ferm;
-        defaultText = literalExpression "pkgs.ferm";
-      };
+      package = mkPackageOption pkgs "ferm" { };
     };
   };
 
diff --git a/nixpkgs/nixos/modules/services/networking/firewall-iptables.nix b/nixpkgs/nixos/modules/services/networking/firewall-iptables.nix
index 63e952194d67..e90086838720 100644
--- a/nixpkgs/nixos/modules/services/networking/firewall-iptables.nix
+++ b/nixpkgs/nixos/modules/services/networking/firewall-iptables.nix
@@ -301,6 +301,7 @@ in
       }
     ];
 
+    environment.systemPackages = [ pkgs.nixos-firewall-tool ];
     networking.firewall.checkReversePath = mkIf (!kernelHasRPFilter) (mkDefault false);
 
     systemd.services.firewall = {
diff --git a/nixpkgs/nixos/modules/services/networking/flannel.nix b/nixpkgs/nixos/modules/services/networking/flannel.nix
index 6ed4f78ddc92..2c2b6dc58cce 100644
--- a/nixpkgs/nixos/modules/services/networking/flannel.nix
+++ b/nixpkgs/nixos/modules/services/networking/flannel.nix
@@ -16,12 +16,7 @@ in {
   options.services.flannel = {
     enable = mkEnableOption (lib.mdDoc "flannel");
 
-    package = mkOption {
-      description = lib.mdDoc "Package to use for flannel";
-      type = types.package;
-      default = pkgs.flannel;
-      defaultText = literalExpression "pkgs.flannel";
-    };
+    package = mkPackageOption pkgs "flannel" { };
 
     publicIp = mkOption {
       description = lib.mdDoc ''
diff --git a/nixpkgs/nixos/modules/services/networking/frp.nix b/nixpkgs/nixos/modules/services/networking/frp.nix
index e4f9a220b5e8..218d532c12da 100644
--- a/nixpkgs/nixos/modules/services/networking/frp.nix
+++ b/nixpkgs/nixos/modules/services/networking/frp.nix
@@ -14,7 +14,7 @@ in
     services.frp = {
       enable = mkEnableOption (mdDoc "frp");
 
-      package = mkPackageOptionMD pkgs "frp" { };
+      package = mkPackageOption pkgs "frp" { };
 
       role = mkOption {
         type = types.enum [ "server" "client" ];
diff --git a/nixpkgs/nixos/modules/services/networking/ghostunnel.nix b/nixpkgs/nixos/modules/services/networking/ghostunnel.nix
index 4902367e2a6a..d5e2ff19ce50 100644
--- a/nixpkgs/nixos/modules/services/networking/ghostunnel.nix
+++ b/nixpkgs/nixos/modules/services/networking/ghostunnel.nix
@@ -9,6 +9,7 @@ let
     mapAttrs'
     mkDefault
     mkEnableOption
+    mkPackageOption
     mkIf
     mkOption
     nameValuePair
@@ -215,12 +216,7 @@ in
   options = {
     services.ghostunnel.enable = mkEnableOption (lib.mdDoc "ghostunnel");
 
-    services.ghostunnel.package = mkOption {
-      description = lib.mdDoc "The ghostunnel package to use.";
-      type = types.package;
-      default = pkgs.ghostunnel;
-      defaultText = literalExpression "pkgs.ghostunnel";
-    };
+    services.ghostunnel.package = mkPackageOption pkgs "ghostunnel" { };
 
     services.ghostunnel.servers = mkOption {
       description = lib.mdDoc ''
diff --git a/nixpkgs/nixos/modules/services/networking/gnunet.nix b/nixpkgs/nixos/modules/services/networking/gnunet.nix
index fdb353fd3443..a235f1605e54 100644
--- a/nixpkgs/nixos/modules/services/networking/gnunet.nix
+++ b/nixpkgs/nixos/modules/services/networking/gnunet.nix
@@ -112,12 +112,8 @@ in
         };
       };
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.gnunet;
-        defaultText = literalExpression "pkgs.gnunet";
-        description = lib.mdDoc "Overridable attribute of the gnunet package to use.";
-        example = literalExpression "pkgs.gnunet_git";
+      package = mkPackageOption pkgs "gnunet" {
+        example = "gnunet_git";
       };
 
       extraOptions = mkOption {
diff --git a/nixpkgs/nixos/modules/services/networking/haproxy.nix b/nixpkgs/nixos/modules/services/networking/haproxy.nix
index 208eb356d629..a2f3be6c49ce 100644
--- a/nixpkgs/nixos/modules/services/networking/haproxy.nix
+++ b/nixpkgs/nixos/modules/services/networking/haproxy.nix
@@ -19,7 +19,7 @@ with lib;
 
       enable = mkEnableOption (lib.mdDoc "HAProxy, the reliable, high performance TCP/HTTP load balancer.");
 
-      package = mkPackageOptionMD pkgs "haproxy" { };
+      package = mkPackageOption pkgs "haproxy" { };
 
       user = mkOption {
         type = types.str;
diff --git a/nixpkgs/nixos/modules/services/networking/harmonia.nix b/nixpkgs/nixos/modules/services/networking/harmonia.nix
index 4733165cf7d1..beaa7d00b6ce 100644
--- a/nixpkgs/nixos/modules/services/networking/harmonia.nix
+++ b/nixpkgs/nixos/modules/services/networking/harmonia.nix
@@ -14,7 +14,7 @@ in
         description = lib.mdDoc "Path to the signing key that will be used for signing the cache";
       };
 
-      package = lib.mkPackageOptionMD pkgs "harmonia" { };
+      package = lib.mkPackageOption pkgs "harmonia" { };
 
       settings = lib.mkOption {
         inherit (format) type;
diff --git a/nixpkgs/nixos/modules/services/networking/headscale.nix b/nixpkgs/nixos/modules/services/networking/headscale.nix
index 03e6f86af53f..4224a0578cc3 100644
--- a/nixpkgs/nixos/modules/services/networking/headscale.nix
+++ b/nixpkgs/nixos/modules/services/networking/headscale.nix
@@ -17,14 +17,7 @@ in {
     services.headscale = {
       enable = mkEnableOption (lib.mdDoc "headscale, Open Source coordination server for Tailscale");
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.headscale;
-        defaultText = literalExpression "pkgs.headscale";
-        description = lib.mdDoc ''
-          Which headscale package to use for the running server.
-        '';
-      };
+      package = mkPackageOption pkgs "headscale" { };
 
       user = mkOption {
         default = "headscale";
diff --git a/nixpkgs/nixos/modules/services/networking/i2pd.nix b/nixpkgs/nixos/modules/services/networking/i2pd.nix
index 808e7b66d36e..8d9eff61488c 100644
--- a/nixpkgs/nixos/modules/services/networking/i2pd.nix
+++ b/nixpkgs/nixos/modules/services/networking/i2pd.nix
@@ -244,14 +244,7 @@ in
         '';
       };
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.i2pd;
-        defaultText = literalExpression "pkgs.i2pd";
-        description = lib.mdDoc ''
-          i2pd package to use.
-        '';
-      };
+      package = mkPackageOption pkgs "i2pd" { };
 
       logLevel = mkOption {
         type = types.enum ["debug" "info" "warn" "error"];
diff --git a/nixpkgs/nixos/modules/services/networking/icecream/daemon.nix b/nixpkgs/nixos/modules/services/networking/icecream/daemon.nix
index fdd7a139c2fa..48363cc22c36 100644
--- a/nixpkgs/nixos/modules/services/networking/icecream/daemon.nix
+++ b/nixpkgs/nixos/modules/services/networking/icecream/daemon.nix
@@ -99,12 +99,7 @@ in {
         '';
       };
 
-      package = mkOption {
-        default = pkgs.icecream;
-        defaultText = literalExpression "pkgs.icecream";
-        type = types.package;
-        description = lib.mdDoc "Icecream package to use.";
-      };
+      package = mkPackageOption pkgs "icecream" { };
 
       extraArgs = mkOption {
         type = types.listOf types.str;
diff --git a/nixpkgs/nixos/modules/services/networking/icecream/scheduler.nix b/nixpkgs/nixos/modules/services/networking/icecream/scheduler.nix
index 33aee1bb19cc..2d53282ba88f 100644
--- a/nixpkgs/nixos/modules/services/networking/icecream/scheduler.nix
+++ b/nixpkgs/nixos/modules/services/networking/icecream/scheduler.nix
@@ -54,12 +54,7 @@ in {
         '';
       };
 
-      package = mkOption {
-        default = pkgs.icecream;
-        defaultText = literalExpression "pkgs.icecream";
-        type = types.package;
-        description = lib.mdDoc "Icecream package to use.";
-      };
+      package = mkPackageOption pkgs "icecream" { };
 
       extraArgs = mkOption {
         type = types.listOf types.str;
diff --git a/nixpkgs/nixos/modules/services/networking/iscsi/initiator.nix b/nixpkgs/nixos/modules/services/networking/iscsi/initiator.nix
index 6c30f89b7968..2d802d8cfc70 100644
--- a/nixpkgs/nixos/modules/services/networking/iscsi/initiator.nix
+++ b/nixpkgs/nixos/modules/services/networking/iscsi/initiator.nix
@@ -19,12 +19,7 @@ in
       description = lib.mdDoc "Name of this iscsi initiator";
       example = "iqn.2020-08.org.linux-iscsi.initiatorhost:example";
     };
-    package = mkOption {
-      type = package;
-      description = lib.mdDoc "openiscsi package to use";
-      default = pkgs.openiscsi;
-      defaultText = literalExpression "pkgs.openiscsi";
-    };
+    package = mkPackageOption pkgs "openiscsi" { };
 
     extraConfig = mkOption {
       type = str;
diff --git a/nixpkgs/nixos/modules/services/networking/iwd.nix b/nixpkgs/nixos/modules/services/networking/iwd.nix
index 993a603c1ed5..b74f5d0bec9b 100644
--- a/nixpkgs/nixos/modules/services/networking/iwd.nix
+++ b/nixpkgs/nixos/modules/services/networking/iwd.nix
@@ -2,7 +2,7 @@
 
 let
   inherit (lib)
-    mkEnableOption mkIf mkOption types
+    mkEnableOption mkPackageOption mkIf mkOption types
     recursiveUpdate;
 
   cfg = config.networking.wireless.iwd;
@@ -19,14 +19,7 @@ in
   options.networking.wireless.iwd = {
     enable = mkEnableOption (lib.mdDoc "iwd");
 
-    package = mkOption {
-      type = types.package;
-      default = pkgs.iwd;
-      defaultText = lib.literalExpression "pkgs.iwd";
-      description = lib.mdDoc ''
-        The iwd package to use.
-      '';
-    };
+    package = mkPackageOption pkgs "iwd" { };
 
     settings = mkOption {
       type = ini.type;
diff --git a/nixpkgs/nixos/modules/services/networking/knot.nix b/nixpkgs/nixos/modules/services/networking/knot.nix
index 4f6ac945cf97..d4bd81629c97 100644
--- a/nixpkgs/nixos/modules/services/networking/knot.nix
+++ b/nixpkgs/nixos/modules/services/networking/knot.nix
@@ -182,14 +182,7 @@ in {
         '';
       };
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.knot-dns;
-        defaultText = literalExpression "pkgs.knot-dns";
-        description = lib.mdDoc ''
-          Which Knot DNS package to use
-        '';
-      };
+      package = mkPackageOption pkgs "knot-dns" { };
     };
   };
   imports = [
diff --git a/nixpkgs/nixos/modules/services/networking/kresd.nix b/nixpkgs/nixos/modules/services/networking/kresd.nix
index 3ad757133a60..0c7363e564dc 100644
--- a/nixpkgs/nixos/modules/services/networking/kresd.nix
+++ b/nixpkgs/nixos/modules/services/networking/kresd.nix
@@ -57,14 +57,8 @@ in {
         and give commands interactively to kresd@1.service.
       '';
     };
-    package = mkOption {
-      type = types.package;
-      description = lib.mdDoc ''
-        knot-resolver package to use.
-      '';
-      default = pkgs.knot-resolver;
-      defaultText = literalExpression "pkgs.knot-resolver";
-      example = literalExpression "pkgs.knot-resolver.override { extraFeatures = true; }";
+    package = mkPackageOption pkgs "knot-resolver" {
+      example = "knot-resolver.override { extraFeatures = true; }";
     };
     extraConfig = mkOption {
       type = types.lines;
diff --git a/nixpkgs/nixos/modules/services/networking/lambdabot.nix b/nixpkgs/nixos/modules/services/networking/lambdabot.nix
index 8609bc971962..01914097ad72 100644
--- a/nixpkgs/nixos/modules/services/networking/lambdabot.nix
+++ b/nixpkgs/nixos/modules/services/networking/lambdabot.nix
@@ -24,12 +24,7 @@ in
         description = lib.mdDoc "Enable the Lambdabot IRC bot";
       };
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.lambdabot;
-        defaultText = literalExpression "pkgs.lambdabot";
-        description = lib.mdDoc "Used lambdabot package";
-      };
+      package = mkPackageOption pkgs "lambdabot" { };
 
       script = mkOption {
         type = types.str;
diff --git a/nixpkgs/nixos/modules/services/networking/legit.nix b/nixpkgs/nixos/modules/services/networking/legit.nix
index 90234f3955e8..ff8e0dd4f93c 100644
--- a/nixpkgs/nixos/modules/services/networking/legit.nix
+++ b/nixpkgs/nixos/modules/services/networking/legit.nix
@@ -7,7 +7,7 @@ let
     mdDoc
     mkIf
     mkOption
-    mkPackageOptionMD
+    mkPackageOption
     optionalAttrs
     optional
     types;
@@ -25,7 +25,7 @@ in
   options.services.legit = {
     enable = mkEnableOption (mdDoc "legit git web frontend");
 
-    package = mkPackageOptionMD pkgs "legit-web" { };
+    package = mkPackageOption pkgs "legit-web" { };
 
     user = mkOption {
       type = types.str;
diff --git a/nixpkgs/nixos/modules/services/networking/lokinet.nix b/nixpkgs/nixos/modules/services/networking/lokinet.nix
index f6bc314ed260..8f64d3f0119f 100644
--- a/nixpkgs/nixos/modules/services/networking/lokinet.nix
+++ b/nixpkgs/nixos/modules/services/networking/lokinet.nix
@@ -9,12 +9,7 @@ in with lib; {
   options.services.lokinet = {
     enable = mkEnableOption (lib.mdDoc "Lokinet daemon");
 
-    package = mkOption {
-      type = types.package;
-      default = pkgs.lokinet;
-      defaultText = literalExpression "pkgs.lokinet";
-      description = lib.mdDoc "Lokinet package to use.";
-    };
+    package = mkPackageOption pkgs "lokinet" { };
 
     useLocally = mkOption {
       type = types.bool;
diff --git a/nixpkgs/nixos/modules/services/networking/miredo.nix b/nixpkgs/nixos/modules/services/networking/miredo.nix
index d15a55b4d7d6..0c43839c15ab 100644
--- a/nixpkgs/nixos/modules/services/networking/miredo.nix
+++ b/nixpkgs/nixos/modules/services/networking/miredo.nix
@@ -22,14 +22,7 @@ in
 
       enable = mkEnableOption (lib.mdDoc "the Miredo IPv6 tunneling service");
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.miredo;
-        defaultText = literalExpression "pkgs.miredo";
-        description = lib.mdDoc ''
-          The package to use for the miredo daemon's binary.
-        '';
-      };
+      package = mkPackageOption pkgs "miredo" { };
 
       serverAddress = mkOption {
         default = "teredo.remlab.net";
diff --git a/nixpkgs/nixos/modules/services/networking/morty.nix b/nixpkgs/nixos/modules/services/networking/morty.nix
index 72514764a7c6..6954596addfd 100644
--- a/nixpkgs/nixos/modules/services/networking/morty.nix
+++ b/nixpkgs/nixos/modules/services/networking/morty.nix
@@ -42,12 +42,7 @@ in
         description = lib.mdDoc "Request timeout in seconds.";
       };
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.morty;
-        defaultText = literalExpression "pkgs.morty";
-        description = lib.mdDoc "morty package to use.";
-      };
+      package = mkPackageOption pkgs "morty" { };
 
       port = mkOption {
         type = types.port;
diff --git a/nixpkgs/nixos/modules/services/networking/mosquitto.nix b/nixpkgs/nixos/modules/services/networking/mosquitto.nix
index c53d86c0babc..f2b158b98942 100644
--- a/nixpkgs/nixos/modules/services/networking/mosquitto.nix
+++ b/nixpkgs/nixos/modules/services/networking/mosquitto.nix
@@ -482,14 +482,7 @@ let
   globalOptions = with types; {
     enable = mkEnableOption (lib.mdDoc "the MQTT Mosquitto broker");
 
-    package = mkOption {
-      type = package;
-      default = pkgs.mosquitto;
-      defaultText = literalExpression "pkgs.mosquitto";
-      description = lib.mdDoc ''
-        Mosquitto package to use.
-      '';
-    };
+    package = mkPackageOption pkgs "mosquitto" { };
 
     bridges = mkOption {
       type = attrsOf bridgeOptions;
diff --git a/nixpkgs/nixos/modules/services/networking/mtr-exporter.nix b/nixpkgs/nixos/modules/services/networking/mtr-exporter.nix
index af694c3e736b..38bc0401a7e6 100644
--- a/nixpkgs/nixos/modules/services/networking/mtr-exporter.nix
+++ b/nixpkgs/nixos/modules/services/networking/mtr-exporter.nix
@@ -5,7 +5,7 @@ let
     maintainers types literalExpression
     escapeShellArg escapeShellArgs
     mkEnableOption mkOption mkRemovedOptionModule mkIf mdDoc
-    optionalString concatMapStrings concatStringsSep;
+    mkPackageOption optionalString concatMapStrings concatStringsSep;
 
   cfg = config.services.mtr-exporter;
 
@@ -44,19 +44,9 @@ in {
           '';
         };
 
-        package = mkOption {
-          type = types.package;
-          default = pkgs.mtr-exporter;
-          defaultText = literalExpression "pkgs.mtr-exporter";
-          description = mdDoc "The MTR exporter package to use.";
-        };
+        package = mkPackageOption pkgs "mtr-exporter" { };
 
-        mtrPackage = mkOption {
-          type = types.package;
-          default = pkgs.mtr;
-          defaultText = literalExpression "pkgs.mtr";
-          description = mdDoc "The MTR package to use.";
-        };
+        mtrPackage = mkPackageOption pkgs "mtr" { };
 
         jobs = mkOption {
           description = mdDoc "List of MTR jobs. Will be added to /etc/mtr-exporter.conf";
diff --git a/nixpkgs/nixos/modules/services/networking/mullvad-vpn.nix b/nixpkgs/nixos/modules/services/networking/mullvad-vpn.nix
index 8c7d5237971f..446c71f40764 100644
--- a/nixpkgs/nixos/modules/services/networking/mullvad-vpn.nix
+++ b/nixpkgs/nixos/modules/services/networking/mullvad-vpn.nix
@@ -23,12 +23,10 @@ with lib;
       '';
     };
 
-    package = mkOption {
-      type = types.package;
-      default = pkgs.mullvad;
-      defaultText = literalExpression "pkgs.mullvad";
-      description = lib.mdDoc ''
-        The Mullvad package to use. `pkgs.mullvad` only provides the CLI tool, `pkgs.mullvad-vpn` provides both the CLI and the GUI.
+    package = mkPackageOption pkgs "mullvad" {
+      example = "mullvad-vpn";
+      extraDescription = ''
+        `pkgs.mullvad` only provides the CLI tool, `pkgs.mullvad-vpn` provides both the CLI and the GUI.
       '';
     };
   };
diff --git a/nixpkgs/nixos/modules/services/networking/multipath.nix b/nixpkgs/nixos/modules/services/networking/multipath.nix
index 9099cbe0cd32..42ffc3c88426 100644
--- a/nixpkgs/nixos/modules/services/networking/multipath.nix
+++ b/nixpkgs/nixos/modules/services/networking/multipath.nix
@@ -24,12 +24,7 @@ in {
 
     enable = mkEnableOption (lib.mdDoc "the device mapper multipath (DM-MP) daemon");
 
-    package = mkOption {
-      type = package;
-      description = lib.mdDoc "multipath-tools package to use";
-      default = pkgs.multipath-tools;
-      defaultText = lib.literalExpression "pkgs.multipath-tools";
-    };
+    package = mkPackageOption pkgs "multipath-tools" { };
 
     devices = mkOption {
       default = [ ];
diff --git a/nixpkgs/nixos/modules/services/networking/murmur.nix b/nixpkgs/nixos/modules/services/networking/murmur.nix
index 20c2eff11e62..0cd80e134ace 100644
--- a/nixpkgs/nixos/modules/services/networking/murmur.nix
+++ b/nixpkgs/nixos/modules/services/networking/murmur.nix
@@ -119,12 +119,7 @@ in
         description = lib.mdDoc "Host to bind to. Defaults binding on all addresses.";
       };
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.murmur;
-        defaultText = literalExpression "pkgs.murmur";
-        description = lib.mdDoc "Overridable attribute of the murmur package to use.";
-      };
+      package = mkPackageOption pkgs "murmur" { };
 
       password = mkOption {
         type = types.str;
diff --git a/nixpkgs/nixos/modules/services/networking/mxisd.nix b/nixpkgs/nixos/modules/services/networking/mxisd.nix
index 528a51c1f3af..47d2b16a1501 100644
--- a/nixpkgs/nixos/modules/services/networking/mxisd.nix
+++ b/nixpkgs/nixos/modules/services/networking/mxisd.nix
@@ -39,12 +39,7 @@ in {
     services.mxisd = {
       enable = mkEnableOption (lib.mdDoc "matrix federated identity server");
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.ma1sd;
-        defaultText = literalExpression "pkgs.ma1sd";
-        description = lib.mdDoc "The mxisd/ma1sd package to use";
-      };
+      package = mkPackageOption pkgs "ma1sd" { };
 
       environmentFile = mkOption {
         type = types.nullOr types.str;
diff --git a/nixpkgs/nixos/modules/services/networking/nar-serve.nix b/nixpkgs/nixos/modules/services/networking/nar-serve.nix
index b8b76120e44f..02b8979bd8bc 100644
--- a/nixpkgs/nixos/modules/services/networking/nar-serve.nix
+++ b/nixpkgs/nixos/modules/services/networking/nar-serve.nix
@@ -6,7 +6,7 @@ let
 in
 {
   meta = {
-    maintainers = [ maintainers.rizary ];
+    maintainers = [ maintainers.rizary maintainers.zimbatm ];
   };
   options = {
     services.nar-serve = {
diff --git a/nixpkgs/nixos/modules/services/networking/nat-nftables.nix b/nixpkgs/nixos/modules/services/networking/nat-nftables.nix
index 4b2317ca2ffc..7aa93d8a64b1 100644
--- a/nixpkgs/nixos/modules/services/networking/nat-nftables.nix
+++ b/nixpkgs/nixos/modules/services/networking/nat-nftables.nix
@@ -1,4 +1,4 @@
-{ config, lib, pkgs, ... }:
+{ config, lib, ... }:
 
 with lib;
 
@@ -35,26 +35,18 @@ let
 
   mkTable = { ipVer, dest, ipSet, forwardPorts, dmzHost }:
     let
-      # nftables does not support both port and port range as values in a dnat map.
-      # e.g. "dnat th dport map { 80 : 10.0.0.1 . 80, 443 : 10.0.0.2 . 900-1000 }"
-      # So we split them.
-      fwdPorts = filter (x: length (splitString "-" x.destination) == 1) forwardPorts;
-      fwdPortsRange = filter (x: length (splitString "-" x.destination) > 1) forwardPorts;
-
       # nftables maps for port forward
       # l4proto . dport : addr . port
-      toFwdMap = forwardPorts: toNftSet (map
+      fwdMap = toNftSet (map
         (fwd:
           with (splitIPPorts fwd.destination);
           "${fwd.proto} . ${toNftRange fwd.sourcePort} : ${IP} . ${ports}"
         )
         forwardPorts);
-      fwdMap = toFwdMap fwdPorts;
-      fwdRangeMap = toFwdMap fwdPortsRange;
 
       # nftables maps for port forward loopback dnat
       # daddr . l4proto . dport : addr . port
-      toFwdLoopDnatMap = forwardPorts: toNftSet (concatMap
+      fwdLoopDnatMap = toNftSet (concatMap
         (fwd: map
           (loopbackip:
             with (splitIPPorts fwd.destination);
@@ -62,8 +54,6 @@ let
           )
           fwd.loopbackIPs)
         forwardPorts);
-      fwdLoopDnatMap = toFwdLoopDnatMap fwdPorts;
-      fwdLoopDnatRangeMap = toFwdLoopDnatMap fwdPortsRange;
 
       # nftables set for port forward loopback snat
       # daddr . l4proto . dport
@@ -79,17 +69,11 @@ let
         type nat hook prerouting priority dstnat;
 
         ${optionalString (fwdMap != "") ''
-          iifname "${cfg.externalInterface}" dnat meta l4proto . th dport map { ${fwdMap} } comment "port forward"
-        ''}
-        ${optionalString (fwdRangeMap != "") ''
-          iifname "${cfg.externalInterface}" dnat meta l4proto . th dport map { ${fwdRangeMap} } comment "port forward"
+          iifname "${cfg.externalInterface}" meta l4proto { tcp, udp } dnat meta l4proto . th dport map { ${fwdMap} } comment "port forward"
         ''}
 
         ${optionalString (fwdLoopDnatMap != "") ''
-          dnat ${ipVer} daddr . meta l4proto . th dport map { ${fwdLoopDnatMap} } comment "port forward loopback from other hosts behind NAT"
-        ''}
-        ${optionalString (fwdLoopDnatRangeMap != "") ''
-          dnat ${ipVer} daddr . meta l4proto . th dport map { ${fwdLoopDnatRangeMap} } comment "port forward loopback from other hosts behind NAT"
+          meta l4proto { tcp, udp } dnat ${ipVer} daddr . meta l4proto . th dport map { ${fwdLoopDnatMap} } comment "port forward loopback from other hosts behind NAT"
         ''}
 
         ${optionalString (dmzHost != null) ''
@@ -116,10 +100,7 @@ let
         type nat hook output priority mangle;
 
         ${optionalString (fwdLoopDnatMap != "") ''
-          dnat ${ipVer} daddr . meta l4proto . th dport map { ${fwdLoopDnatMap} } comment "port forward loopback from the host itself"
-        ''}
-        ${optionalString (fwdLoopDnatRangeMap != "") ''
-          dnat ${ipVer} daddr . meta l4proto . th dport map { ${fwdLoopDnatRangeMap} } comment "port forward loopback from the host itself"
+          meta l4proto { tcp, udp } dnat ${ipVer} daddr . meta l4proto . th dport map { ${fwdLoopDnatMap} } comment "port forward loopback from the host itself"
         ''}
       }
     '';
diff --git a/nixpkgs/nixos/modules/services/networking/nebula.nix b/nixpkgs/nixos/modules/services/networking/nebula.nix
index e1a8c6740f57..b9ebbfbd9a29 100644
--- a/nixpkgs/nixos/modules/services/networking/nebula.nix
+++ b/nixpkgs/nixos/modules/services/networking/nebula.nix
@@ -27,12 +27,7 @@ in
               description = lib.mdDoc "Enable or disable this network.";
             };
 
-            package = mkOption {
-              type = types.package;
-              default = pkgs.nebula;
-              defaultText = literalExpression "pkgs.nebula";
-              description = lib.mdDoc "Nebula derivation to use.";
-            };
+            package = mkPackageOption pkgs "nebula" { };
 
             ca = mkOption {
               type = types.path;
diff --git a/nixpkgs/nixos/modules/services/networking/netbird.nix b/nixpkgs/nixos/modules/services/networking/netbird.nix
index 647c0ce3e6d1..4b0bd63e9dbc 100644
--- a/nixpkgs/nixos/modules/services/networking/netbird.nix
+++ b/nixpkgs/nixos/modules/services/networking/netbird.nix
@@ -11,12 +11,7 @@ in {
 
   options.services.netbird = {
     enable = mkEnableOption (lib.mdDoc "Netbird daemon");
-    package = mkOption {
-      type = types.package;
-      default = pkgs.netbird;
-      defaultText = literalExpression "pkgs.netbird";
-      description = lib.mdDoc "The package to use for netbird";
-    };
+    package = mkPackageOption pkgs "netbird" { };
   };
 
   config = mkIf cfg.enable {
diff --git a/nixpkgs/nixos/modules/services/networking/netclient.nix b/nixpkgs/nixos/modules/services/networking/netclient.nix
index 124735fd716a..43b8f07cca04 100644
--- a/nixpkgs/nixos/modules/services/networking/netclient.nix
+++ b/nixpkgs/nixos/modules/services/networking/netclient.nix
@@ -7,7 +7,7 @@ in
 
   options.services.netclient = {
     enable = lib.mkEnableOption (lib.mdDoc "Netclient Daemon");
-    package = lib.mkPackageOptionMD pkgs "netclient" { };
+    package = lib.mkPackageOption pkgs "netclient" { };
   };
 
   config = lib.mkIf cfg.enable {
diff --git a/nixpkgs/nixos/modules/services/networking/ngircd.nix b/nixpkgs/nixos/modules/services/networking/ngircd.nix
index 5e721f5aa625..a2fff78fdff8 100644
--- a/nixpkgs/nixos/modules/services/networking/ngircd.nix
+++ b/nixpkgs/nixos/modules/services/networking/ngircd.nix
@@ -28,14 +28,7 @@ in {
         type = types.lines;
       };
 
-      package = mkOption {
-        description = lib.mdDoc "The ngircd package.";
-
-        type = types.package;
-
-        default = pkgs.ngircd;
-        defaultText = literalExpression "pkgs.ngircd";
-      };
+      package = mkPackageOption pkgs "ngircd" { };
     };
   };
 
diff --git a/nixpkgs/nixos/modules/services/networking/nix-serve.nix b/nixpkgs/nixos/modules/services/networking/nix-serve.nix
index 8c4352bc95e8..a0c0be2ff254 100644
--- a/nixpkgs/nixos/modules/services/networking/nix-serve.nix
+++ b/nixpkgs/nixos/modules/services/networking/nix-serve.nix
@@ -26,14 +26,7 @@ in
         '';
       };
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.nix-serve;
-        defaultText = literalExpression "pkgs.nix-serve";
-        description = lib.mdDoc ''
-          nix-serve package to use.
-        '';
-      };
+      package = mkPackageOption pkgs "nix-serve" { };
 
       openFirewall = mkOption {
         type = types.bool;
@@ -67,7 +60,9 @@ in
   };
 
   config = mkIf cfg.enable {
-    nix.settings.extra-allowed-users = [ "nix-serve" ];
+    nix.settings = lib.optionalAttrs (lib.versionAtLeast config.nix.package.version "2.4") {
+      extra-allowed-users = [ "nix-serve" ];
+    };
 
     systemd.services.nix-serve = {
       description = "nix-serve binary cache server";
diff --git a/nixpkgs/nixos/modules/services/networking/nomad.nix b/nixpkgs/nixos/modules/services/networking/nomad.nix
index b1e51195247a..8cb0264648de 100644
--- a/nixpkgs/nixos/modules/services/networking/nomad.nix
+++ b/nixpkgs/nixos/modules/services/networking/nomad.nix
@@ -10,14 +10,7 @@ in
     services.nomad = {
       enable = mkEnableOption (lib.mdDoc "Nomad, a distributed, highly available, datacenter-aware scheduler");
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.nomad;
-        defaultText = literalExpression "pkgs.nomad";
-        description = lib.mdDoc ''
-          The package used for the Nomad agent and CLI.
-        '';
-      };
+      package = mkPackageOption pkgs "nomad" { };
 
       extraPackages = mkOption {
         type = types.listOf types.package;
diff --git a/nixpkgs/nixos/modules/services/networking/ntp/chrony.nix b/nixpkgs/nixos/modules/services/networking/ntp/chrony.nix
index 3f10145033c5..b56bea4e134f 100644
--- a/nixpkgs/nixos/modules/services/networking/ntp/chrony.nix
+++ b/nixpkgs/nixos/modules/services/networking/ntp/chrony.nix
@@ -47,14 +47,7 @@ in
         '';
       };
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.chrony;
-        defaultText = literalExpression "pkgs.chrony";
-        description = lib.mdDoc ''
-          Which chrony package to use.
-        '';
-      };
+      package = mkPackageOption pkgs "chrony" { };
 
       servers = mkOption {
         default = config.networking.timeServers;
diff --git a/nixpkgs/nixos/modules/services/networking/openconnect.nix b/nixpkgs/nixos/modules/services/networking/openconnect.nix
index 7f9006053b89..d2730faf9381 100644
--- a/nixpkgs/nixos/modules/services/networking/openconnect.nix
+++ b/nixpkgs/nixos/modules/services/networking/openconnect.nix
@@ -117,7 +117,7 @@ let
   };
 in {
   options.networking.openconnect = {
-    package = mkPackageOptionMD pkgs "openconnect" { };
+    package = mkPackageOption pkgs "openconnect" { };
 
     interfaces = mkOption {
       description = lib.mdDoc "OpenConnect interfaces.";
diff --git a/nixpkgs/nixos/modules/services/networking/peroxide.nix b/nixpkgs/nixos/modules/services/networking/peroxide.nix
index 885ee1d96cd0..34c82e2c8b03 100644
--- a/nixpkgs/nixos/modules/services/networking/peroxide.nix
+++ b/nixpkgs/nixos/modules/services/networking/peroxide.nix
@@ -11,7 +11,7 @@ in
   options.services.peroxide = {
     enable = mkEnableOption (lib.mdDoc "peroxide");
 
-    package = mkPackageOptionMD pkgs "peroxide" {
+    package = mkPackageOption pkgs "peroxide" {
       default = [ "peroxide" ];
     };
 
diff --git a/nixpkgs/nixos/modules/services/networking/pleroma.nix b/nixpkgs/nixos/modules/services/networking/pleroma.nix
index 89e64d36c8a0..db0a61b83469 100644
--- a/nixpkgs/nixos/modules/services/networking/pleroma.nix
+++ b/nixpkgs/nixos/modules/services/networking/pleroma.nix
@@ -6,12 +6,7 @@ in {
     services.pleroma = with lib; {
       enable = mkEnableOption (lib.mdDoc "pleroma");
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.pleroma;
-        defaultText = literalExpression "pkgs.pleroma";
-        description = lib.mdDoc "Pleroma package to use.";
-      };
+      package = mkPackageOption pkgs "pleroma" { };
 
       user = mkOption {
         type = types.str;
diff --git a/nixpkgs/nixos/modules/services/networking/pppd.nix b/nixpkgs/nixos/modules/services/networking/pppd.nix
index 75fc04c67571..855b5358f47f 100644
--- a/nixpkgs/nixos/modules/services/networking/pppd.nix
+++ b/nixpkgs/nixos/modules/services/networking/pppd.nix
@@ -14,12 +14,7 @@ in
     services.pppd = {
       enable = mkEnableOption (lib.mdDoc "pppd");
 
-      package = mkOption {
-        default = pkgs.ppp;
-        defaultText = literalExpression "pkgs.ppp";
-        type = types.package;
-        description = lib.mdDoc "pppd package to use.";
-      };
+      package = mkPackageOption pkgs "ppp" { };
 
       peers = mkOption {
         default = {};
diff --git a/nixpkgs/nixos/modules/services/networking/prosody.nix b/nixpkgs/nixos/modules/services/networking/prosody.nix
index 038d574bd878..2952df2a1099 100644
--- a/nixpkgs/nixos/modules/services/networking/prosody.nix
+++ b/nixpkgs/nixos/modules/services/networking/prosody.nix
@@ -496,12 +496,8 @@ in
         '';
       };
 
-      package = mkOption {
-        type = types.package;
-        description = lib.mdDoc "Prosody package to use";
-        default = pkgs.prosody;
-        defaultText = literalExpression "pkgs.prosody";
-        example = literalExpression ''
+      package = mkPackageOption pkgs "prosody" {
+        example = ''
           pkgs.prosody.override {
             withExtraLibs = [ pkgs.luaPackages.lpty ];
             withCommunityModules = [ "auth_external" ];
diff --git a/nixpkgs/nixos/modules/services/networking/quassel.nix b/nixpkgs/nixos/modules/services/networking/quassel.nix
index a074023b5ee4..4294d67fffd3 100644
--- a/nixpkgs/nixos/modules/services/networking/quassel.nix
+++ b/nixpkgs/nixos/modules/services/networking/quassel.nix
@@ -35,14 +35,7 @@ in
         '';
       };
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.quasselDaemon;
-        defaultText = literalExpression "pkgs.quasselDaemon";
-        description = lib.mdDoc ''
-          The package of the quassel daemon.
-        '';
-      };
+      package = mkPackageOption pkgs "quasselDaemon" { };
 
       interfaces = mkOption {
         type = types.listOf types.str;
diff --git a/nixpkgs/nixos/modules/services/networking/radvd.nix b/nixpkgs/nixos/modules/services/networking/radvd.nix
index 72590eda4ee6..57aa21287050 100644
--- a/nixpkgs/nixos/modules/services/networking/radvd.nix
+++ b/nixpkgs/nixos/modules/services/networking/radvd.nix
@@ -32,14 +32,7 @@ in
         '';
     };
 
-    package = mkOption {
-      type = types.package;
-      default = pkgs.radvd;
-      defaultText = literalExpression "pkgs.radvd";
-      description = lib.mdDoc ''
-        The RADVD package to use for the RADVD service.
-      '';
-    };
+    package = mkPackageOption pkgs "radvd" { };
 
     config = mkOption {
       type = types.lines;
diff --git a/nixpkgs/nixos/modules/services/networking/routedns.nix b/nixpkgs/nixos/modules/services/networking/routedns.nix
index 2a29a06700ce..126539702438 100644
--- a/nixpkgs/nixos/modules/services/networking/routedns.nix
+++ b/nixpkgs/nixos/modules/services/networking/routedns.nix
@@ -52,12 +52,7 @@ in
       description = lib.mdDoc "Path to RouteDNS TOML configuration file.";
     };
 
-    package = mkOption {
-      default = pkgs.routedns;
-      defaultText = literalExpression "pkgs.routedns";
-      type = types.package;
-      description = lib.mdDoc "RouteDNS package to use.";
-    };
+    package = mkPackageOption pkgs "routedns" { };
   };
 
   config = mkIf cfg.enable {
diff --git a/nixpkgs/nixos/modules/services/networking/sabnzbd.nix b/nixpkgs/nixos/modules/services/networking/sabnzbd.nix
index 8f3545df8995..cff2622b38e9 100644
--- a/nixpkgs/nixos/modules/services/networking/sabnzbd.nix
+++ b/nixpkgs/nixos/modules/services/networking/sabnzbd.nix
@@ -17,12 +17,7 @@ in
     services.sabnzbd = {
       enable = mkEnableOption (lib.mdDoc "the sabnzbd server");
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.sabnzbd;
-        defaultText = lib.literalExpression "pkgs.sabnzbd";
-        description = lib.mdDoc "The sabnzbd executable package run by the service.";
-      };
+      package = mkPackageOption pkgs "sabnzbd" { };
 
       configFile = mkOption {
         type = types.path;
diff --git a/nixpkgs/nixos/modules/services/networking/seafile.nix b/nixpkgs/nixos/modules/services/networking/seafile.nix
index b07d51b9b49a..9caabc60c78f 100644
--- a/nixpkgs/nixos/modules/services/networking/seafile.nix
+++ b/nixpkgs/nixos/modules/services/networking/seafile.nix
@@ -121,12 +121,7 @@ in {
       '';
     };
 
-    seafilePackage = mkOption {
-      type = types.package;
-      description = lib.mdDoc "Which package to use for the seafile server.";
-      default = pkgs.seafile-server;
-      defaultText = literalExpression "pkgs.seafile-server";
-    };
+    seafilePackage = mkPackageOption pkgs "seafile-server" { };
 
     seahubExtraConf = mkOption {
       default = "";
diff --git a/nixpkgs/nixos/modules/services/networking/searx.nix b/nixpkgs/nixos/modules/services/networking/searx.nix
index 8054f01d705f..938d585e3179 100644
--- a/nixpkgs/nixos/modules/services/networking/searx.nix
+++ b/nixpkgs/nixos/modules/services/networking/searx.nix
@@ -143,12 +143,7 @@ in
         '';
       };
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.searxng;
-        defaultText = literalExpression "pkgs.searxng";
-        description = lib.mdDoc "searx package to use.";
-      };
+      package = mkPackageOption pkgs "searxng" { };
 
       runInUwsgi = mkOption {
         type = types.bool;
diff --git a/nixpkgs/nixos/modules/services/networking/shellhub-agent.nix b/nixpkgs/nixos/modules/services/networking/shellhub-agent.nix
index 7cce23cb9c4e..ad33c50f9d63 100644
--- a/nixpkgs/nixos/modules/services/networking/shellhub-agent.nix
+++ b/nixpkgs/nixos/modules/services/networking/shellhub-agent.nix
@@ -14,7 +14,7 @@ in
 
       enable = mkEnableOption (lib.mdDoc "ShellHub Agent daemon");
 
-      package = mkPackageOptionMD pkgs "shellhub-agent" { };
+      package = mkPackageOption pkgs "shellhub-agent" { };
 
       preferredHostname = mkOption {
         type = types.str;
diff --git a/nixpkgs/nixos/modules/services/networking/sing-box.nix b/nixpkgs/nixos/modules/services/networking/sing-box.nix
index a884bcd271ec..ea7363713601 100644
--- a/nixpkgs/nixos/modules/services/networking/sing-box.nix
+++ b/nixpkgs/nixos/modules/services/networking/sing-box.nix
@@ -13,7 +13,7 @@ in
     services.sing-box = {
       enable = lib.mkEnableOption (lib.mdDoc "sing-box universal proxy platform");
 
-      package = lib.mkPackageOptionMD pkgs "sing-box" { };
+      package = lib.mkPackageOption pkgs "sing-box" { };
 
       settings = lib.mkOption {
         type = lib.types.submodule {
diff --git a/nixpkgs/nixos/modules/services/networking/skydns.nix b/nixpkgs/nixos/modules/services/networking/skydns.nix
index 84cf6b0deac1..0514bff2767e 100644
--- a/nixpkgs/nixos/modules/services/networking/skydns.nix
+++ b/nixpkgs/nixos/modules/services/networking/skydns.nix
@@ -55,12 +55,7 @@ in {
       example = ["8.8.8.8:53" "8.8.4.4:53"];
     };
 
-    package = mkOption {
-      default = pkgs.skydns;
-      defaultText = literalExpression "pkgs.skydns";
-      type = types.package;
-      description = lib.mdDoc "Skydns package to use.";
-    };
+    package = mkPackageOption pkgs "skydns" { };
 
     extraConfig = mkOption {
       default = {};
diff --git a/nixpkgs/nixos/modules/services/networking/smokeping.nix b/nixpkgs/nixos/modules/services/networking/smokeping.nix
index c7aec7d9489f..4ecf411c7496 100644
--- a/nixpkgs/nixos/modules/services/networking/smokeping.nix
+++ b/nixpkgs/nixos/modules/services/networking/smokeping.nix
@@ -165,12 +165,7 @@ in
         example = "no-reply@yourdomain.com";
         description = lib.mdDoc "Email contact for owner";
       };
-      package = mkOption {
-        type = types.package;
-        default = pkgs.smokeping;
-        defaultText = literalExpression "pkgs.smokeping";
-        description = lib.mdDoc "Specify a custom smokeping package";
-      };
+      package = mkPackageOption pkgs "smokeping" { };
       host = mkOption {
         type = types.nullOr types.str;
         default = "localhost";
diff --git a/nixpkgs/nixos/modules/services/networking/softether.nix b/nixpkgs/nixos/modules/services/networking/softether.nix
index c8e888eafcc2..234832ea0c0f 100644
--- a/nixpkgs/nixos/modules/services/networking/softether.nix
+++ b/nixpkgs/nixos/modules/services/networking/softether.nix
@@ -18,14 +18,7 @@ in
 
       enable = mkEnableOption (lib.mdDoc "SoftEther VPN services");
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.softether;
-        defaultText = literalExpression "pkgs.softether";
-        description = lib.mdDoc ''
-          softether derivation to use.
-        '';
-      };
+      package = mkPackageOption pkgs "softether" { };
 
       vpnserver.enable = mkEnableOption (lib.mdDoc "SoftEther VPN Server");
 
diff --git a/nixpkgs/nixos/modules/services/networking/spacecookie.nix b/nixpkgs/nixos/modules/services/networking/spacecookie.nix
index b2956edfcb7f..745c942ba60b 100644
--- a/nixpkgs/nixos/modules/services/networking/spacecookie.nix
+++ b/nixpkgs/nixos/modules/services/networking/spacecookie.nix
@@ -27,15 +27,8 @@ in {
 
       enable = mkEnableOption (lib.mdDoc "spacecookie");
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.spacecookie;
-        defaultText = literalExpression "pkgs.spacecookie";
-        example = literalExpression "pkgs.haskellPackages.spacecookie";
-        description = lib.mdDoc ''
-          The spacecookie derivation to use. This can be used to
-          override the used package or to use another version.
-        '';
+      package = mkPackageOption pkgs "spacecookie" {
+        example = "haskellPackages.spacecookie";
       };
 
       openFirewall = mkOption {
diff --git a/nixpkgs/nixos/modules/services/networking/squid.nix b/nixpkgs/nixos/modules/services/networking/squid.nix
index f93bcf19f2b3..68f4dc3d6dc1 100644
--- a/nixpkgs/nixos/modules/services/networking/squid.nix
+++ b/nixpkgs/nixos/modules/services/networking/squid.nix
@@ -111,12 +111,7 @@ in
         description = lib.mdDoc "Whether to run squid web proxy.";
       };
 
-      package = mkOption {
-        default = pkgs.squid;
-        defaultText = literalExpression "pkgs.squid";
-        type = types.package;
-        description = lib.mdDoc "Squid package to use.";
-      };
+      package = mkPackageOption pkgs "squid" { };
 
       proxyAddress = mkOption {
         type = types.nullOr types.str;
diff --git a/nixpkgs/nixos/modules/services/networking/strongswan-swanctl/module.nix b/nixpkgs/nixos/modules/services/networking/strongswan-swanctl/module.nix
index bfea89969728..c8832ed4defb 100644
--- a/nixpkgs/nixos/modules/services/networking/strongswan-swanctl/module.nix
+++ b/nixpkgs/nixos/modules/services/networking/strongswan-swanctl/module.nix
@@ -10,14 +10,7 @@ in  {
   options.services.strongswan-swanctl = {
     enable = mkEnableOption (lib.mdDoc "strongswan-swanctl service");
 
-    package = mkOption {
-      type = types.package;
-      default = pkgs.strongswan;
-      defaultText = literalExpression "pkgs.strongswan";
-      description = lib.mdDoc ''
-        The strongswan derivation to use.
-      '';
-    };
+    package = mkPackageOption pkgs "strongswan" { };
 
     strongswan.extraConfig = mkOption {
       type = types.str;
diff --git a/nixpkgs/nixos/modules/services/networking/syncthing.nix b/nixpkgs/nixos/modules/services/networking/syncthing.nix
index 6d9af6141f12..99d4d9eeffcc 100644
--- a/nixpkgs/nixos/modules/services/networking/syncthing.nix
+++ b/nixpkgs/nixos/modules/services/networking/syncthing.nix
@@ -583,14 +583,7 @@ in {
         '';
       };
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.syncthing;
-        defaultText = literalExpression "pkgs.syncthing";
-        description = lib.mdDoc ''
-          The Syncthing package to use.
-        '';
-      };
+      package = mkPackageOption pkgs "syncthing" { };
     };
   };
 
diff --git a/nixpkgs/nixos/modules/services/networking/tailscale.nix b/nixpkgs/nixos/modules/services/networking/tailscale.nix
index a5d171e0baab..3822df81063d 100644
--- a/nixpkgs/nixos/modules/services/networking/tailscale.nix
+++ b/nixpkgs/nixos/modules/services/networking/tailscale.nix
@@ -29,7 +29,7 @@ in {
       description = lib.mdDoc "Username or user ID of the user allowed to to fetch Tailscale TLS certificates for the node.";
     };
 
-    package = lib.mkPackageOptionMD pkgs "tailscale" {};
+    package = lib.mkPackageOption pkgs "tailscale" {};
 
     openFirewall = mkOption {
       default = false;
diff --git a/nixpkgs/nixos/modules/services/networking/tayga.nix b/nixpkgs/nixos/modules/services/networking/tayga.nix
index 299ae2777f7c..63423bf02922 100644
--- a/nixpkgs/nixos/modules/services/networking/tayga.nix
+++ b/nixpkgs/nixos/modules/services/networking/tayga.nix
@@ -64,12 +64,7 @@ in
     services.tayga = {
       enable = mkEnableOption (lib.mdDoc "Tayga");
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.tayga;
-        defaultText = lib.literalMD "pkgs.tayga";
-        description = lib.mdDoc "This option specifies the TAYGA package to use.";
-      };
+      package = mkPackageOption pkgs "tayga" { };
 
       ipv4 = mkOption {
         type = types.submodule (versionOpts 4);
diff --git a/nixpkgs/nixos/modules/services/networking/teleport.nix b/nixpkgs/nixos/modules/services/networking/teleport.nix
index 399af711c0e1..add6b47315b1 100644
--- a/nixpkgs/nixos/modules/services/networking/teleport.nix
+++ b/nixpkgs/nixos/modules/services/networking/teleport.nix
@@ -11,12 +11,8 @@ in
     services.teleport = with lib.types; {
       enable = mkEnableOption (lib.mdDoc "the Teleport service");
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.teleport;
-        defaultText = lib.literalMD "pkgs.teleport";
-        example = lib.literalMD "pkgs.teleport_11";
-        description = lib.mdDoc "The teleport package to use";
+      package = mkPackageOption pkgs "teleport" {
+        example = "teleport_11";
       };
 
       settings = mkOption {
diff --git a/nixpkgs/nixos/modules/services/networking/thelounge.nix b/nixpkgs/nixos/modules/services/networking/thelounge.nix
index 321e46fb5d4d..92da2e6c254b 100644
--- a/nixpkgs/nixos/modules/services/networking/thelounge.nix
+++ b/nixpkgs/nixos/modules/services/networking/thelounge.nix
@@ -25,7 +25,7 @@ in
   options.services.thelounge = {
     enable = mkEnableOption (lib.mdDoc "The Lounge web IRC client");
 
-    package = mkPackageOptionMD pkgs "thelounge" { };
+    package = mkPackageOption pkgs "thelounge" { };
 
     public = mkOption {
       type = types.bool;
diff --git a/nixpkgs/nixos/modules/services/networking/tinc.nix b/nixpkgs/nixos/modules/services/networking/tinc.nix
index 7db83e6a584b..eb769f53901c 100644
--- a/nixpkgs/nixos/modules/services/networking/tinc.nix
+++ b/nixpkgs/nixos/modules/services/networking/tinc.nix
@@ -279,14 +279,7 @@ in
               '';
             };
 
-            package = mkOption {
-              type = types.package;
-              default = pkgs.tinc_pre;
-              defaultText = literalExpression "pkgs.tinc_pre";
-              description = lib.mdDoc ''
-                The package to use for the tinc daemon's binary.
-              '';
-            };
+            package = mkPackageOption pkgs "tinc_pre" { };
 
             chroot = mkOption {
               default = false;
diff --git a/nixpkgs/nixos/modules/services/networking/tinyproxy.nix b/nixpkgs/nixos/modules/services/networking/tinyproxy.nix
index 9bcd8bfd814b..42d45c460c2e 100644
--- a/nixpkgs/nixos/modules/services/networking/tinyproxy.nix
+++ b/nixpkgs/nixos/modules/services/networking/tinyproxy.nix
@@ -28,7 +28,7 @@ in
   options = {
     services.tinyproxy = {
       enable = mkEnableOption (lib.mdDoc "Tinyproxy daemon");
-      package = mkPackageOptionMD pkgs "tinyproxy" {};
+      package = mkPackageOption pkgs "tinyproxy" {};
       settings = mkOption {
         description = lib.mdDoc "Configuration for [tinyproxy](https://tinyproxy.github.io/).";
         default = { };
diff --git a/nixpkgs/nixos/modules/services/networking/tmate-ssh-server.nix b/nixpkgs/nixos/modules/services/networking/tmate-ssh-server.nix
index ff4ce0773309..6bee2721f9a7 100644
--- a/nixpkgs/nixos/modules/services/networking/tmate-ssh-server.nix
+++ b/nixpkgs/nixos/modules/services/networking/tmate-ssh-server.nix
@@ -18,12 +18,7 @@ in
   options.services.tmate-ssh-server = {
     enable = mkEnableOption (mdDoc "tmate ssh server");
 
-    package = mkOption {
-      type = types.package;
-      description = mdDoc "The package containing tmate-ssh-server";
-      defaultText = literalExpression "pkgs.tmate-ssh-server";
-      default = pkgs.tmate-ssh-server;
-    };
+    package = mkPackageOption pkgs "tmate-ssh-server" { };
 
     host = mkOption {
       type = types.str;
@@ -81,12 +76,12 @@ in
       [
         (pkgs.writeShellApplication {
           name = "tmate-client-config";
-          runtimeInputs = with pkgs;[ openssh coreutils sd ];
+          runtimeInputs = with pkgs;[ openssh coreutils ];
           text = ''
             RSA_SIG="$(ssh-keygen -l -E SHA256 -f "${keysDir}/ssh_host_rsa_key.pub" | cut -d ' ' -f 2)"
             ED25519_SIG="$(ssh-keygen -l -E SHA256 -f "${keysDir}/ssh_host_ed25519_key.pub" | cut -d ' ' -f 2)"
-            sd -sp '@ed25519_fingerprint@' "$ED25519_SIG" ${tmate-config} | \
-              sd -sp '@rsa_fingerprint@' "$RSA_SIG"
+            sed "s|@ed25519_fingerprint@|$ED25519_SIG|g" ${tmate-config} | \
+              sed "s|@rsa_fingerprint@|$RSA_SIG|g"
           '';
         })
       ];
diff --git a/nixpkgs/nixos/modules/services/networking/trickster.nix b/nixpkgs/nixos/modules/services/networking/trickster.nix
index 0b696e412b4d..4b920ec446e0 100644
--- a/nixpkgs/nixos/modules/services/networking/trickster.nix
+++ b/nixpkgs/nixos/modules/services/networking/trickster.nix
@@ -20,14 +20,7 @@ in
         '';
       };
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.trickster;
-        defaultText = literalExpression "pkgs.trickster";
-        description = lib.mdDoc ''
-          Package that should be used for trickster.
-        '';
-      };
+      package = mkPackageOption pkgs "trickster" { };
 
       configFile = mkOption {
         type = types.nullOr types.path;
diff --git a/nixpkgs/nixos/modules/services/networking/trust-dns.nix b/nixpkgs/nixos/modules/services/networking/trust-dns.nix
index 758e33f16d38..47020341024b 100644
--- a/nixpkgs/nixos/modules/services/networking/trust-dns.nix
+++ b/nixpkgs/nixos/modules/services/networking/trust-dns.nix
@@ -48,13 +48,11 @@ in
   options = {
     services.trust-dns = with lib; {
       enable = mkEnableOption (lib.mdDoc "trust-dns");
-      package = mkOption {
-        type = types.package;
-        default = pkgs.trust-dns;
-        defaultText = "pkgs.trust-dns";
-        description = mdDoc ''
-          Trust-dns package to use.
-          The package must provide `meta.mainProgram` which names the server binary; any other utilities (client, resolver) are not needed.
+      package = mkPackageOption pkgs "trust-dns" {
+        extraDescription = ''
+          ::: {.note}
+          The package must provide `meta.mainProgram` which names the server binayr; any other utilities (client, resolver) are not needed.
+          :::
         '';
       };
       quiet = mkOption {
diff --git a/nixpkgs/nixos/modules/services/networking/twingate.nix b/nixpkgs/nixos/modules/services/networking/twingate.nix
index 03c68fc874f0..6874b1c18b57 100644
--- a/nixpkgs/nixos/modules/services/networking/twingate.nix
+++ b/nixpkgs/nixos/modules/services/networking/twingate.nix
@@ -6,7 +6,7 @@ in
 {
   options.services.twingate = {
     enable = lib.mkEnableOption (lib.mdDoc "Twingate Client daemon");
-    package = lib.mkPackageOptionMD pkgs "twingate" { };
+    package = lib.mkPackageOption pkgs "twingate" { };
   };
 
   config = lib.mkIf cfg.enable {
diff --git a/nixpkgs/nixos/modules/services/networking/ucarp.nix b/nixpkgs/nixos/modules/services/networking/ucarp.nix
index 1214cec63f54..56799fe00ade 100644
--- a/nixpkgs/nixos/modules/services/networking/ucarp.nix
+++ b/nixpkgs/nixos/modules/services/networking/ucarp.nix
@@ -143,16 +143,11 @@ in {
       default = null;
     };
 
-    package = mkOption {
-      type = types.package;
-      description = lib.mdDoc ''
-        Package that should be used for ucarp.
-
+    package = mkPackageOption pkgs "ucarp" {
+      extraDescription = ''
         Please note that the default package, pkgs.ucarp, has not received any
         upstream updates for a long time and can be considered as unmaintained.
       '';
-      default = pkgs.ucarp;
-      defaultText = literalExpression "pkgs.ucarp";
     };
   };
 
diff --git a/nixpkgs/nixos/modules/services/networking/unbound.nix b/nixpkgs/nixos/modules/services/networking/unbound.nix
index b6579af10a79..616b32f11797 100644
--- a/nixpkgs/nixos/modules/services/networking/unbound.nix
+++ b/nixpkgs/nixos/modules/services/networking/unbound.nix
@@ -42,12 +42,7 @@ in {
 
       enable = mkEnableOption (lib.mdDoc "Unbound domain name server");
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.unbound-with-systemd;
-        defaultText = literalExpression "pkgs.unbound-with-systemd";
-        description = lib.mdDoc "The unbound package to use";
-      };
+      package = mkPackageOption pkgs "unbound-with-systemd" { };
 
       user = mkOption {
         type = types.str;
diff --git a/nixpkgs/nixos/modules/services/networking/unifi.nix b/nixpkgs/nixos/modules/services/networking/unifi.nix
index 537a4db95ca7..8eb29f2bcdb6 100644
--- a/nixpkgs/nixos/modules/services/networking/unifi.nix
+++ b/nixpkgs/nixos/modules/services/networking/unifi.nix
@@ -36,21 +36,14 @@ in
       '';
     };
 
-    services.unifi.unifiPackage = lib.mkOption {
-      type = lib.types.package;
-      default = pkgs.unifi5;
-      defaultText = lib.literalExpression "pkgs.unifi5";
-      description = lib.mdDoc ''
-        The unifi package to use.
-      '';
-    };
-
-    services.unifi.mongodbPackage = lib.mkOption {
-      type = lib.types.package;
-      default = pkgs.mongodb-4_4;
-      defaultText = lib.literalExpression "pkgs.mongodb";
-      description = lib.mdDoc ''
-        The mongodb package to use. Please note: unifi7 officially only supports mongodb up until 3.6 but works with 4.4.
+    services.unifi.unifiPackage = lib.mkPackageOption pkgs "unifi5" { };
+
+    services.unifi.mongodbPackage = lib.mkPackageOption pkgs "mongodb" {
+      default = "mongodb-4_4";
+      extraDescription = ''
+        ::: {.note}
+        unifi7 officially only supports mongodb up until 3.6 but works with 4.4.
+        :::
       '';
     };
 
diff --git a/nixpkgs/nixos/modules/services/networking/v2ray.nix b/nixpkgs/nixos/modules/services/networking/v2ray.nix
index ba2aa5bc1de7..3e1895fbe20c 100644
--- a/nixpkgs/nixos/modules/services/networking/v2ray.nix
+++ b/nixpkgs/nixos/modules/services/networking/v2ray.nix
@@ -16,14 +16,7 @@ with lib;
         '';
       };
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.v2ray;
-        defaultText = literalExpression "pkgs.v2ray";
-        description = lib.mdDoc ''
-          Which v2ray package to use.
-        '';
-      };
+      package = mkPackageOption pkgs "v2ray" { };
 
       configFile = mkOption {
         type = types.nullOr types.str;
diff --git a/nixpkgs/nixos/modules/services/networking/vdirsyncer.nix b/nixpkgs/nixos/modules/services/networking/vdirsyncer.nix
index f9b880c763e3..6a069943434d 100644
--- a/nixpkgs/nixos/modules/services/networking/vdirsyncer.nix
+++ b/nixpkgs/nixos/modules/services/networking/vdirsyncer.nix
@@ -71,7 +71,7 @@ in
     services.vdirsyncer = {
       enable = mkEnableOption (mdDoc "vdirsyncer");
 
-      package = mkPackageOptionMD pkgs "vdirsyncer" {};
+      package = mkPackageOption pkgs "vdirsyncer" {};
 
       jobs = mkOption {
         description = mdDoc "vdirsyncer job configurations";
diff --git a/nixpkgs/nixos/modules/services/networking/webhook.nix b/nixpkgs/nixos/modules/services/networking/webhook.nix
index 2a78491941cf..b020db6961c3 100644
--- a/nixpkgs/nixos/modules/services/networking/webhook.nix
+++ b/nixpkgs/nixos/modules/services/networking/webhook.nix
@@ -36,7 +36,7 @@ in {
         which execute configured commands for any person or service that knows the URL
       '');
 
-      package = mkPackageOptionMD pkgs "webhook" {};
+      package = mkPackageOption pkgs "webhook" {};
       user = mkOption {
         type = types.str;
         default = defaultUser;
diff --git a/nixpkgs/nixos/modules/services/networking/wstunnel.nix b/nixpkgs/nixos/modules/services/networking/wstunnel.nix
index 3c3ecc3e04d7..2762c85651f4 100644
--- a/nixpkgs/nixos/modules/services/networking/wstunnel.nix
+++ b/nixpkgs/nixos/modules/services/networking/wstunnel.nix
@@ -48,7 +48,7 @@ let
       default = true;
     };
 
-    package = mkPackageOptionMD pkgs "wstunnel" {};
+    package = mkPackageOption pkgs "wstunnel" {};
 
     autoStart = mkOption {
       description = mdDoc "Whether this tunnel server should be started automatically.";
diff --git a/nixpkgs/nixos/modules/services/networking/x2goserver.nix b/nixpkgs/nixos/modules/services/networking/x2goserver.nix
index 1242229a0b60..f1eba9fafc1c 100644
--- a/nixpkgs/nixos/modules/services/networking/x2goserver.nix
+++ b/nixpkgs/nixos/modules/services/networking/x2goserver.nix
@@ -160,5 +160,8 @@ in {
     security.sudo.extraConfig = ''
       Defaults  env_keep+=QT_GRAPHICSSYSTEM
     '';
+    security.sudo-rs.extraConfig = ''
+      Defaults  env_keep+=QT_GRAPHICSSYSTEM
+    '';
   };
 }
diff --git a/nixpkgs/nixos/modules/services/networking/xandikos.nix b/nixpkgs/nixos/modules/services/networking/xandikos.nix
index 6d1ddc74c719..147f07ac546d 100644
--- a/nixpkgs/nixos/modules/services/networking/xandikos.nix
+++ b/nixpkgs/nixos/modules/services/networking/xandikos.nix
@@ -11,12 +11,7 @@ in
     services.xandikos = {
       enable = mkEnableOption (lib.mdDoc "Xandikos CalDAV and CardDAV server");
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.xandikos;
-        defaultText = literalExpression "pkgs.xandikos";
-        description = lib.mdDoc "The Xandikos package to use.";
-      };
+      package = mkPackageOption pkgs "xandikos" { };
 
       address = mkOption {
         type = types.str;
diff --git a/nixpkgs/nixos/modules/services/networking/xray.nix b/nixpkgs/nixos/modules/services/networking/xray.nix
index 83655a2f88ef..56c7887b3308 100644
--- a/nixpkgs/nixos/modules/services/networking/xray.nix
+++ b/nixpkgs/nixos/modules/services/networking/xray.nix
@@ -16,14 +16,7 @@ with lib;
         '';
       };
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.xray;
-        defaultText = literalExpression "pkgs.xray";
-        description = lib.mdDoc ''
-          Which xray package to use.
-        '';
-      };
+      package = mkPackageOption pkgs "xray" { };
 
       settingsFile = mkOption {
         type = types.nullOr types.path;
diff --git a/nixpkgs/nixos/modules/services/networking/xrdp.nix b/nixpkgs/nixos/modules/services/networking/xrdp.nix
index 218b440aab3c..3b674840b936 100644
--- a/nixpkgs/nixos/modules/services/networking/xrdp.nix
+++ b/nixpkgs/nixos/modules/services/networking/xrdp.nix
@@ -44,14 +44,7 @@ in
 
       enable = mkEnableOption (lib.mdDoc "xrdp, the Remote Desktop Protocol server");
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.xrdp;
-        defaultText = literalExpression "pkgs.xrdp";
-        description = lib.mdDoc ''
-          The package to use for the xrdp daemon's binary.
-        '';
-      };
+      package = mkPackageOption pkgs "xrdp" { };
 
       port = mkOption {
         type = types.port;
diff --git a/nixpkgs/nixos/modules/services/networking/yggdrasil.nix b/nixpkgs/nixos/modules/services/networking/yggdrasil.nix
index 56d81fb04013..514753687d69 100644
--- a/nixpkgs/nixos/modules/services/networking/yggdrasil.nix
+++ b/nixpkgs/nixos/modules/services/networking/yggdrasil.nix
@@ -108,12 +108,7 @@ in
         '';
       };
 
-      package = mkOption {
-        type = package;
-        default = pkgs.yggdrasil;
-        defaultText = literalExpression "pkgs.yggdrasil";
-        description = lib.mdDoc "Yggdrasil package to use.";
-      };
+      package = mkPackageOption pkgs "yggdrasil" { };
 
       persistentKeys = mkEnableOption (lib.mdDoc ''
         persistent keys. If enabled then keys will be generated once and Yggdrasil
diff --git a/nixpkgs/nixos/modules/services/networking/zeronet.nix b/nixpkgs/nixos/modules/services/networking/zeronet.nix
index 1f3711bd0d72..7e88a8b346d9 100644
--- a/nixpkgs/nixos/modules/services/networking/zeronet.nix
+++ b/nixpkgs/nixos/modules/services/networking/zeronet.nix
@@ -1,7 +1,8 @@
 { config, lib, pkgs, ... }:
 
 let
-  inherit (lib) generators literalExpression mkEnableOption mkIf mkOption recursiveUpdate types;
+  inherit (lib) generators literalExpression mkEnableOption mkPackageOption
+                mkIf mkOption recursiveUpdate types;
   cfg = config.services.zeronet;
   dataDir = "/var/lib/zeronet";
   configFile = pkgs.writeText "zeronet.conf" (generators.toINI {} (recursiveUpdate defaultSettings cfg.settings));
@@ -19,12 +20,7 @@ in with lib; {
   options.services.zeronet = {
     enable = mkEnableOption (lib.mdDoc "zeronet");
 
-    package = mkOption {
-      type = types.package;
-      default = pkgs.zeronet;
-      defaultText = literalExpression "pkgs.zeronet";
-      description = lib.mdDoc "ZeroNet package to use";
-    };
+    package = mkPackageOption pkgs "zeronet" { };
 
     settings = mkOption {
       type = with types; attrsOf (oneOf [ str int bool (listOf str) ]);
diff --git a/nixpkgs/nixos/modules/services/networking/zerotierone.nix b/nixpkgs/nixos/modules/services/networking/zerotierone.nix
index f78fd8642ba0..994e01d4980e 100644
--- a/nixpkgs/nixos/modules/services/networking/zerotierone.nix
+++ b/nixpkgs/nixos/modules/services/networking/zerotierone.nix
@@ -27,14 +27,7 @@ in
     '';
   };
 
-  options.services.zerotierone.package = mkOption {
-    default = pkgs.zerotierone;
-    defaultText = literalExpression "pkgs.zerotierone";
-    type = types.package;
-    description = lib.mdDoc ''
-      ZeroTier One package to use.
-    '';
-  };
+  options.services.zerotierone.package = mkPackageOption pkgs "zerotierone" { };
 
   config = mkIf cfg.enable {
     systemd.services.zerotierone = {
diff --git a/nixpkgs/nixos/modules/services/search/elasticsearch.nix b/nixpkgs/nixos/modules/services/search/elasticsearch.nix
index fa1627566ebe..6eebeb8b0a9a 100644
--- a/nixpkgs/nixos/modules/services/search/elasticsearch.nix
+++ b/nixpkgs/nixos/modules/services/search/elasticsearch.nix
@@ -50,12 +50,7 @@ in
       type = types.bool;
     };
 
-    package = mkOption {
-      description = lib.mdDoc "Elasticsearch package to use.";
-      default = pkgs.elasticsearch;
-      defaultText = literalExpression "pkgs.elasticsearch";
-      type = types.package;
-    };
+    package = mkPackageOption pkgs "elasticsearch" { };
 
     listenAddress = mkOption {
       description = lib.mdDoc "Elasticsearch listen address.";
diff --git a/nixpkgs/nixos/modules/services/search/hound.nix b/nixpkgs/nixos/modules/services/search/hound.nix
index b41a2e2bae1f..539a322b431f 100644
--- a/nixpkgs/nixos/modules/services/search/hound.nix
+++ b/nixpkgs/nixos/modules/services/search/hound.nix
@@ -48,14 +48,7 @@ in {
         '';
       };
 
-      package = mkOption {
-        default = pkgs.hound;
-        defaultText = literalExpression "pkgs.hound";
-        type = types.package;
-        description = lib.mdDoc ''
-          Package for running hound.
-        '';
-      };
+      package = mkPackageOption pkgs "hound" { };
 
       config = mkOption {
         type = types.str;
diff --git a/nixpkgs/nixos/modules/services/search/meilisearch.nix b/nixpkgs/nixos/modules/services/search/meilisearch.nix
index 7c9fa62ae954..4183847d1be3 100644
--- a/nixpkgs/nixos/modules/services/search/meilisearch.nix
+++ b/nixpkgs/nixos/modules/services/search/meilisearch.nix
@@ -16,11 +16,10 @@ in
   options.services.meilisearch = {
     enable = mkEnableOption (lib.mdDoc "MeiliSearch - a RESTful search API");
 
-    package = mkOption {
-      description = lib.mdDoc "The package to use for meilisearch. Use this if you require specific features to be enabled. The default package has no features.";
-      default = pkgs.meilisearch;
-      defaultText = lib.literalExpression "pkgs.meilisearch";
-      type = types.package;
+    package = mkPackageOption pkgs "meilisearch" {
+      extraDescription = ''
+        Use this if you require specific features to be enabled. The default package has no features.
+      '';
     };
 
     listenAddress = mkOption {
diff --git a/nixpkgs/nixos/modules/services/search/opensearch.nix b/nixpkgs/nixos/modules/services/search/opensearch.nix
index ae79d5545fd7..3c054b6d7caa 100644
--- a/nixpkgs/nixos/modules/services/search/opensearch.nix
+++ b/nixpkgs/nixos/modules/services/search/opensearch.nix
@@ -25,7 +25,7 @@ in
   options.services.opensearch = {
     enable = mkEnableOption (lib.mdDoc "OpenSearch");
 
-    package = lib.mkPackageOptionMD pkgs "OpenSearch" {
+    package = lib.mkPackageOption pkgs "OpenSearch" {
       default = [ "opensearch" ];
     };
 
@@ -200,7 +200,7 @@ in
               # Install plugins
 
               # remove plugins directory if it is empty.
-              if [ -z "$(ls -A ${cfg.dataDir}/plugins)" ]; then
+              if [[ -d ${cfg.dataDir}/plugins && -z "$(ls -A ${cfg.dataDir}/plugins)" ]]; then
                 rm -r "${cfg.dataDir}/plugins"
               fi
 
diff --git a/nixpkgs/nixos/modules/services/search/sonic-server.nix b/nixpkgs/nixos/modules/services/search/sonic-server.nix
new file mode 100644
index 000000000000..59d96ae6b05a
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/search/sonic-server.nix
@@ -0,0 +1,77 @@
+{ config, lib, pkgs, ... }:
+
+let
+  cfg = config.services.sonic-server;
+
+  settingsFormat = pkgs.formats.toml { };
+  configFile = settingsFormat.generate "sonic-server-config.toml" cfg.settings;
+
+in {
+  meta.maintainers = [ lib.maintainers.anthonyroussel ];
+
+  options = {
+    services.sonic-server = {
+      enable = lib.mkEnableOption (lib.mdDoc "Sonic Search Index");
+
+      package = lib.mkPackageOption pkgs "sonic-server" { };
+
+      settings = lib.mkOption {
+        type = lib.types.submodule { freeformType = settingsFormat.type; };
+        default = {
+          store.kv.path = "/var/lib/sonic/kv";
+          store.fst.path = "/var/lib/sonic/fst";
+        };
+        example = {
+          server.log_level = "debug";
+          channel.inet = "[::1]:1491";
+        };
+        description = lib.mdDoc ''
+          Sonic Server configuration options.
+
+          Refer to
+          <https://github.com/valeriansaliou/sonic/blob/master/CONFIGURATION.md>
+          for a full list of available options.
+        '';
+      };
+    };
+  };
+
+  config = lib.mkIf cfg.enable {
+    services.sonic-server.settings = lib.mapAttrs (name: lib.mkDefault) {
+      server = {};
+      channel.search = {};
+      store = {
+        kv = {
+          path = "/var/lib/sonic/kv";
+          database = {};
+          pool = {};
+        };
+        fst = {
+          path = "/var/lib/sonic/fst";
+          graph = {};
+          pool = {};
+        };
+      };
+    };
+
+    systemd.services.sonic-server = {
+      description = "Sonic Search Index";
+
+      wantedBy = [ "multi-user.target" ];
+      after = [ "network.target" ];
+
+      serviceConfig = {
+        Type = "simple";
+
+        ExecStart = "${lib.getExe cfg.package} -c ${configFile}";
+        DynamicUser = true;
+        Group = "sonic";
+        LimitNOFILE = "infinity";
+        Restart = "on-failure";
+        StateDirectory = "sonic";
+        StateDirectoryMode = "750";
+        User = "sonic";
+      };
+    };
+  };
+}
diff --git a/nixpkgs/nixos/modules/services/security/authelia.nix b/nixpkgs/nixos/modules/services/security/authelia.nix
index cc55260e20f8..614b3b1e22b2 100644
--- a/nixpkgs/nixos/modules/services/security/authelia.nix
+++ b/nixpkgs/nixos/modules/services/security/authelia.nix
@@ -24,12 +24,7 @@ let
         '';
       };
 
-      package = mkOption {
-        default = pkgs.authelia;
-        type = types.package;
-        defaultText = literalExpression "pkgs.authelia";
-        description = mdDoc "Authelia derivation to use.";
-      };
+      package = mkPackageOption pkgs "authelia" { };
 
       user = mkOption {
         default = "authelia-${name}";
diff --git a/nixpkgs/nixos/modules/services/security/certmgr.nix b/nixpkgs/nixos/modules/services/security/certmgr.nix
index ca4cf5084722..db80e943973d 100644
--- a/nixpkgs/nixos/modules/services/security/certmgr.nix
+++ b/nixpkgs/nixos/modules/services/security/certmgr.nix
@@ -37,12 +37,7 @@ in
   options.services.certmgr = {
     enable = mkEnableOption (lib.mdDoc "certmgr");
 
-    package = mkOption {
-      type = types.package;
-      default = pkgs.certmgr;
-      defaultText = literalExpression "pkgs.certmgr";
-      description = lib.mdDoc "Which certmgr package to use in the service.";
-    };
+    package = mkPackageOption pkgs "certmgr" { };
 
     defaultRemote = mkOption {
       type = types.str;
diff --git a/nixpkgs/nixos/modules/services/security/clamav.nix b/nixpkgs/nixos/modules/services/security/clamav.nix
index 34897a9ac7db..72a195d3a04e 100644
--- a/nixpkgs/nixos/modules/services/security/clamav.nix
+++ b/nixpkgs/nixos/modules/services/security/clamav.nix
@@ -15,6 +15,9 @@ let
 
   clamdConfigFile = pkgs.writeText "clamd.conf" (toKeyValue cfg.daemon.settings);
   freshclamConfigFile = pkgs.writeText "freshclam.conf" (toKeyValue cfg.updater.settings);
+  fangfrischConfigFile = pkgs.writeText "fangfrisch.conf" ''
+    ${lib.generators.toINI {} cfg.fangfrisch.settings}
+  '';
 in
 {
   imports = [
@@ -66,6 +69,36 @@ in
           '';
         };
       };
+      fangfrisch = {
+        enable = mkEnableOption (lib.mdDoc "ClamAV fangfrisch updater");
+
+        interval = mkOption {
+          type = types.str;
+          default = "hourly";
+          description = lib.mdDoc ''
+            How often freshclam is invoked. See systemd.time(7) for more
+            information about the format.
+          '';
+        };
+
+        settings = mkOption {
+          type = lib.types.submodule {
+            freeformType = with types; attrsOf (attrsOf (oneOf [ str int bool ]));
+          };
+          default = { };
+          example = {
+            securiteinfo = {
+              enabled = "yes";
+              customer_id = "your customer_id";
+            };
+          };
+          description = lib.mdDoc ''
+            fangfrisch configuration. Refer to <https://rseichter.github.io/fangfrisch/#_configuration>,
+            for details on supported values.
+            Note that by default urlhaus and sanesecurity are enabled.
+          '';
+        };
+      };
     };
   };
 
@@ -98,23 +131,32 @@ in
       DatabaseMirror = [ "database.clamav.net" ];
     };
 
+    services.clamav.fangfrisch.settings = {
+      DEFAULT.db_url = mkDefault "sqlite:////var/lib/clamav/fangfrisch_db.sqlite";
+      DEFAULT.local_directory = mkDefault stateDir;
+      DEFAULT.log_level = mkDefault "INFO";
+      urlhaus.enabled = mkDefault "yes";
+      urlhaus.max_size = mkDefault "2MB";
+      sanesecurity.enabled = mkDefault "yes";
+    };
+
     environment.etc."clamav/freshclam.conf".source = freshclamConfigFile;
     environment.etc."clamav/clamd.conf".source = clamdConfigFile;
 
     systemd.services.clamav-daemon = mkIf cfg.daemon.enable {
       description = "ClamAV daemon (clamd)";
-      after = optional cfg.updater.enable "clamav-freshclam.service";
+      after = optionals cfg.updater.enable [ "clamav-freshclam.service" ];
+      wants = optionals cfg.updater.enable [ "clamav-freshclam.service" ];
       wantedBy = [ "multi-user.target" ];
       restartTriggers = [ clamdConfigFile ];
 
-      preStart = ''
-        mkdir -m 0755 -p ${runDir}
-        chown ${clamavUser}:${clamavGroup} ${runDir}
-      '';
-
       serviceConfig = {
         ExecStart = "${pkg}/bin/clamd";
         ExecReload = "${pkgs.coreutils}/bin/kill -USR2 $MAINPID";
+        User = clamavUser;
+        Group = clamavGroup;
+        StateDirectory = "clamav";
+        RuntimeDirectory = "clamav";
         PrivateTmp = "yes";
         PrivateDevices = "yes";
         PrivateNetwork = "yes";
@@ -134,15 +176,63 @@ in
       description = "ClamAV virus database updater (freshclam)";
       restartTriggers = [ freshclamConfigFile ];
       after = [ "network-online.target" ];
-      preStart = ''
-        mkdir -m 0755 -p ${stateDir}
-        chown ${clamavUser}:${clamavGroup} ${stateDir}
-      '';
 
       serviceConfig = {
         Type = "oneshot";
         ExecStart = "${pkg}/bin/freshclam";
         SuccessExitStatus = "1"; # if databases are up to date
+        StateDirectory = "clamav";
+        RuntimeDirectory = "clamav";
+        User = clamavUser;
+        Group = clamavGroup;
+        PrivateTmp = "yes";
+        PrivateDevices = "yes";
+      };
+    };
+
+    systemd.services.clamav-fangfrisch-init = mkIf cfg.fangfrisch.enable {
+      wantedBy = [ "multi-user.target" ];
+      # if the sqlite file can be found assume the database has already been initialised
+      script = ''
+        db_url="${cfg.fangfrisch.settings.DEFAULT.db_url}"
+        db_path="''${db_url#sqlite:///}"
+
+        if [ ! -f "$db_path" ]; then
+          ${pkgs.fangfrisch}/bin/fangfrisch --conf ${fangfrischConfigFile} initdb
+        fi
+      '';
+      serviceConfig = {
+        Type = "oneshot";
+        StateDirectory = "clamav";
+        RuntimeDirectory = "clamav";
+        User = clamavUser;
+        Group = clamavGroup;
+        PrivateTmp = "yes";
+        PrivateDevices = "yes";
+      };
+    };
+
+    systemd.timers.clamav-fangfrisch = mkIf cfg.fangfrisch.enable {
+      description = "Timer for ClamAV virus database updater (fangfrisch)";
+      wantedBy = [ "timers.target" ];
+      timerConfig = {
+        OnCalendar = cfg.fangfrisch.interval;
+        Unit = "clamav-fangfrisch.service";
+      };
+    };
+
+    systemd.services.clamav-fangfrisch = mkIf cfg.fangfrisch.enable {
+      description = "ClamAV virus database updater (fangfrisch)";
+      restartTriggers = [ fangfrischConfigFile ];
+      after = [ "network-online.target" "clamav-fangfrisch-init.service" ];
+
+      serviceConfig = {
+        Type = "oneshot";
+        ExecStart = "${pkgs.fangfrisch}/bin/fangfrisch --conf ${fangfrischConfigFile} refresh";
+        StateDirectory = "clamav";
+        RuntimeDirectory = "clamav";
+        User = clamavUser;
+        Group = clamavGroup;
         PrivateTmp = "yes";
         PrivateDevices = "yes";
       };
diff --git a/nixpkgs/nixos/modules/services/security/esdm.nix b/nixpkgs/nixos/modules/services/security/esdm.nix
index 2b246fff7e96..134b4be1a94c 100644
--- a/nixpkgs/nixos/modules/services/security/esdm.nix
+++ b/nixpkgs/nixos/modules/services/security/esdm.nix
@@ -6,7 +6,7 @@ in
 {
   options.services.esdm = {
     enable = lib.mkEnableOption (lib.mdDoc "ESDM service configuration");
-    package = lib.mkPackageOptionMD pkgs "esdm" { };
+    package = lib.mkPackageOption pkgs "esdm" { };
     serverEnable = lib.mkOption {
       type = lib.types.bool;
       default = true;
diff --git a/nixpkgs/nixos/modules/services/security/fail2ban.nix b/nixpkgs/nixos/modules/services/security/fail2ban.nix
index 235f29ab8a6a..59b9ea70209d 100644
--- a/nixpkgs/nixos/modules/services/security/fail2ban.nix
+++ b/nixpkgs/nixos/modules/services/security/fail2ban.nix
@@ -77,12 +77,8 @@ in
         '';
       };
 
-      package = mkOption {
-        default = pkgs.fail2ban;
-        defaultText = literalExpression "pkgs.fail2ban";
-        type = types.package;
-        example = literalExpression "pkgs.fail2ban_0_11";
-        description = lib.mdDoc "The fail2ban package to use for running the fail2ban service.";
+      package = mkPackageOption pkgs "fail2ban" {
+        example = "fail2ban_0_11";
       };
 
       packageFirewall = mkOption {
@@ -128,8 +124,8 @@ in
       };
 
       banaction-allports = mkOption {
-        default = if config.networking.nftables.enable then "nftables-allport" else "iptables-allport";
-        defaultText = literalExpression ''if config.networking.nftables.enable then "nftables-allport" else "iptables-allport"'';
+        default = if config.networking.nftables.enable then "nftables-allports" else "iptables-allports";
+        defaultText = literalExpression ''if config.networking.nftables.enable then "nftables-allports" else "iptables-allports"'';
         type = types.str;
         description = lib.mdDoc ''
           Default banning action (e.g. iptables, iptables-new, iptables-multiport,
diff --git a/nixpkgs/nixos/modules/services/security/haka.nix b/nixpkgs/nixos/modules/services/security/haka.nix
index c93638f44d60..dda039857401 100644
--- a/nixpkgs/nixos/modules/services/security/haka.nix
+++ b/nixpkgs/nixos/modules/services/security/haka.nix
@@ -57,14 +57,7 @@ in
 
       enable = mkEnableOption (lib.mdDoc "Haka");
 
-      package = mkOption {
-        default = pkgs.haka;
-        defaultText = literalExpression "pkgs.haka";
-        type = types.package;
-        description = lib.mdDoc ''
-          Which Haka derivation to use.
-        '';
-      };
+      package = mkPackageOption pkgs "haka" { };
 
       configFile = mkOption {
         default = "empty.lua";
diff --git a/nixpkgs/nixos/modules/services/security/jitterentropy-rngd.nix b/nixpkgs/nixos/modules/services/security/jitterentropy-rngd.nix
index 7bfacb5ddc5d..289d2f7a9839 100644
--- a/nixpkgs/nixos/modules/services/security/jitterentropy-rngd.nix
+++ b/nixpkgs/nixos/modules/services/security/jitterentropy-rngd.nix
@@ -6,7 +6,7 @@ in
   options.services.jitterentropy-rngd = {
     enable =
       lib.mkEnableOption (lib.mdDoc "jitterentropy-rngd service configuration");
-    package = lib.mkPackageOptionMD pkgs "jitterentropy-rngd" { };
+    package = lib.mkPackageOption pkgs "jitterentropy-rngd" { };
   };
 
   config = lib.mkIf cfg.enable {
diff --git a/nixpkgs/nixos/modules/services/security/kanidm.nix b/nixpkgs/nixos/modules/services/security/kanidm.nix
index 6f4d1dc382ab..c8d8f69729e9 100644
--- a/nixpkgs/nixos/modules/services/security/kanidm.nix
+++ b/nixpkgs/nixos/modules/services/security/kanidm.nix
@@ -69,7 +69,7 @@ in
     enableServer = lib.mkEnableOption (lib.mdDoc "the Kanidm server");
     enablePam = lib.mkEnableOption (lib.mdDoc "the Kanidm PAM and NSS integration");
 
-    package = lib.mkPackageOptionMD pkgs "kanidm" {};
+    package = lib.mkPackageOption pkgs "kanidm" {};
 
     serverSettings = lib.mkOption {
       type = lib.types.submodule {
diff --git a/nixpkgs/nixos/modules/services/security/nginx-sso.nix b/nixpkgs/nixos/modules/services/security/nginx-sso.nix
index 971f22ed3476..dd32b8356cbb 100644
--- a/nixpkgs/nixos/modules/services/security/nginx-sso.nix
+++ b/nixpkgs/nixos/modules/services/security/nginx-sso.nix
@@ -10,14 +10,7 @@ in {
   options.services.nginx.sso = {
     enable = mkEnableOption (lib.mdDoc "nginx-sso service");
 
-    package = mkOption {
-      type = types.package;
-      default = pkgs.nginx-sso;
-      defaultText = literalExpression "pkgs.nginx-sso";
-      description = lib.mdDoc ''
-        The nginx-sso package that should be used.
-      '';
-    };
+    package = mkPackageOption pkgs "nginx-sso" { };
 
     configuration = mkOption {
       type = types.attrsOf types.unspecified;
diff --git a/nixpkgs/nixos/modules/services/security/oauth2_proxy.nix b/nixpkgs/nixos/modules/services/security/oauth2_proxy.nix
index 718c3d2498ea..78916c907279 100644
--- a/nixpkgs/nixos/modules/services/security/oauth2_proxy.nix
+++ b/nixpkgs/nixos/modules/services/security/oauth2_proxy.nix
@@ -87,14 +87,7 @@ in
   options.services.oauth2_proxy = {
     enable = mkEnableOption (lib.mdDoc "oauth2_proxy");
 
-    package = mkOption {
-      type = types.package;
-      default = pkgs.oauth2-proxy;
-      defaultText = literalExpression "pkgs.oauth2-proxy";
-      description = lib.mdDoc ''
-        The package that provides oauth2-proxy.
-      '';
-    };
+    package = mkPackageOption pkgs "oauth2-proxy" { };
 
     ##############################################
     # PROVIDER configuration
diff --git a/nixpkgs/nixos/modules/services/security/pass-secret-service.nix b/nixpkgs/nixos/modules/services/security/pass-secret-service.nix
index c3c70d97ff59..f864f8a26595 100644
--- a/nixpkgs/nixos/modules/services/security/pass-secret-service.nix
+++ b/nixpkgs/nixos/modules/services/security/pass-secret-service.nix
@@ -9,12 +9,8 @@ in
   options.services.passSecretService = {
     enable = mkEnableOption (lib.mdDoc "pass secret service");
 
-    package = mkOption {
-      type = types.package;
-      default = pkgs.pass-secret-service;
-      defaultText = literalExpression "pkgs.pass-secret-service";
-      description = lib.mdDoc "Which pass-secret-service package to use.";
-      example = literalExpression "pkgs.pass-secret-service.override { python3 = pkgs.python310 }";
+    package = mkPackageOption pkgs "pass-secret-service" {
+      example = "pass-secret-service.override { python3 = pkgs.python310 }";
     };
   };
 
diff --git a/nixpkgs/nixos/modules/services/security/sks.nix b/nixpkgs/nixos/modules/services/security/sks.nix
index 550b61916a22..7ac5ecec0d82 100644
--- a/nixpkgs/nixos/modules/services/security/sks.nix
+++ b/nixpkgs/nixos/modules/services/security/sks.nix
@@ -21,12 +21,7 @@ in {
         server. You need to create "''${dataDir}/dump/*.gpg" for the initial
         import'');
 
-      package = mkOption {
-        default = pkgs.sks;
-        defaultText = literalExpression "pkgs.sks";
-        type = types.package;
-        description = lib.mdDoc "Which SKS derivation to use.";
-      };
+      package = mkPackageOption pkgs "sks" { };
 
       dataDir = mkOption {
         type = types.path;
diff --git a/nixpkgs/nixos/modules/services/security/tor.nix b/nixpkgs/nixos/modules/services/security/tor.nix
index 9e786eb2bf06..4ff941251c99 100644
--- a/nixpkgs/nixos/modules/services/security/tor.nix
+++ b/nixpkgs/nixos/modules/services/security/tor.nix
@@ -230,12 +230,7 @@ in
 
       openFirewall = mkEnableOption (lib.mdDoc "opening of the relay port(s) in the firewall");
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.tor;
-        defaultText = literalExpression "pkgs.tor";
-        description = lib.mdDoc "Tor package to use.";
-      };
+      package = mkPackageOption pkgs "tor" { };
 
       enableGeoIP = mkEnableOption (lib.mdDoc ''use of GeoIP databases.
         Disabling this will disable by-country statistics for bridges and relays
diff --git a/nixpkgs/nixos/modules/services/security/usbguard.nix b/nixpkgs/nixos/modules/services/security/usbguard.nix
index 071e69975143..f167fbb2eca8 100644
--- a/nixpkgs/nixos/modules/services/security/usbguard.nix
+++ b/nixpkgs/nixos/modules/services/security/usbguard.nix
@@ -39,13 +39,9 @@ in
     services.usbguard = {
       enable = mkEnableOption (lib.mdDoc "USBGuard daemon");
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.usbguard;
-        defaultText = literalExpression "pkgs.usbguard";
-        description = lib.mdDoc ''
-          The usbguard package to use. If you do not need the Qt GUI, use
-          `pkgs.usbguard-nox` to save disk space.
+      package = mkPackageOption pkgs "usbguard" {
+        extraDescription = ''
+          If you do not need the Qt GUI, use `pkgs.usbguard-nox` to save disk space.
         '';
       };
 
diff --git a/nixpkgs/nixos/modules/services/security/vault-agent.nix b/nixpkgs/nixos/modules/services/security/vault-agent.nix
index 17b8ff83592e..f8c281442f5f 100644
--- a/nixpkgs/nixos/modules/services/security/vault-agent.nix
+++ b/nixpkgs/nixos/modules/services/security/vault-agent.nix
@@ -14,7 +14,7 @@ let
       options = {
         enable = mkEnableOption (mdDoc "this ${flavour} instance") // { default = true; };
 
-        package = mkPackageOptionMD pkgs pkgName { };
+        package = mkPackageOption pkgs pkgName { };
 
         user = mkOption {
           type = types.str;
diff --git a/nixpkgs/nixos/modules/services/security/vault.nix b/nixpkgs/nixos/modules/services/security/vault.nix
index 18d981cdb0d2..31782073968f 100644
--- a/nixpkgs/nixos/modules/services/security/vault.nix
+++ b/nixpkgs/nixos/modules/services/security/vault.nix
@@ -45,12 +45,7 @@ in
     services.vault = {
       enable = mkEnableOption (lib.mdDoc "Vault daemon");
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.vault;
-        defaultText = literalExpression "pkgs.vault";
-        description = lib.mdDoc "This option specifies the vault package to use.";
-      };
+      package = mkPackageOption pkgs "vault" { };
 
       dev = mkOption {
         type = types.bool;
diff --git a/nixpkgs/nixos/modules/services/security/vaultwarden/default.nix b/nixpkgs/nixos/modules/services/security/vaultwarden/default.nix
index 0517615a4c6a..14bbfa95a9ca 100644
--- a/nixpkgs/nixos/modules/services/security/vaultwarden/default.nix
+++ b/nixpkgs/nixos/modules/services/security/vaultwarden/default.nix
@@ -156,12 +156,7 @@ in {
       '';
     };
 
-    package = mkOption {
-      type = package;
-      default = pkgs.vaultwarden;
-      defaultText = literalExpression "pkgs.vaultwarden";
-      description = lib.mdDoc "Vaultwarden package to use.";
-    };
+    package = mkPackageOption pkgs "vaultwarden" { };
 
     webVaultPackage = mkOption {
       type = package;
diff --git a/nixpkgs/nixos/modules/services/security/yubikey-agent.nix b/nixpkgs/nixos/modules/services/security/yubikey-agent.nix
index ee57ec8bf812..a9f15e4405f2 100644
--- a/nixpkgs/nixos/modules/services/security/yubikey-agent.nix
+++ b/nixpkgs/nixos/modules/services/security/yubikey-agent.nix
@@ -30,14 +30,7 @@ in
         '';
       };
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.yubikey-agent;
-        defaultText = literalExpression "pkgs.yubikey-agent";
-        description = lib.mdDoc ''
-          The package used for the yubikey-agent daemon.
-        '';
-      };
+      package = mkPackageOption pkgs "yubikey-agent" { };
     };
   };
 
diff --git a/nixpkgs/nixos/modules/services/system/automatic-timezoned.nix b/nixpkgs/nixos/modules/services/system/automatic-timezoned.nix
index 9bdd64dd33a3..8934ed3a7ef2 100644
--- a/nixpkgs/nixos/modules/services/system/automatic-timezoned.nix
+++ b/nixpkgs/nixos/modules/services/system/automatic-timezoned.nix
@@ -18,14 +18,7 @@ in
           the timezone.
         '';
       };
-      package = mkOption {
-        type = types.package;
-        default = pkgs.automatic-timezoned;
-        defaultText = literalExpression "pkgs.automatic-timezoned";
-        description = mdDoc ''
-          Which `automatic-timezoned` package to use.
-        '';
-      };
+      package = mkPackageOption pkgs "automatic-timezoned" { };
     };
   };
 
diff --git a/nixpkgs/nixos/modules/services/system/bpftune.nix b/nixpkgs/nixos/modules/services/system/bpftune.nix
index d656a19c0ad1..7106d5e4f78e 100644
--- a/nixpkgs/nixos/modules/services/system/bpftune.nix
+++ b/nixpkgs/nixos/modules/services/system/bpftune.nix
@@ -11,7 +11,7 @@ in
     services.bpftune = {
       enable = lib.mkEnableOption (lib.mdDoc "bpftune BPF driven auto-tuning");
 
-      package = lib.mkPackageOptionMD pkgs "bpftune" { };
+      package = lib.mkPackageOption pkgs "bpftune" { };
     };
   };
 
diff --git a/nixpkgs/nixos/modules/services/system/cachix-agent/default.nix b/nixpkgs/nixos/modules/services/system/cachix-agent/default.nix
index 06494ddb631a..196d3291d555 100644
--- a/nixpkgs/nixos/modules/services/system/cachix-agent/default.nix
+++ b/nixpkgs/nixos/modules/services/system/cachix-agent/default.nix
@@ -35,12 +35,7 @@ in {
       description = lib.mdDoc "Cachix uri to use.";
     };
 
-    package = mkOption {
-      type = types.package;
-      default = pkgs.cachix;
-      defaultText = literalExpression "pkgs.cachix";
-      description = lib.mdDoc "Cachix Client package to use.";
-    };
+    package = mkPackageOption pkgs "cachix" { };
 
     credentialsFile = mkOption {
       type = types.path;
diff --git a/nixpkgs/nixos/modules/services/system/cachix-watch-store.nix b/nixpkgs/nixos/modules/services/system/cachix-watch-store.nix
index 89157b460b9a..992a59cbc075 100644
--- a/nixpkgs/nixos/modules/services/system/cachix-watch-store.nix
+++ b/nixpkgs/nixos/modules/services/system/cachix-watch-store.nix
@@ -47,13 +47,7 @@ in
       default = false;
     };
 
-    package = mkOption {
-      type = types.package;
-      default = pkgs.cachix;
-      defaultText = literalExpression "pkgs.cachix";
-      description = lib.mdDoc "Cachix Client package to use.";
-    };
-
+    package = mkPackageOption pkgs "cachix" { };
   };
 
   config = mkIf cfg.enable {
diff --git a/nixpkgs/nixos/modules/services/system/saslauthd.nix b/nixpkgs/nixos/modules/services/system/saslauthd.nix
index 09720146aaa9..9424b6c51fc1 100644
--- a/nixpkgs/nixos/modules/services/system/saslauthd.nix
+++ b/nixpkgs/nixos/modules/services/system/saslauthd.nix
@@ -18,12 +18,7 @@ in
 
       enable = mkEnableOption (lib.mdDoc "saslauthd, the Cyrus SASL authentication daemon");
 
-      package = mkOption {
-        default = pkgs.cyrus_sasl.bin;
-        defaultText = literalExpression "pkgs.cyrus_sasl.bin";
-        type = types.package;
-        description = lib.mdDoc "Cyrus SASL package to use.";
-      };
+      package = mkPackageOption pkgs [ "cyrus_sasl" "bin" ] { };
 
       mechanism = mkOption {
         type = types.str;
diff --git a/nixpkgs/nixos/modules/services/system/zram-generator.nix b/nixpkgs/nixos/modules/services/system/zram-generator.nix
index 5902eda55696..10b9992375cc 100644
--- a/nixpkgs/nixos/modules/services/system/zram-generator.nix
+++ b/nixpkgs/nixos/modules/services/system/zram-generator.nix
@@ -11,7 +11,7 @@ in
   options.services.zram-generator = {
     enable = lib.mkEnableOption (lib.mdDoc "Systemd unit generator for zram devices");
 
-    package = lib.mkPackageOptionMD pkgs "zram-generator" { };
+    package = lib.mkPackageOption pkgs "zram-generator" { };
 
     settings = lib.mkOption {
       type = lib.types.submodule {
diff --git a/nixpkgs/nixos/modules/services/torrent/deluge.nix b/nixpkgs/nixos/modules/services/torrent/deluge.nix
index 003f7b2613b7..4802e3e1c63a 100644
--- a/nixpkgs/nixos/modules/services/torrent/deluge.nix
+++ b/nixpkgs/nixos/modules/services/torrent/deluge.nix
@@ -147,13 +147,7 @@ in {
           '';
         };
 
-        package = mkOption {
-          type = types.package;
-          example = literalExpression "pkgs.deluge-2_x";
-          description = lib.mdDoc ''
-            Deluge package to use.
-          '';
-        };
+        package = mkPackageOption pkgs "deluge-2_x" { };
       };
 
       deluge.web = {
diff --git a/nixpkgs/nixos/modules/services/torrent/flexget.nix b/nixpkgs/nixos/modules/services/torrent/flexget.nix
index 58a4b7001497..bc06b34a1f9e 100644
--- a/nixpkgs/nixos/modules/services/torrent/flexget.nix
+++ b/nixpkgs/nixos/modules/services/torrent/flexget.nix
@@ -16,7 +16,7 @@ in {
     services.flexget = {
       enable = mkEnableOption (lib.mdDoc "FlexGet daemon");
 
-      package = mkPackageOptionMD pkgs "flexget" {};
+      package = mkPackageOption pkgs "flexget" {};
 
       user = mkOption {
         default = "deluge";
diff --git a/nixpkgs/nixos/modules/services/torrent/opentracker.nix b/nixpkgs/nixos/modules/services/torrent/opentracker.nix
index 7d67491c1191..71852f24e55b 100644
--- a/nixpkgs/nixos/modules/services/torrent/opentracker.nix
+++ b/nixpkgs/nixos/modules/services/torrent/opentracker.nix
@@ -7,14 +7,7 @@ in {
   options.services.opentracker = {
     enable = mkEnableOption (lib.mdDoc "opentracker");
 
-    package = mkOption {
-      type = types.package;
-      description = lib.mdDoc ''
-        opentracker package to use
-      '';
-      default = pkgs.opentracker;
-      defaultText = literalExpression "pkgs.opentracker";
-    };
+    package = mkPackageOption pkgs "opentracker" { };
 
     extraOptions = mkOption {
       type = types.separatedString " ";
diff --git a/nixpkgs/nixos/modules/services/torrent/rtorrent.nix b/nixpkgs/nixos/modules/services/torrent/rtorrent.nix
index 64cda7fb675f..699f3be82a9d 100644
--- a/nixpkgs/nixos/modules/services/torrent/rtorrent.nix
+++ b/nixpkgs/nixos/modules/services/torrent/rtorrent.nix
@@ -53,14 +53,7 @@ in {
       '';
     };
 
-    package = mkOption {
-      type = types.package;
-      default = pkgs.rtorrent;
-      defaultText = literalExpression "pkgs.rtorrent";
-      description = lib.mdDoc ''
-        The rtorrent package to use.
-      '';
-    };
+    package = mkPackageOption pkgs "rtorrent" { };
 
     port = mkOption {
       type = types.port;
diff --git a/nixpkgs/nixos/modules/services/torrent/torrentstream.nix b/nixpkgs/nixos/modules/services/torrent/torrentstream.nix
new file mode 100644
index 000000000000..27aad06130e3
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/torrent/torrentstream.nix
@@ -0,0 +1,53 @@
+{ config, lib, pkgs, ... }:
+
+let
+  cfg = config.services.torrentstream;
+  dataDir = "/var/lib/torrentstream/";
+in
+{
+  options.services.torrentstream = {
+    enable = lib.mkEnableOption (lib.mdDoc "TorrentStream daemon");
+    package = lib.mkPackageOption pkgs "torrentstream" { };
+    port = lib.mkOption {
+      type = lib.types.port;
+      default = 5082;
+      description = lib.mdDoc ''
+        TorrentStream port.
+      '';
+    };
+    openFirewall = lib.mkOption {
+      type = lib.types.bool;
+      default = false;
+      description = lib.mdDoc ''
+        Open ports in the firewall for TorrentStream daemon.
+      '';
+    };
+    address = lib.mkOption {
+      type = lib.types.str;
+      default = "0.0.0.0";
+      description = lib.mdDoc ''
+        Address to listen on.
+      '';
+    };
+  };
+  config = lib.mkIf cfg.enable {
+    systemd.services.torrentstream = {
+      after = [ "network.target" ];
+      description = "TorrentStream Daemon";
+      wantedBy = [ "multi-user.target" ];
+      serviceConfig = {
+        ExecStart = lib.getExe cfg.package;
+        Restart = "on-failure";
+        UMask = "077";
+        StateDirectory = "torrentstream";
+        DynamicUser = true;
+      };
+      environment = {
+        WEB_PORT = toString cfg.port;
+        DOWNLOAD_PATH = "%S/torrentstream";
+        LISTEN_ADDR = cfg.address;
+      };
+    };
+    networking.firewall.allowedTCPPorts = lib.mkIf cfg.openFirewall [ cfg.port ];
+  };
+}
diff --git a/nixpkgs/nixos/modules/services/torrent/transmission.nix b/nixpkgs/nixos/modules/services/torrent/transmission.nix
index 5efb9334ea03..0cd24fb03a7b 100644
--- a/nixpkgs/nixos/modules/services/torrent/transmission.nix
+++ b/nixpkgs/nixos/modules/services/torrent/transmission.nix
@@ -174,7 +174,7 @@ in
         };
       };
 
-      package = mkPackageOptionMD pkgs "transmission" {};
+      package = mkPackageOption pkgs "transmission" {};
 
       downloadDirPermissions = mkOption {
         type = with types; nullOr str;
diff --git a/nixpkgs/nixos/modules/services/video/epgstation/default.nix b/nixpkgs/nixos/modules/services/video/epgstation/default.nix
index fca483b0dbd7..a7468e7cc2b6 100644
--- a/nixpkgs/nixos/modules/services/video/epgstation/default.nix
+++ b/nixpkgs/nixos/modules/services/video/epgstation/default.nix
@@ -80,11 +80,11 @@ in
   options.services.epgstation = {
     enable = lib.mkEnableOption (lib.mdDoc description);
 
-    package = lib.mkPackageOptionMD pkgs "epgstation" { };
+    package = lib.mkPackageOption pkgs "epgstation" { };
 
-    ffmpeg = lib.mkPackageOptionMD pkgs "ffmpeg" {
-      default = [ "ffmpeg-headless" ];
-      example = "pkgs.ffmpeg-full";
+    ffmpeg = lib.mkPackageOption pkgs "ffmpeg" {
+      default = "ffmpeg-headless";
+      example = "ffmpeg-full";
     };
 
     usePreconfiguredStreaming = lib.mkOption {
diff --git a/nixpkgs/nixos/modules/services/video/frigate.nix b/nixpkgs/nixos/modules/services/video/frigate.nix
index 8db2bfae80ac..146e968780c3 100644
--- a/nixpkgs/nixos/modules/services/video/frigate.nix
+++ b/nixpkgs/nixos/modules/services/video/frigate.nix
@@ -10,6 +10,7 @@ let
     mkDefault
     mdDoc
     mkEnableOption
+    mkPackageOption
     mkIf
     mkOption
     types;
@@ -62,13 +63,7 @@ in
   options.services.frigate = with types; {
     enable = mkEnableOption (mdDoc "Frigate NVR");
 
-    package = mkOption {
-      type = package;
-      default = pkgs.frigate;
-      description = mdDoc ''
-        The frigate package to use.
-      '';
-    };
+    package = mkPackageOption pkgs "frigate" { };
 
     hostname = mkOption {
       type = str;
diff --git a/nixpkgs/nixos/modules/services/video/go2rtc/default.nix b/nixpkgs/nixos/modules/services/video/go2rtc/default.nix
index 1151d31b68e6..13851fa0306f 100644
--- a/nixpkgs/nixos/modules/services/video/go2rtc/default.nix
+++ b/nixpkgs/nixos/modules/services/video/go2rtc/default.nix
@@ -11,7 +11,7 @@ let
     mdDoc
     mkEnableOption
     mkOption
-    mkPackageOptionMD
+    mkPackageOption
     types
     ;
 
@@ -28,7 +28,7 @@ in
   options.services.go2rtc = with types; {
     enable = mkEnableOption (mdDoc "go2rtc streaming server");
 
-    package = mkPackageOptionMD pkgs "go2rtc" { };
+    package = mkPackageOption pkgs "go2rtc" { };
 
     settings = mkOption {
       default = {};
diff --git a/nixpkgs/nixos/modules/services/video/mediamtx.nix b/nixpkgs/nixos/modules/services/video/mediamtx.nix
index 50f8e8810278..f741dea59e3e 100644
--- a/nixpkgs/nixos/modules/services/video/mediamtx.nix
+++ b/nixpkgs/nixos/modules/services/video/mediamtx.nix
@@ -11,7 +11,7 @@ in
     services.mediamtx = {
       enable = lib.mkEnableOption (lib.mdDoc "MediaMTX");
 
-      package = lib.mkPackageOptionMD pkgs "mediamtx" { };
+      package = lib.mkPackageOption pkgs "mediamtx" { };
 
       settings = lib.mkOption {
         description = lib.mdDoc ''
diff --git a/nixpkgs/nixos/modules/services/video/unifi-video.nix b/nixpkgs/nixos/modules/services/video/unifi-video.nix
index 5c93f60cbd79..518977e49bae 100644
--- a/nixpkgs/nixos/modules/services/video/unifi-video.nix
+++ b/nixpkgs/nixos/modules/services/video/unifi-video.nix
@@ -103,31 +103,12 @@ in
       '';
     };
 
-    jrePackage = mkOption {
-      type = types.package;
-      default = pkgs.jre8;
-      defaultText = literalExpression "pkgs.jre8";
-      description = lib.mdDoc ''
-        The JRE package to use. Check the release notes to ensure it is supported.
-      '';
-    };
+    jrePackage = mkPackageOption pkgs "jre8" { };
 
-    unifiVideoPackage = mkOption {
-      type = types.package;
-      default = pkgs.unifi-video;
-      defaultText = literalExpression "pkgs.unifi-video";
-      description = lib.mdDoc ''
-        The unifi-video package to use.
-      '';
-    };
+    unifiVideoPackage = mkPackageOption pkgs "unifi-video" { };
 
-    mongodbPackage = mkOption {
-      type = types.package;
-      default = pkgs.mongodb-4_4;
-      defaultText = literalExpression "pkgs.mongodb";
-      description = lib.mdDoc ''
-        The mongodb package to use.
-      '';
+    mongodbPackage = mkPackageOption pkgs "mongodb" {
+      default = "mongodb-4_4";
     };
 
     logDir = mkOption {
diff --git a/nixpkgs/nixos/modules/services/web-apps/akkoma.nix b/nixpkgs/nixos/modules/services/web-apps/akkoma.nix
index 8a8ed49115fd..8980556ab014 100644
--- a/nixpkgs/nixos/modules/services/web-apps/akkoma.nix
+++ b/nixpkgs/nixos/modules/services/web-apps/akkoma.nix
@@ -352,12 +352,7 @@ in {
     services.akkoma = {
       enable = mkEnableOption (mdDoc "Akkoma");
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.akkoma;
-        defaultText = literalExpression "pkgs.akkoma";
-        description = mdDoc "Akkoma package to use.";
-      };
+      package = mkPackageOption pkgs "akkoma" { };
 
       user = mkOption {
         type = types.nonEmptyStr;
diff --git a/nixpkgs/nixos/modules/services/web-apps/anuko-time-tracker.nix b/nixpkgs/nixos/modules/services/web-apps/anuko-time-tracker.nix
index f43cbc40ec7a..3b326390fa43 100644
--- a/nixpkgs/nixos/modules/services/web-apps/anuko-time-tracker.nix
+++ b/nixpkgs/nixos/modules/services/web-apps/anuko-time-tracker.nix
@@ -58,7 +58,7 @@ in
   options.services.anuko-time-tracker = {
     enable = lib.mkEnableOption (lib.mdDoc "Anuko Time Tracker");
 
-    package = lib.mkPackageOptionMD pkgs "anuko-time-tracker" {};
+    package = lib.mkPackageOption pkgs "anuko-time-tracker" {};
 
     database = {
       createLocally = lib.mkOption {
diff --git a/nixpkgs/nixos/modules/services/web-apps/atlassian/confluence.nix b/nixpkgs/nixos/modules/services/web-apps/atlassian/confluence.nix
index fe98c1777ea0..aa13659fcc30 100644
--- a/nixpkgs/nixos/modules/services/web-apps/atlassian/confluence.nix
+++ b/nixpkgs/nixos/modules/services/web-apps/atlassian/confluence.nix
@@ -133,18 +133,14 @@ in
         };
       };
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.atlassian-confluence;
-        defaultText = literalExpression "pkgs.atlassian-confluence";
-        description = lib.mdDoc "Atlassian Confluence package to use.";
-      };
-
-      jrePackage = mkOption {
-        type = types.package;
-        default = pkgs.oraclejre8;
-        defaultText = literalExpression "pkgs.oraclejre8";
-        description = lib.mdDoc "Note that Atlassian only support the Oracle JRE (JRASERVER-46152).";
+      package = mkPackageOption pkgs "atlassian-confluence" { };
+
+      jrePackage = mkPackageOption pkgs "oraclejre8" {
+        extraDescription = ''
+        ::: {.note }
+        Atlassian only supports the Oracle JRE (JRASERVER-46152).
+        :::
+        '';
       };
     };
   };
diff --git a/nixpkgs/nixos/modules/services/web-apps/atlassian/crowd.nix b/nixpkgs/nixos/modules/services/web-apps/atlassian/crowd.nix
index c8d1eaef31d8..eed1a127fe4f 100644
--- a/nixpkgs/nixos/modules/services/web-apps/atlassian/crowd.nix
+++ b/nixpkgs/nixos/modules/services/web-apps/atlassian/crowd.nix
@@ -115,18 +115,14 @@ in
         };
       };
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.atlassian-crowd;
-        defaultText = literalExpression "pkgs.atlassian-crowd";
-        description = lib.mdDoc "Atlassian Crowd package to use.";
-      };
-
-      jrePackage = mkOption {
-        type = types.package;
-        default = pkgs.oraclejre8;
-        defaultText = literalExpression "pkgs.oraclejre8";
-        description = lib.mdDoc "Note that Atlassian only support the Oracle JRE (JRASERVER-46152).";
+      package = mkPackageOption pkgs "atlassian-crowd" { };
+
+      jrePackage = mkPackageOption pkgs "oraclejre8" {
+        extraDescription = ''
+        ::: {.note }
+        Atlassian only supports the Oracle JRE (JRASERVER-46152).
+        :::
+        '';
       };
     };
   };
diff --git a/nixpkgs/nixos/modules/services/web-apps/atlassian/jira.nix b/nixpkgs/nixos/modules/services/web-apps/atlassian/jira.nix
index 4cc858216944..a9f337810a0f 100644
--- a/nixpkgs/nixos/modules/services/web-apps/atlassian/jira.nix
+++ b/nixpkgs/nixos/modules/services/web-apps/atlassian/jira.nix
@@ -132,18 +132,14 @@ in
         };
       };
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.atlassian-jira;
-        defaultText = literalExpression "pkgs.atlassian-jira";
-        description = lib.mdDoc "Atlassian JIRA package to use.";
-      };
-
-      jrePackage = mkOption {
-        type = types.package;
-        default = pkgs.oraclejre8;
-        defaultText = literalExpression "pkgs.oraclejre8";
-        description = lib.mdDoc "Note that Atlassian only support the Oracle JRE (JRASERVER-46152).";
+      package = mkPackageOption pkgs "atlassian-jira" { };
+
+      jrePackage = mkPackageOption pkgs "oraclejre8" {
+        extraDescription = ''
+        ::: {.note }
+        Atlassian only supports the Oracle JRE (JRASERVER-46152).
+        :::
+        '';
       };
     };
   };
diff --git a/nixpkgs/nixos/modules/services/web-apps/coder.nix b/nixpkgs/nixos/modules/services/web-apps/coder.nix
index f65211308c40..0f5cb2c3c689 100644
--- a/nixpkgs/nixos/modules/services/web-apps/coder.nix
+++ b/nixpkgs/nixos/modules/services/web-apps/coder.nix
@@ -36,14 +36,7 @@ in {
         '';
       };
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.coder;
-        description = lib.mdDoc ''
-          Package to use for the service.
-        '';
-        defaultText = literalExpression "pkgs.coder";
-      };
+      package = mkPackageOption pkgs "coder" { };
 
       homeDir = mkOption {
         type = types.str;
diff --git a/nixpkgs/nixos/modules/services/web-apps/documize.nix b/nixpkgs/nixos/modules/services/web-apps/documize.nix
index f70da0829f44..6f88b3f3c6d2 100644
--- a/nixpkgs/nixos/modules/services/web-apps/documize.nix
+++ b/nixpkgs/nixos/modules/services/web-apps/documize.nix
@@ -23,14 +23,7 @@ in {
       '';
     };
 
-    package = mkOption {
-      type = types.package;
-      default = pkgs.documize-community;
-      defaultText = literalExpression "pkgs.documize-community";
-      description = lib.mdDoc ''
-        Which package to use for documize.
-      '';
-    };
+    package = mkPackageOption pkgs "documize-community" { };
 
     salt = mkOption {
       type = types.nullOr types.str;
diff --git a/nixpkgs/nixos/modules/services/web-apps/dokuwiki.nix b/nixpkgs/nixos/modules/services/web-apps/dokuwiki.nix
index 9e9bfb1bfd83..1df1cbf9f0e1 100644
--- a/nixpkgs/nixos/modules/services/web-apps/dokuwiki.nix
+++ b/nixpkgs/nixos/modules/services/web-apps/dokuwiki.nix
@@ -182,12 +182,7 @@ let
       options = {
         enable = mkEnableOption (lib.mdDoc "DokuWiki web application");
 
-        package = mkOption {
-          type = types.package;
-          default = pkgs.dokuwiki;
-          defaultText = literalExpression "pkgs.dokuwiki";
-          description = lib.mdDoc "Which DokuWiki package to use.";
-        };
+        package = mkPackageOption pkgs "dokuwiki" { };
 
         stateDir = mkOption {
           type = types.path;
@@ -335,14 +330,9 @@ let
           '';
         };
 
-        phpPackage = mkOption {
-          type = types.package;
-          relatedPackages = [ "php81" "php82" ];
-          default = pkgs.php81;
-          defaultText = "pkgs.php81";
-          description = lib.mdDoc ''
-            PHP package to use for this dokuwiki site.
-          '';
+        phpPackage = mkPackageOption pkgs "php" {
+          default = "php81";
+          example = "php82";
         };
 
         phpOptions = mkOption {
diff --git a/nixpkgs/nixos/modules/services/web-apps/dolibarr.nix b/nixpkgs/nixos/modules/services/web-apps/dolibarr.nix
index 453229c130c2..193be47ab9b2 100644
--- a/nixpkgs/nixos/modules/services/web-apps/dolibarr.nix
+++ b/nixpkgs/nixos/modules/services/web-apps/dolibarr.nix
@@ -1,8 +1,8 @@
 { config, pkgs, lib, ... }:
 let
-  inherit (lib) any boolToString concatStringsSep isBool isString mapAttrsToList mkDefault mkEnableOption mkIf mkMerge mkOption optionalAttrs types;
+  inherit (lib) any boolToString concatStringsSep isBool isString mapAttrsToList mkDefault mkEnableOption mkIf mkMerge mkOption optionalAttrs types mkPackageOption;
 
-  package = pkgs.dolibarr.override { inherit (cfg) stateDir; };
+  package = cfg.package.override { inherit (cfg) stateDir; };
 
   cfg = config.services.dolibarr;
   vhostCfg = lib.optionalAttrs (cfg.nginx != null) config.services.nginx.virtualHosts."${cfg.domain}";
@@ -50,6 +50,8 @@ in
   options.services.dolibarr = {
     enable = mkEnableOption (lib.mdDoc "dolibarr");
 
+    package = mkPackageOption pkgs "dolibarr" { };
+
     domain = mkOption {
       type = types.str;
       default = "localhost";
diff --git a/nixpkgs/nixos/modules/services/web-apps/engelsystem.nix b/nixpkgs/nixos/modules/services/web-apps/engelsystem.nix
index 138e2f3f1b90..669620debce5 100644
--- a/nixpkgs/nixos/modules/services/web-apps/engelsystem.nix
+++ b/nixpkgs/nixos/modules/services/web-apps/engelsystem.nix
@@ -1,7 +1,7 @@
 { config, lib, pkgs, utils, ... }:
 
 let
-  inherit (lib) mkDefault mkEnableOption mkIf mkOption types literalExpression;
+  inherit (lib) mkDefault mkEnableOption mkIf mkOption types mkPackageOption;
   cfg = config.services.engelsystem;
 in {
   options = {
@@ -22,12 +22,7 @@ in {
         description = lib.mdDoc "Domain to serve on.";
       };
 
-      package = mkOption {
-        type = types.package;
-        description = lib.mdDoc "Engelsystem package used for the service.";
-        default = pkgs.engelsystem;
-        defaultText = literalExpression "pkgs.engelsystem";
-      };
+      package = mkPackageOption pkgs "engelsystem" { };
 
       createDatabase = mkOption {
         type = types.bool;
diff --git a/nixpkgs/nixos/modules/services/web-apps/ethercalc.nix b/nixpkgs/nixos/modules/services/web-apps/ethercalc.nix
index a5be86a34aa6..a38e89ec0de9 100644
--- a/nixpkgs/nixos/modules/services/web-apps/ethercalc.nix
+++ b/nixpkgs/nixos/modules/services/web-apps/ethercalc.nix
@@ -24,12 +24,7 @@ in {
         '';
       };
 
-      package = mkOption {
-        default = pkgs.ethercalc;
-        defaultText = literalExpression "pkgs.ethercalc";
-        type = types.package;
-        description = lib.mdDoc "Ethercalc package to use.";
-      };
+      package = mkPackageOption pkgs "ethercalc" { };
 
       host = mkOption {
         type = types.str;
diff --git a/nixpkgs/nixos/modules/services/web-apps/fluidd.nix b/nixpkgs/nixos/modules/services/web-apps/fluidd.nix
index d4b86b9dfb39..1d9b56f5ccf2 100644
--- a/nixpkgs/nixos/modules/services/web-apps/fluidd.nix
+++ b/nixpkgs/nixos/modules/services/web-apps/fluidd.nix
@@ -8,12 +8,7 @@ in
   options.services.fluidd = {
     enable = mkEnableOption (lib.mdDoc "Fluidd, a Klipper web interface for managing your 3d printer");
 
-    package = mkOption {
-      type = types.package;
-      description = lib.mdDoc "Fluidd package to be used in the module";
-      default = pkgs.fluidd;
-      defaultText = literalExpression "pkgs.fluidd";
-    };
+    package = mkPackageOption pkgs "fluidd" { };
 
     hostName = mkOption {
       type = types.str;
diff --git a/nixpkgs/nixos/modules/services/web-apps/freshrss.nix b/nixpkgs/nixos/modules/services/web-apps/freshrss.nix
index 8b4ea2aa53c9..9683730bbe1f 100644
--- a/nixpkgs/nixos/modules/services/web-apps/freshrss.nix
+++ b/nixpkgs/nixos/modules/services/web-apps/freshrss.nix
@@ -12,12 +12,7 @@ in
   options.services.freshrss = {
     enable = mkEnableOption (mdDoc "FreshRSS feed reader");
 
-    package = mkOption {
-      type = types.package;
-      default = pkgs.freshrss;
-      defaultText = lib.literalExpression "pkgs.freshrss";
-      description = mdDoc "Which FreshRSS package to use.";
-    };
+    package = mkPackageOption pkgs "freshrss" { };
 
     defaultUser = mkOption {
       type = types.str;
diff --git a/nixpkgs/nixos/modules/services/web-apps/galene.nix b/nixpkgs/nixos/modules/services/web-apps/galene.nix
index 81fed8a0b99a..28d4069ec385 100644
--- a/nixpkgs/nixos/modules/services/web-apps/galene.nix
+++ b/nixpkgs/nixos/modules/services/web-apps/galene.nix
@@ -110,14 +110,7 @@ in
         description = lib.mdDoc "Web server directory.";
       };
 
-      package = mkOption {
-        default = pkgs.galene;
-        defaultText = literalExpression "pkgs.galene";
-        type = types.package;
-        description = lib.mdDoc ''
-          Package for running Galene.
-        '';
-      };
+      package = mkPackageOption pkgs "galene" { };
     };
   };
 
diff --git a/nixpkgs/nixos/modules/services/web-apps/gerrit.nix b/nixpkgs/nixos/modules/services/web-apps/gerrit.nix
index ab2eeea09bdc..5c62a7ebbd93 100644
--- a/nixpkgs/nixos/modules/services/web-apps/gerrit.nix
+++ b/nixpkgs/nixos/modules/services/web-apps/gerrit.nix
@@ -61,19 +61,9 @@ in
     services.gerrit = {
       enable = mkEnableOption (lib.mdDoc "Gerrit service");
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.gerrit;
-        defaultText = literalExpression "pkgs.gerrit";
-        description = lib.mdDoc "Gerrit package to use";
-      };
+      package = mkPackageOption pkgs "gerrit" { };
 
-      jvmPackage = mkOption {
-        type = types.package;
-        default = pkgs.jre_headless;
-        defaultText = literalExpression "pkgs.jre_headless";
-        description = lib.mdDoc "Java Runtime Environment package to use";
-      };
+      jvmPackage = mkPackageOption pkgs "jre_headless" { };
 
       jvmOpts = mkOption {
         type = types.listOf types.str;
diff --git a/nixpkgs/nixos/modules/services/web-apps/gotosocial.nix b/nixpkgs/nixos/modules/services/web-apps/gotosocial.nix
index 9c21719a5759..45464f646da8 100644
--- a/nixpkgs/nixos/modules/services/web-apps/gotosocial.nix
+++ b/nixpkgs/nixos/modules/services/web-apps/gotosocial.nix
@@ -32,7 +32,7 @@ in
   options.services.gotosocial = {
     enable = lib.mkEnableOption (lib.mdDoc "ActivityPub social network server");
 
-    package = lib.mkPackageOptionMD pkgs "gotosocial" { };
+    package = lib.mkPackageOption pkgs "gotosocial" { };
 
     openFirewall = lib.mkOption {
       type = lib.types.bool;
diff --git a/nixpkgs/nixos/modules/services/web-apps/grocy.nix b/nixpkgs/nixos/modules/services/web-apps/grocy.nix
index fe40a3c20941..858fd74279d0 100644
--- a/nixpkgs/nixos/modules/services/web-apps/grocy.nix
+++ b/nixpkgs/nixos/modules/services/web-apps/grocy.nix
@@ -8,7 +8,7 @@ in {
   options.services.grocy = {
     enable = mkEnableOption (lib.mdDoc "grocy");
 
-    package = mkPackageOptionMD pkgs "grocy" { };
+    package = mkPackageOption pkgs "grocy" { };
 
     hostName = mkOption {
       type = types.str;
diff --git a/nixpkgs/nixos/modules/services/web-apps/guacamole-client.nix b/nixpkgs/nixos/modules/services/web-apps/guacamole-client.nix
index c12f6582468c..04d867c0a943 100644
--- a/nixpkgs/nixos/modules/services/web-apps/guacamole-client.nix
+++ b/nixpkgs/nixos/modules/services/web-apps/guacamole-client.nix
@@ -11,7 +11,7 @@ in
   options = {
     services.guacamole-client = {
       enable = lib.mkEnableOption (lib.mdDoc "Apache Guacamole Client (Tomcat)");
-      package = lib.mkPackageOptionMD pkgs "guacamole-client" { };
+      package = lib.mkPackageOption pkgs "guacamole-client" { };
 
       settings = lib.mkOption {
         type = lib.types.submodule {
diff --git a/nixpkgs/nixos/modules/services/web-apps/guacamole-server.nix b/nixpkgs/nixos/modules/services/web-apps/guacamole-server.nix
index 0cffdce83d83..71e80d8aad32 100644
--- a/nixpkgs/nixos/modules/services/web-apps/guacamole-server.nix
+++ b/nixpkgs/nixos/modules/services/web-apps/guacamole-server.nix
@@ -10,7 +10,7 @@ in
   options = {
     services.guacamole-server = {
       enable = lib.mkEnableOption (lib.mdDoc "Apache Guacamole Server (guacd)");
-      package = lib.mkPackageOptionMD pkgs "guacamole-server" { };
+      package = lib.mkPackageOption pkgs "guacamole-server" { };
 
       extraEnvironment = lib.mkOption {
         type = lib.types.attrsOf lib.types.str;
diff --git a/nixpkgs/nixos/modules/services/web-apps/healthchecks.nix b/nixpkgs/nixos/modules/services/web-apps/healthchecks.nix
index b92525075541..e5e425a29d54 100644
--- a/nixpkgs/nixos/modules/services/web-apps/healthchecks.nix
+++ b/nixpkgs/nixos/modules/services/web-apps/healthchecks.nix
@@ -33,12 +33,7 @@ in
       '';
     };
 
-    package = mkOption {
-      default = pkgs.healthchecks;
-      defaultText = literalExpression "pkgs.healthchecks";
-      type = types.package;
-      description = lib.mdDoc "healthchecks package to use.";
-    };
+    package = mkPackageOption pkgs "healthchecks" { };
 
     user = mkOption {
       default = defaultUser;
diff --git a/nixpkgs/nixos/modules/services/web-apps/hedgedoc.nix b/nixpkgs/nixos/modules/services/web-apps/hedgedoc.nix
index 1a66f077b09d..adcfe80a7332 100644
--- a/nixpkgs/nixos/modules/services/web-apps/hedgedoc.nix
+++ b/nixpkgs/nixos/modules/services/web-apps/hedgedoc.nix
@@ -33,7 +33,7 @@ in
   ];
 
   options.services.hedgedoc = {
-    package = lib.mkPackageOptionMD pkgs "hedgedoc" { };
+    package = lib.mkPackageOption pkgs "hedgedoc" { };
     enable = lib.mkEnableOption (mdDoc "the HedgeDoc Markdown Editor");
 
     settings = mkOption {
diff --git a/nixpkgs/nixos/modules/services/web-apps/honk.nix b/nixpkgs/nixos/modules/services/web-apps/honk.nix
index d47b17e54ffb..eb270a661ecb 100644
--- a/nixpkgs/nixos/modules/services/web-apps/honk.nix
+++ b/nixpkgs/nixos/modules/services/web-apps/honk.nix
@@ -22,7 +22,7 @@ in
   options = {
     services.honk = {
       enable = lib.mkEnableOption (lib.mdDoc "the Honk server");
-      package = lib.mkPackageOptionMD pkgs "honk" { };
+      package = lib.mkPackageOption pkgs "honk" { };
 
       host = lib.mkOption {
         default = "127.0.0.1";
diff --git a/nixpkgs/nixos/modules/services/web-apps/invidious.nix b/nixpkgs/nixos/modules/services/web-apps/invidious.nix
index e4fbc6fd9368..cfba3c8a2970 100644
--- a/nixpkgs/nixos/modules/services/web-apps/invidious.nix
+++ b/nixpkgs/nixos/modules/services/web-apps/invidious.nix
@@ -185,12 +185,7 @@ in
   options.services.invidious = {
     enable = lib.mkEnableOption (lib.mdDoc "Invidious");
 
-    package = lib.mkOption {
-      type = types.package;
-      default = pkgs.invidious;
-      defaultText = lib.literalExpression "pkgs.invidious";
-      description = lib.mdDoc "The Invidious package to use.";
-    };
+    package = lib.mkPackageOption pkgs "invidious" { };
 
     settings = lib.mkOption {
       type = settingsFormat.type;
diff --git a/nixpkgs/nixos/modules/services/web-apps/invoiceplane.nix b/nixpkgs/nixos/modules/services/web-apps/invoiceplane.nix
index f419b75cf70f..429520470a0d 100644
--- a/nixpkgs/nixos/modules/services/web-apps/invoiceplane.nix
+++ b/nixpkgs/nixos/modules/services/web-apps/invoiceplane.nix
@@ -28,7 +28,19 @@ let
     REMOVE_INDEXPHP=true
   '';
 
-  extraConfig = hostName: cfg: pkgs.writeText "extraConfig.php" ''
+  mkPhpValue = v:
+    if isString v then escapeShellArg v
+    # NOTE: If any value contains a , (comma) this will not get escaped
+    else if isList v && any lib.strings.isCoercibleToString v then escapeShellArg (concatMapStringsSep "," toString v)
+    else if isInt v then toString v
+    else if isBool v then boolToString v
+    else abort "The Invoiceplane config value ${lib.generators.toPretty {} v} can not be encoded."
+  ;
+
+  extraConfig = hostName: cfg: let
+    settings = mapAttrsToList (k: v: "${k}=${mkPhpValue v}") cfg.settings;
+  in pkgs.writeText "extraConfig.php" ''
+    ${concatStringsSep "\n" settings}
     ${toString cfg.extraConfig}
   '';
 
@@ -182,11 +194,31 @@ let
             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.
           '';
         };
 
-        cron = {
+        settings = mkOption {
+          type = types.attrsOf types.anything;
+          default = {};
+          description = lib.mdDoc ''
+            Structural InvoicePlane configuration. Refer to
+            <https://github.com/InvoicePlane/InvoicePlane/blob/master/ipconfig.php.example>
+            for details and supported values.
+          '';
+          example = literalExpression ''
+            {
+              SETUP_COMPLETED = true;
+              DISABLE_SETUP = true;
+              IP_URL = "https://invoice.example.com";
+            }
+          '';
+        };
 
+        cron = {
           enable = mkOption {
             type = types.bool;
             default = false;
@@ -197,12 +229,10 @@ let
               on how to configure it.
             '';
           };
-
           key = mkOption {
             type = types.str;
             description = lib.mdDoc "Cron key taken from the administration page.";
           };
-
         };
 
       };
@@ -239,8 +269,14 @@ in
   # implementation
   config = mkIf (eachSite != {}) (mkMerge [{
 
-    assertions = flatten (mapAttrsToList (hostName: cfg:
-      [{ assertion = cfg.database.createLocally -> cfg.database.user == user;
+    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'';
       }
       { assertion = cfg.database.createLocally -> cfg.database.passwordFile == null;
diff --git a/nixpkgs/nixos/modules/services/web-apps/jirafeau.nix b/nixpkgs/nixos/modules/services/web-apps/jirafeau.nix
index b2e274167164..5f754d824a28 100644
--- a/nixpkgs/nixos/modules/services/web-apps/jirafeau.nix
+++ b/nixpkgs/nixos/modules/services/web-apps/jirafeau.nix
@@ -92,12 +92,7 @@ in
       description = lib.mdDoc "Extra configuration for the nginx virtual host of Jirafeau.";
     };
 
-    package = mkOption {
-      type = types.package;
-      default = pkgs.jirafeau;
-      defaultText = literalExpression "pkgs.jirafeau";
-      description = lib.mdDoc "Jirafeau package to use";
-    };
+    package = mkPackageOption pkgs "jirafeau" { };
 
     poolConfig = mkOption {
       type = with types; attrsOf (oneOf [ str int bool ]);
diff --git a/nixpkgs/nixos/modules/services/web-apps/jitsi-meet.nix b/nixpkgs/nixos/modules/services/web-apps/jitsi-meet.nix
index c0f9d785eea2..0c0eb66e65b7 100644
--- a/nixpkgs/nixos/modules/services/web-apps/jitsi-meet.nix
+++ b/nixpkgs/nixos/modules/services/web-apps/jitsi-meet.nix
@@ -479,7 +479,7 @@ in
         extraConfig =
         let
           templatedJitsiMeet = pkgs.runCommand "templated-jitsi-meet" { } ''
-            cp -R ${pkgs.jitsi-meet}/* .
+            cp -R --no-preserve=all ${pkgs.jitsi-meet}/* .
             for file in *.html **/*.html ; do
               ${pkgs.sd}/bin/sd '<!--#include virtual="(.*)" -->' '{{ include "$1" }}' $file
             done
diff --git a/nixpkgs/nixos/modules/services/web-apps/kavita.nix b/nixpkgs/nixos/modules/services/web-apps/kavita.nix
index ca9cd01d403d..c3e39f0b5476 100644
--- a/nixpkgs/nixos/modules/services/web-apps/kavita.nix
+++ b/nixpkgs/nixos/modules/services/web-apps/kavita.nix
@@ -12,7 +12,7 @@ in {
       description = lib.mdDoc "User account under which Kavita runs.";
     };
 
-    package = lib.mkPackageOptionMD pkgs "kavita" { };
+    package = lib.mkPackageOption pkgs "kavita" { };
 
     dataDir = lib.mkOption {
       default = "/var/lib/kavita";
diff --git a/nixpkgs/nixos/modules/services/web-apps/keycloak.nix b/nixpkgs/nixos/modules/services/web-apps/keycloak.nix
index a7e4fab8ea28..5d44bdee64a7 100644
--- a/nixpkgs/nixos/modules/services/web-apps/keycloak.nix
+++ b/nixpkgs/nixos/modules/services/web-apps/keycloak.nix
@@ -11,6 +11,7 @@ let
     mkChangedOptionModule
     mkRenamedOptionModule
     mkRemovedOptionModule
+    mkPackageOption
     concatStringsSep
     mapAttrsToList
     escapeShellArg
@@ -246,14 +247,7 @@ in
         };
       };
 
-      package = mkOption {
-        type = package;
-        default = pkgs.keycloak;
-        defaultText = literalExpression "pkgs.keycloak";
-        description = lib.mdDoc ''
-          Keycloak package to use.
-        '';
-      };
+      package = mkPackageOption pkgs "keycloak" { };
 
       initialAdminPassword = mkOption {
         type = str;
diff --git a/nixpkgs/nixos/modules/services/web-apps/lanraragi.nix b/nixpkgs/nixos/modules/services/web-apps/lanraragi.nix
index f1ab8b8b4eb4..6703da005ab0 100644
--- a/nixpkgs/nixos/modules/services/web-apps/lanraragi.nix
+++ b/nixpkgs/nixos/modules/services/web-apps/lanraragi.nix
@@ -9,7 +9,7 @@ in
   options.services = {
     lanraragi = {
       enable = lib.mkEnableOption (lib.mdDoc "LANraragi");
-      package = lib.mkPackageOptionMD pkgs "lanraragi" { };
+      package = lib.mkPackageOption pkgs "lanraragi" { };
 
       port = lib.mkOption {
         type = lib.types.port;
@@ -72,11 +72,10 @@ in
         "HOME" = "/var/lib/lanraragi";
       };
       preStart = ''
-        REDIS_PASS=${lib.optionalString (cfg.redis.passwordFile != null) "$(head -n1 ${cfg.redis.passwordFile})"}
         cat > lrr.conf <<EOF
         {
           redis_address => "127.0.0.1:${toString cfg.redis.port}",
-          redis_password => "$REDIS_PASS",
+          redis_password => "${lib.optionalString (cfg.redis.passwordFile != null) ''$(head -n1 ${cfg.redis.passwordFile})''}",
           redis_database => "0",
           redis_database_minion => "1",
           redis_database_config => "2",
@@ -84,15 +83,9 @@ in
         }
         EOF
       '' + lib.optionalString (cfg.passwordFile != null) ''
-        PASS_HASH=$(
-          PASS=$(head -n1 ${cfg.passwordFile}) ${cfg.package.perlEnv}/bin/perl -I${cfg.package}/share/lanraragi/lib -e \
-            'use LANraragi::Controller::Config; print LANraragi::Controller::Config::make_password_hash($ENV{PASS})' \
-            2>/dev/null
-        )
-
-        ${lib.getExe pkgs.redis} -h 127.0.0.1 -p ${toString cfg.redis.port} -a "$REDIS_PASS" <<EOF
+        ${lib.getExe pkgs.redis} -h 127.0.0.1 -p ${toString cfg.redis.port} ${lib.optionalString (cfg.redis.passwordFile != null) ''-a "$(head -n1 ${cfg.redis.passwordFile})"''}<<EOF
           SELECT 2
-          HSET LRR_CONFIG password $PASS_HASH
+          HSET LRR_CONFIG password $(${cfg.package}/bin/helpers/lrr-make-password-hash $(head -n1 ${cfg.passwordFile}))
         EOF
       '';
     };
diff --git a/nixpkgs/nixos/modules/services/web-apps/lemmy.nix b/nixpkgs/nixos/modules/services/web-apps/lemmy.nix
index 32389f7a59dd..bde9051a7033 100644
--- a/nixpkgs/nixos/modules/services/web-apps/lemmy.nix
+++ b/nixpkgs/nixos/modules/services/web-apps/lemmy.nix
@@ -17,11 +17,11 @@ in
     enable = mkEnableOption (lib.mdDoc "lemmy a federated alternative to reddit in rust");
 
     server = {
-      package = mkPackageOptionMD pkgs "lemmy-server" {};
+      package = mkPackageOption pkgs "lemmy-server" {};
     };
 
     ui = {
-      package = mkPackageOptionMD pkgs "lemmy-ui" {};
+      package = mkPackageOption pkgs "lemmy-ui" {};
 
       port = mkOption {
         type = types.port;
diff --git a/nixpkgs/nixos/modules/services/web-apps/mainsail.nix b/nixpkgs/nixos/modules/services/web-apps/mainsail.nix
index f335d9b015d4..95de2c5640b4 100644
--- a/nixpkgs/nixos/modules/services/web-apps/mainsail.nix
+++ b/nixpkgs/nixos/modules/services/web-apps/mainsail.nix
@@ -8,12 +8,7 @@ in
   options.services.mainsail = {
     enable = mkEnableOption (lib.mdDoc "a modern and responsive user interface for Klipper");
 
-    package = mkOption {
-      type = types.package;
-      description = lib.mdDoc "Mainsail package to be used in the module";
-      default = pkgs.mainsail;
-      defaultText = literalExpression "pkgs.mainsail";
-    };
+    package = mkPackageOption pkgs "mainsail" { };
 
     hostName = mkOption {
       type = types.str;
diff --git a/nixpkgs/nixos/modules/services/web-apps/matomo.nix b/nixpkgs/nixos/modules/services/web-apps/matomo.nix
index eadf8b62b977..fef5dc82de04 100644
--- a/nixpkgs/nixos/modules/services/web-apps/matomo.nix
+++ b/nixpkgs/nixos/modules/services/web-apps/matomo.nix
@@ -36,16 +36,7 @@ in {
         '';
       };
 
-      package = mkOption {
-        type = types.package;
-        description = lib.mdDoc ''
-          Matomo package for the service to use.
-          This can be used to point to newer releases from nixos-unstable,
-          as they don't get backported if they are not security-relevant.
-        '';
-        default = pkgs.matomo;
-        defaultText = literalExpression "pkgs.matomo";
-      };
+      package = mkPackageOption pkgs "matomo" { };
 
       webServerUser = mkOption {
         type = types.nullOr types.str;
diff --git a/nixpkgs/nixos/modules/services/web-apps/mattermost.nix b/nixpkgs/nixos/modules/services/web-apps/mattermost.nix
index 24f3b3331845..f19465eeb59a 100644
--- a/nixpkgs/nixos/modules/services/web-apps/mattermost.nix
+++ b/nixpkgs/nixos/modules/services/web-apps/mattermost.nix
@@ -102,12 +102,7 @@ in
     services.mattermost = {
       enable = mkEnableOption (lib.mdDoc "Mattermost chat server");
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.mattermost;
-        defaultText = lib.literalExpression "pkgs.mattermost";
-        description = lib.mdDoc "Mattermost derivation to use.";
-      };
+      package = mkPackageOption pkgs "mattermostl" { };
 
       statePath = mkOption {
         type = types.str;
@@ -250,12 +245,7 @@ in
 
       matterircd = {
         enable = mkEnableOption (lib.mdDoc "Mattermost IRC bridge");
-        package = mkOption {
-          type = types.package;
-          default = pkgs.matterircd;
-          defaultText = lib.literalExpression "pkgs.matterircd";
-          description = lib.mdDoc "matterircd derivation to use.";
-        };
+        package = mkPackageOption pkgs "matterircd" { };
         parameters = mkOption {
           type = types.listOf types.str;
           default = [ ];
diff --git a/nixpkgs/nixos/modules/services/web-apps/mediawiki.nix b/nixpkgs/nixos/modules/services/web-apps/mediawiki.nix
index ce7bcd94b3f0..5549b6ae1eaa 100644
--- a/nixpkgs/nixos/modules/services/web-apps/mediawiki.nix
+++ b/nixpkgs/nixos/modules/services/web-apps/mediawiki.nix
@@ -2,7 +2,7 @@
 
 let
 
-  inherit (lib) mkDefault mkEnableOption mkForce mkIf mkMerge mkOption;
+  inherit (lib) mkDefault mkEnableOption mkPackageOption mkForce mkIf mkMerge mkOption;
   inherit (lib) concatStringsSep literalExpression mapAttrsToList optional optionals optionalString types;
 
   cfg = config.services.mediawiki;
@@ -20,21 +20,21 @@ let
 
   pkg = pkgs.stdenv.mkDerivation rec {
     pname = "mediawiki-full";
-    version = src.version;
+    inherit (src) version;
     src = cfg.package;
 
     installPhase = ''
       mkdir -p $out
       cp -r * $out/
 
-      rm -rf $out/share/mediawiki/skins/*
-      rm -rf $out/share/mediawiki/extensions/*
-
+      # try removing directories before symlinking to allow overwriting any builtin extension or skin
       ${concatStringsSep "\n" (mapAttrsToList (k: v: ''
+        rm -rf $out/share/mediawiki/skins/${k}
         ln -s ${v} $out/share/mediawiki/skins/${k}
       '') cfg.skins)}
 
       ${concatStringsSep "\n" (mapAttrsToList (k: v: ''
+        rm -rf $out/share/mediawiki/extensions/${k}
         ln -s ${if v != null then v else "$src/share/mediawiki/extensions/${k}"} $out/share/mediawiki/extensions/${k}
       '') cfg.extensions)}
     '';
@@ -194,12 +194,7 @@ in
 
       enable = mkEnableOption (lib.mdDoc "MediaWiki");
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.mediawiki;
-        defaultText = literalExpression "pkgs.mediawiki";
-        description = lib.mdDoc "Which MediaWiki package to use.";
-      };
+      package = mkPackageOption pkgs "mediawiki" { };
 
       finalPackage = mkOption {
         type = types.package;
@@ -230,11 +225,8 @@ in
             "${if hasSSL config.services.nginx.virtualHosts.${cfg.nginx.hostName} then "https" else "http"}://${cfg.nginx.hostName}"
           else
             "http://localhost";
-        defaultText = literalExpression ''
-          if cfg.webserver == "apache" then
-            "''${if cfg.httpd.virtualHost.addSSL || cfg.httpd.virtualHost.forceSSL || cfg.httpd.virtualHost.onlySSL then "https" else "http"}://''${cfg.httpd.virtualHost.hostName}"
-          else
-            "http://localhost";
+        defaultText = ''
+          if "mediawiki uses ssl" then "{"https" else "http"}://''${cfg.hostName}" else "http://localhost";
         '';
         example = "https://wiki.example.org";
         description = lib.mdDoc "URL of the wiki.";
@@ -310,7 +302,7 @@ in
 
       database = {
         type = mkOption {
-          type = types.enum [ "mysql" "postgres" "sqlite" "mssql" "oracle" ];
+          type = types.enum [ "mysql" "postgres" "mssql" "oracle" ];
           default = "mysql";
           description = lib.mdDoc "Database engine to use. MySQL/MariaDB is the database of choice by MediaWiki developers.";
         };
@@ -543,9 +535,8 @@ in
         locations = {
           "~ ^/w/(index|load|api|thumb|opensearch_desc|rest|img_auth)\\.php$".extraConfig = ''
             rewrite ^/w/(.*) /$1 break;
-            include ${config.services.nginx.package}/conf/fastcgi_params;
+            include ${config.services.nginx.package}/conf/fastcgi.conf;
             fastcgi_index index.php;
-            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
             fastcgi_pass unix:${config.services.phpfpm.pools.mediawiki.socket};
           '';
           "/w/images/".alias = withTrailingSlash cfg.uploadsDir;
@@ -576,7 +567,7 @@ in
 
           # Explicit access to the root website, redirect to main page (adapt as needed)
           "= /".extraConfig = ''
-            return 301 /wiki/Main_Page;
+            return 301 /wiki/;
           '';
 
           # Every other entry point will be disallowed.
@@ -611,15 +602,15 @@ in
         ${pkgs.php}/bin/php ${pkg}/share/mediawiki/maintenance/install.php \
           --confpath /tmp \
           --scriptpath / \
-          --dbserver "${dbAddr}" \
+          --dbserver ${lib.escapeShellArg dbAddr} \
           --dbport ${toString cfg.database.port} \
-          --dbname ${cfg.database.name} \
-          ${optionalString (cfg.database.tablePrefix != null) "--dbprefix ${cfg.database.tablePrefix}"} \
-          --dbuser ${cfg.database.user} \
-          ${optionalString (cfg.database.passwordFile != null) "--dbpassfile ${cfg.database.passwordFile}"} \
-          --passfile ${cfg.passwordFile} \
+          --dbname ${lib.escapeShellArg cfg.database.name} \
+          ${optionalString (cfg.database.tablePrefix != null) "--dbprefix ${lib.escapeShellArg cfg.database.tablePrefix}"} \
+          --dbuser ${lib.escapeShellArg cfg.database.user} \
+          ${optionalString (cfg.database.passwordFile != null) "--dbpassfile ${lib.escapeShellArg cfg.database.passwordFile}"} \
+          --passfile ${lib.escapeShellArg cfg.passwordFile} \
           --dbtype ${cfg.database.type} \
-          ${cfg.name} \
+          ${lib.escapeShellArg cfg.name} \
           admin
 
         ${pkgs.php}/bin/php ${pkg}/share/mediawiki/maintenance/update.php --conf ${mediawikiConfig} --quick
@@ -637,7 +628,7 @@ in
       ++ optional (cfg.webserver == "apache" && cfg.database.createLocally && cfg.database.type == "postgres") "postgresql.service";
 
     users.users.${user} = {
-      group = group;
+      inherit group;
       isSystemUser = true;
     };
     users.groups.${group} = {};
diff --git a/nixpkgs/nixos/modules/services/web-apps/meme-bingo-web.nix b/nixpkgs/nixos/modules/services/web-apps/meme-bingo-web.nix
index 652dc8840252..fe68bbecca57 100644
--- a/nixpkgs/nixos/modules/services/web-apps/meme-bingo-web.nix
+++ b/nixpkgs/nixos/modules/services/web-apps/meme-bingo-web.nix
@@ -1,7 +1,7 @@
 { config, lib, pkgs, ... }:
 
 let
-  inherit (lib) mkEnableOption mkIf mkOption mdDoc types literalExpression;
+  inherit (lib) mkEnableOption mkPackageOption mkIf mkOption mdDoc types literalExpression;
 
   cfg = config.services.meme-bingo-web;
 in {
@@ -13,12 +13,7 @@ in {
         Note: The application's author suppose to run meme-bingo-web behind a reverse proxy for SSL and HTTP/3
       '');
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.meme-bingo-web;
-        defaultText = literalExpression "pkgs.meme-bingo-web";
-        description = mdDoc "meme-bingo-web package to use.";
-      };
+      package = mkPackageOption pkgs "meme-bingo-web" { };
 
       baseUrl = mkOption {
         description = mdDoc ''
diff --git a/nixpkgs/nixos/modules/services/web-apps/miniflux.nix b/nixpkgs/nixos/modules/services/web-apps/miniflux.nix
index 5c8c93c13c43..a500008fc792 100644
--- a/nixpkgs/nixos/modules/services/web-apps/miniflux.nix
+++ b/nixpkgs/nixos/modules/services/web-apps/miniflux.nix
@@ -18,12 +18,7 @@ in
     services.miniflux = {
       enable = mkEnableOption (lib.mdDoc "miniflux and creates a local postgres database for it");
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.miniflux;
-        defaultText = literalExpression "pkgs.miniflux";
-        description = lib.mdDoc "Miniflux package to use.";
-      };
+      package = mkPackageOption pkgs "miniflux" { };
 
       config = mkOption {
         type = types.attrsOf types.str;
diff --git a/nixpkgs/nixos/modules/services/web-apps/mobilizon.nix b/nixpkgs/nixos/modules/services/web-apps/mobilizon.nix
index bb4319b51a2f..0a530bff9232 100644
--- a/nixpkgs/nixos/modules/services/web-apps/mobilizon.nix
+++ b/nixpkgs/nixos/modules/services/web-apps/mobilizon.nix
@@ -71,7 +71,7 @@ in
         '';
       };
 
-      package = mkPackageOptionMD pkgs "mobilizon" { };
+      package = mkPackageOption pkgs "mobilizon" { };
 
       settings = mkOption {
         type =
diff --git a/nixpkgs/nixos/modules/services/web-apps/moodle.nix b/nixpkgs/nixos/modules/services/web-apps/moodle.nix
index 04ae6bd7f175..ce6a80054725 100644
--- a/nixpkgs/nixos/modules/services/web-apps/moodle.nix
+++ b/nixpkgs/nixos/modules/services/web-apps/moodle.nix
@@ -1,7 +1,7 @@
 { config, lib, pkgs, ... }:
 
 let
-  inherit (lib) mkDefault mkEnableOption mkForce mkIf mkMerge mkOption types;
+  inherit (lib) mkDefault mkEnableOption mkPackageOption mkForce mkIf mkMerge mkOption types;
   inherit (lib) concatStringsSep literalExpression mapAttrsToList optional optionalString;
 
   cfg = config.services.moodle;
@@ -66,12 +66,7 @@ in
   options.services.moodle = {
     enable = mkEnableOption (lib.mdDoc "Moodle web application");
 
-    package = mkOption {
-      type = types.package;
-      default = pkgs.moodle;
-      defaultText = literalExpression "pkgs.moodle";
-      description = lib.mdDoc "The Moodle package to use.";
-    };
+    package = mkPackageOption pkgs "moodle" { };
 
     initialPassword = mkOption {
       type = types.str;
diff --git a/nixpkgs/nixos/modules/services/web-apps/nextcloud.nix b/nixpkgs/nixos/modules/services/web-apps/nextcloud.nix
index f1ac3770d403..6c50ea3c81ef 100644
--- a/nixpkgs/nixos/modules/services/web-apps/nextcloud.nix
+++ b/nixpkgs/nixos/modules/services/web-apps/nextcloud.nix
@@ -125,12 +125,7 @@ in {
       '';
       example = literalExpression ''
         {
-          maps = pkgs.fetchNextcloudApp {
-            name = "maps";
-            sha256 = "007y80idqg6b6zk6kjxg4vgw0z8fsxs9lajnv49vv1zjy6jx2i1i";
-            url = "https://github.com/nextcloud/maps/releases/download/v0.1.9/maps-0.1.9.tar.gz";
-            version = "0.1.9";
-          };
+          inherit (pkgs.nextcloud25Packages.apps) mail calendar contact;
           phonetrack = pkgs.fetchNextcloudApp {
             name = "phonetrack";
             sha256 = "0qf366vbahyl27p9mshfma1as4nvql6w75zy2zk5xwwbp343vsbc";
@@ -195,13 +190,8 @@ in {
       description = lib.mdDoc "Which package to use for the Nextcloud instance.";
       relatedPackages = [ "nextcloud26" "nextcloud27" ];
     };
-    phpPackage = mkOption {
-      type = types.package;
-      relatedPackages = [ "php81" "php82" ];
-      defaultText = "pkgs.php";
-      description = lib.mdDoc ''
-        PHP package to use for Nextcloud.
-      '';
+    phpPackage = mkPackageOption pkgs "php" {
+      example = "php82";
     };
 
     maxUploadSize = mkOption {
diff --git a/nixpkgs/nixos/modules/services/web-apps/node-red.nix b/nixpkgs/nixos/modules/services/web-apps/node-red.nix
index f4d4ad9681a6..d775042fed16 100644
--- a/nixpkgs/nixos/modules/services/web-apps/node-red.nix
+++ b/nixpkgs/nixos/modules/services/web-apps/node-red.nix
@@ -19,12 +19,7 @@ in
   options.services.node-red = {
     enable = mkEnableOption (lib.mdDoc "the Node-RED service");
 
-    package = mkOption {
-      default = pkgs.nodePackages.node-red;
-      defaultText = literalExpression "pkgs.nodePackages.node-red";
-      type = types.package;
-      description = lib.mdDoc "Node-RED package to use.";
-    };
+    package = mkPackageOption pkgs "node-red" { };
 
     openFirewall = mkOption {
       type = types.bool;
diff --git a/nixpkgs/nixos/modules/services/web-apps/onlyoffice.nix b/nixpkgs/nixos/modules/services/web-apps/onlyoffice.nix
index f958566b91f0..343ca80c9fc2 100644
--- a/nixpkgs/nixos/modules/services/web-apps/onlyoffice.nix
+++ b/nixpkgs/nixos/modules/services/web-apps/onlyoffice.nix
@@ -26,12 +26,7 @@ in
       '';
     };
 
-    package = mkOption {
-      type = types.package;
-      default = pkgs.onlyoffice-documentserver;
-      defaultText = lib.literalExpression "pkgs.onlyoffice-documentserver";
-      description = lib.mdDoc "Which package to use for the OnlyOffice instance.";
-    };
+    package = mkPackageOption pkgs "onlyoffice-documentserver" { };
 
     port = mkOption {
       type = types.port;
diff --git a/nixpkgs/nixos/modules/services/web-apps/openvscode-server.nix b/nixpkgs/nixos/modules/services/web-apps/openvscode-server.nix
index 3daf238c57e1..76a19dccae16 100644
--- a/nixpkgs/nixos/modules/services/web-apps/openvscode-server.nix
+++ b/nixpkgs/nixos/modules/services/web-apps/openvscode-server.nix
@@ -10,7 +10,7 @@ in
     services.openvscode-server = {
       enable = lib.mkEnableOption (lib.mdDoc "openvscode-server");
 
-      package = lib.mkPackageOptionMD pkgs "openvscode-server" { };
+      package = lib.mkPackageOption pkgs "openvscode-server" { };
 
       extraPackages = lib.mkOption {
         default = [ ];
diff --git a/nixpkgs/nixos/modules/services/web-apps/openwebrx.nix b/nixpkgs/nixos/modules/services/web-apps/openwebrx.nix
index 72c5d6c7818c..ddc2d66e723c 100644
--- a/nixpkgs/nixos/modules/services/web-apps/openwebrx.nix
+++ b/nixpkgs/nixos/modules/services/web-apps/openwebrx.nix
@@ -6,12 +6,7 @@ in
   options.services.openwebrx = with lib; {
     enable = mkEnableOption (lib.mdDoc "OpenWebRX Web interface for Software-Defined Radios on http://localhost:8073");
 
-    package = mkOption {
-      type = types.package;
-      default = pkgs.openwebrx;
-      defaultText = literalExpression "pkgs.openwebrx";
-      description = lib.mdDoc "OpenWebRX package to use for the service";
-    };
+    package = mkPackageOption pkgs "openwebrx" { };
   };
 
   config = lib.mkIf cfg.enable {
diff --git a/nixpkgs/nixos/modules/services/web-apps/peertube.nix b/nixpkgs/nixos/modules/services/web-apps/peertube.nix
index a22467611410..39c02c81c423 100644
--- a/nixpkgs/nixos/modules/services/web-apps/peertube.nix
+++ b/nixpkgs/nixos/modules/services/web-apps/peertube.nix
@@ -100,19 +100,19 @@ in {
     listenHttp = lib.mkOption {
       type = lib.types.port;
       default = 9000;
-      description = lib.mdDoc "listen port for HTTP server.";
+      description = lib.mdDoc "The port that the local PeerTube web server will listen on.";
     };
 
     listenWeb = lib.mkOption {
       type = lib.types.port;
       default = 9000;
-      description = lib.mdDoc "listen port for WEB server.";
+      description = lib.mdDoc "The public-facing port that PeerTube will be accessible at (likely 80 or 443 if running behind a reverse proxy). Clients will try to access PeerTube at this port.";
     };
 
     enableWebHttps = lib.mkOption {
       type = lib.types.bool;
       default = false;
-      description = lib.mdDoc "Enable or disable HTTPS protocol.";
+      description = lib.mdDoc "Whether clients will access your PeerTube instance with HTTPS. Does NOT configure the PeerTube webserver itself to listen for incoming HTTPS connections.";
     };
 
     dataDirs = lib.mkOption {
@@ -279,7 +279,7 @@ in {
       type = lib.types.package;
       default = pkgs.peertube;
       defaultText = lib.literalExpression "pkgs.peertube";
-      description = lib.mdDoc "Peertube package to use.";
+      description = lib.mdDoc "PeerTube package to use.";
     };
   };
 
diff --git a/nixpkgs/nixos/modules/services/web-apps/pgpkeyserver-lite.nix b/nixpkgs/nixos/modules/services/web-apps/pgpkeyserver-lite.nix
index dd51bacd75ea..7a5ab579c408 100644
--- a/nixpkgs/nixos/modules/services/web-apps/pgpkeyserver-lite.nix
+++ b/nixpkgs/nixos/modules/services/web-apps/pgpkeyserver-lite.nix
@@ -20,14 +20,7 @@ in
 
       enable = mkEnableOption (lib.mdDoc "pgpkeyserver-lite on a nginx vHost proxying to a gpg keyserver");
 
-      package = mkOption {
-        default = pkgs.pgpkeyserver-lite;
-        defaultText = literalExpression "pkgs.pgpkeyserver-lite";
-        type = types.package;
-        description = lib.mdDoc ''
-          Which webgui derivation to use.
-        '';
-      };
+      package = mkPackageOption pkgs "pgpkeyserver-lite" { };
 
       hostname = mkOption {
         type = types.str;
diff --git a/nixpkgs/nixos/modules/services/web-apps/photoprism.nix b/nixpkgs/nixos/modules/services/web-apps/photoprism.nix
index 423ad5375baa..e25b03484424 100644
--- a/nixpkgs/nixos/modules/services/web-apps/photoprism.nix
+++ b/nixpkgs/nixos/modules/services/web-apps/photoprism.nix
@@ -77,7 +77,7 @@ in
       '';
     };
 
-    package = lib.mkPackageOptionMD pkgs "photoprism" { };
+    package = lib.mkPackageOption pkgs "photoprism" { };
 
     settings = lib.mkOption {
       type = lib.types.attrsOf lib.types.str;
diff --git a/nixpkgs/nixos/modules/services/web-apps/phylactery.nix b/nixpkgs/nixos/modules/services/web-apps/phylactery.nix
index 723b38ee75d9..488373d0e426 100644
--- a/nixpkgs/nixos/modules/services/web-apps/phylactery.nix
+++ b/nixpkgs/nixos/modules/services/web-apps/phylactery.nix
@@ -22,12 +22,7 @@ in {
       description = lib.mdDoc "Path to CBZ library";
     };
 
-    package = mkOption {
-      type = types.package;
-      default = pkgs.phylactery;
-      defaultText = literalExpression "pkgs.phylactery";
-      description = lib.mdDoc "The Phylactery package to use";
-    };
+    package = mkPackageOption pkgs "phylactery" { };
   };
 
   config = mkIf cfg.enable {
diff --git a/nixpkgs/nixos/modules/services/web-apps/pict-rs.nix b/nixpkgs/nixos/modules/services/web-apps/pict-rs.nix
index e1b8c8333553..983342c37732 100644
--- a/nixpkgs/nixos/modules/services/web-apps/pict-rs.nix
+++ b/nixpkgs/nixos/modules/services/web-apps/pict-rs.nix
@@ -14,13 +14,7 @@ in
   options.services.pict-rs = {
     enable = lib.mkEnableOption (lib.mdDoc "pict-rs server");
 
-    package = mkOption {
-      type = types.package;
-      example = lib.literalExpression "pkgs.pict-rs";
-      description = lib.mdDoc ''
-        pict-rs package to use.
-      '';
-    };
+    package = lib.mkPackageOption pkgs "pict-rs" { };
 
     dataDir = mkOption {
       type = types.path;
diff --git a/nixpkgs/nixos/modules/services/web-apps/pixelfed.nix b/nixpkgs/nixos/modules/services/web-apps/pixelfed.nix
index b0a25dcce9ef..2add98264447 100644
--- a/nixpkgs/nixos/modules/services/web-apps/pixelfed.nix
+++ b/nixpkgs/nixos/modules/services/web-apps/pixelfed.nix
@@ -39,8 +39,8 @@ in {
   options.services = {
     pixelfed = {
       enable = mkEnableOption (lib.mdDoc "a Pixelfed instance");
-      package = mkPackageOptionMD pkgs "pixelfed" { };
-      phpPackage = mkPackageOptionMD pkgs "php81" { };
+      package = mkPackageOption pkgs "pixelfed" { };
+      phpPackage = mkPackageOption pkgs "php81" { };
 
       user = mkOption {
         type = types.str;
diff --git a/nixpkgs/nixos/modules/services/web-apps/plantuml-server.nix b/nixpkgs/nixos/modules/services/web-apps/plantuml-server.nix
index 1fa69814c6c9..b7bdf997d955 100644
--- a/nixpkgs/nixos/modules/services/web-apps/plantuml-server.nix
+++ b/nixpkgs/nixos/modules/services/web-apps/plantuml-server.nix
@@ -7,7 +7,7 @@ let
     mkEnableOption
     mkIf
     mkOption
-    mkPackageOptionMD
+    mkPackageOption
     mkRemovedOptionModule
     types
     ;
@@ -25,12 +25,12 @@ in
     services.plantuml-server = {
       enable = mkEnableOption (mdDoc "PlantUML server");
 
-      package = mkPackageOptionMD pkgs "plantuml-server" { };
+      package = mkPackageOption pkgs "plantuml-server" { };
 
       packages = {
-        jdk = mkPackageOptionMD pkgs "jdk" { };
-        jetty = mkPackageOptionMD pkgs "jetty" {
-          default = "jetty_11";
+        jdk = mkPackageOption pkgs "jdk" { };
+        jetty = mkPackageOption pkgs "jetty" {
+          default = [ "jetty_11" ];
           extraDescription = ''
             At the time of writing (v1.2023.12), PlantUML Server does not support
             Jetty versions higher than 12.x.
@@ -78,7 +78,7 @@ in
         description = mdDoc "Limits image width and height.";
       };
 
-      graphvizPackage = mkPackageOptionMD pkgs "graphviz" { };
+      graphvizPackage = mkPackageOption pkgs "graphviz" { };
 
       plantumlStats = mkOption {
         type = types.bool;
diff --git a/nixpkgs/nixos/modules/services/web-apps/plausible.nix b/nixpkgs/nixos/modules/services/web-apps/plausible.nix
index 300a0f892ef7..a6bb81e0b73f 100644
--- a/nixpkgs/nixos/modules/services/web-apps/plausible.nix
+++ b/nixpkgs/nixos/modules/services/web-apps/plausible.nix
@@ -9,7 +9,7 @@ in {
   options.services.plausible = {
     enable = mkEnableOption (lib.mdDoc "plausible");
 
-    package = mkPackageOptionMD pkgs "plausible" { };
+    package = mkPackageOption pkgs "plausible" { };
 
     adminUser = {
       name = mkOption {
diff --git a/nixpkgs/nixos/modules/services/web-apps/sftpgo.nix b/nixpkgs/nixos/modules/services/web-apps/sftpgo.nix
index 846478ecbd6d..1b5111e5a81c 100644
--- a/nixpkgs/nixos/modules/services/web-apps/sftpgo.nix
+++ b/nixpkgs/nixos/modules/services/web-apps/sftpgo.nix
@@ -23,14 +23,7 @@ in
       description = mdDoc "sftpgo";
     };
 
-    package = mkOption {
-      type = types.package;
-      default = pkgs.sftpgo;
-      defaultText = literalExpression "pkgs.sftpgo";
-      description = mdDoc ''
-        Which SFTPGo package to use.
-      '';
-    };
+    package = mkPackageOption pkgs "sftpgo" { };
 
     extraArgs = mkOption {
       type = with types; listOf str;
diff --git a/nixpkgs/nixos/modules/services/web-apps/shiori.nix b/nixpkgs/nixos/modules/services/web-apps/shiori.nix
index 71b5ad4d4c06..f9026e04d155 100644
--- a/nixpkgs/nixos/modules/services/web-apps/shiori.nix
+++ b/nixpkgs/nixos/modules/services/web-apps/shiori.nix
@@ -8,12 +8,7 @@ in {
     services.shiori = {
       enable = mkEnableOption (lib.mdDoc "Shiori simple bookmarks manager");
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.shiori;
-        defaultText = literalExpression "pkgs.shiori";
-        description = lib.mdDoc "The Shiori package to use.";
-      };
+      package = mkPackageOption pkgs "shiori" { };
 
       address = mkOption {
         type = types.str;
diff --git a/nixpkgs/nixos/modules/services/web-apps/slskd.nix b/nixpkgs/nixos/modules/services/web-apps/slskd.nix
index 33353a59440c..580f66ec3ac9 100644
--- a/nixpkgs/nixos/modules/services/web-apps/slskd.nix
+++ b/nixpkgs/nixos/modules/services/web-apps/slskd.nix
@@ -8,7 +8,7 @@ in {
 
     rotateLogs = mkEnableOption "enable an unit and timer that will rotate logs in /var/slskd/logs";
 
-    package = mkPackageOptionMD pkgs "slskd" { };
+    package = mkPackageOption pkgs "slskd" { };
 
     nginx = mkOption {
       description = lib.mdDoc "options for nginx";
diff --git a/nixpkgs/nixos/modules/services/web-apps/vikunja.nix b/nixpkgs/nixos/modules/services/web-apps/vikunja.nix
index 6b1d4da532bf..b893f2c1f33c 100644
--- a/nixpkgs/nixos/modules/services/web-apps/vikunja.nix
+++ b/nixpkgs/nixos/modules/services/web-apps/vikunja.nix
@@ -11,18 +11,8 @@ let
 in {
   options.services.vikunja = with lib; {
     enable = mkEnableOption (lib.mdDoc "vikunja service");
-    package-api = mkOption {
-      default = pkgs.vikunja-api;
-      type = types.package;
-      defaultText = literalExpression "pkgs.vikunja-api";
-      description = lib.mdDoc "vikunja-api derivation to use.";
-    };
-    package-frontend = mkOption {
-      default = pkgs.vikunja-frontend;
-      type = types.package;
-      defaultText = literalExpression "pkgs.vikunja-frontend";
-      description = lib.mdDoc "vikunja-frontend derivation to use.";
-    };
+    package-api = mkPackageOption pkgs "vikunja-api" { };
+    package-frontend = mkPackageOption pkgs "vikunja-frontend" { };
     environmentFiles = mkOption {
       type = types.listOf types.path;
       default = [ ];
diff --git a/nixpkgs/nixos/modules/services/web-apps/whitebophir.nix b/nixpkgs/nixos/modules/services/web-apps/whitebophir.nix
index b673a7c1179e..dabcf38b2dbd 100644
--- a/nixpkgs/nixos/modules/services/web-apps/whitebophir.nix
+++ b/nixpkgs/nixos/modules/services/web-apps/whitebophir.nix
@@ -9,12 +9,7 @@ in {
     services.whitebophir = {
       enable = mkEnableOption (lib.mdDoc "whitebophir, an online collaborative whiteboard server (persistent state will be maintained under {file}`/var/lib/whitebophir`)");
 
-      package = mkOption {
-        default = pkgs.whitebophir;
-        defaultText = literalExpression "pkgs.whitebophir";
-        type = types.package;
-        description = lib.mdDoc "Whitebophir package to use.";
-      };
+      package = mkPackageOption pkgs "whitebophir" { };
 
       listenAddress = mkOption {
         type = types.str;
diff --git a/nixpkgs/nixos/modules/services/web-apps/wordpress.nix b/nixpkgs/nixos/modules/services/web-apps/wordpress.nix
index 5d2e775d4521..03d5634854a3 100644
--- a/nixpkgs/nixos/modules/services/web-apps/wordpress.nix
+++ b/nixpkgs/nixos/modules/services/web-apps/wordpress.nix
@@ -104,12 +104,7 @@ let
   siteOpts = { lib, name, config, ... }:
     {
       options = {
-        package = mkOption {
-          type = types.package;
-          default = pkgs.wordpress;
-          defaultText = literalExpression "pkgs.wordpress";
-          description = lib.mdDoc "Which WordPress package to use.";
-        };
+        package = mkPackageOption pkgs "wordpress" { };
 
         uploadsDir = mkOption {
           type = types.path;
diff --git a/nixpkgs/nixos/modules/services/web-apps/youtrack.nix b/nixpkgs/nixos/modules/services/web-apps/youtrack.nix
index 09a2b9e965c0..79e1d12e0abb 100644
--- a/nixpkgs/nixos/modules/services/web-apps/youtrack.nix
+++ b/nixpkgs/nixos/modules/services/web-apps/youtrack.nix
@@ -54,14 +54,7 @@ in
       type = types.attrsOf types.str;
     };
 
-    package = mkOption {
-      description = lib.mdDoc ''
-        Package to use.
-      '';
-      type = types.package;
-      default = pkgs.youtrack;
-      defaultText = literalExpression "pkgs.youtrack";
-    };
+    package = mkPackageOption pkgs "youtrack" { };
 
     port = mkOption {
       description = lib.mdDoc ''
diff --git a/nixpkgs/nixos/modules/services/web-apps/zabbix.nix b/nixpkgs/nixos/modules/services/web-apps/zabbix.nix
index 2cea7e7cea72..4f6d7e4e6c1c 100644
--- a/nixpkgs/nixos/modules/services/web-apps/zabbix.nix
+++ b/nixpkgs/nixos/modules/services/web-apps/zabbix.nix
@@ -2,7 +2,7 @@
 
 let
 
-  inherit (lib) mkDefault mkEnableOption mkForce mkIf mkMerge mkOption types;
+  inherit (lib) mkDefault mkEnableOption mkPackageOption mkForce mkIf mkMerge mkOption types;
   inherit (lib) literalExpression mapAttrs optionalString versionAtLeast;
 
   cfg = config.services.zabbixWeb;
@@ -42,12 +42,7 @@ in
     zabbixWeb = {
       enable = mkEnableOption (lib.mdDoc "the Zabbix web interface");
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.zabbix.web;
-        defaultText = literalExpression "zabbix.web";
-        description = lib.mdDoc "Which Zabbix package to use.";
-      };
+      package = mkPackageOption pkgs [ "zabbix" "web" ] { };
 
       server = {
         port = mkOption {
diff --git a/nixpkgs/nixos/modules/services/web-servers/agate.nix b/nixpkgs/nixos/modules/services/web-servers/agate.nix
index a0c8a8c94ee5..dce425035ff7 100644
--- a/nixpkgs/nixos/modules/services/web-servers/agate.nix
+++ b/nixpkgs/nixos/modules/services/web-servers/agate.nix
@@ -10,12 +10,7 @@ in
     services.agate = {
       enable = mkEnableOption (lib.mdDoc "Agate Server");
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.agate;
-        defaultText = literalExpression "pkgs.agate";
-        description = lib.mdDoc "The package to use";
-      };
+      package = mkPackageOption pkgs "agate" { };
 
       addresses = mkOption {
         type = types.listOf types.str;
diff --git a/nixpkgs/nixos/modules/services/web-servers/apache-httpd/default.nix b/nixpkgs/nixos/modules/services/web-servers/apache-httpd/default.nix
index 588f5ee4d003..016e4885a095 100644
--- a/nixpkgs/nixos/modules/services/web-servers/apache-httpd/default.nix
+++ b/nixpkgs/nixos/modules/services/web-servers/apache-httpd/default.nix
@@ -406,14 +406,7 @@ in
 
       enable = mkEnableOption (lib.mdDoc "the Apache HTTP Server");
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.apacheHttpd;
-        defaultText = literalExpression "pkgs.apacheHttpd";
-        description = lib.mdDoc ''
-          Overridable attribute of the Apache HTTP Server package to use.
-        '';
-      };
+      package = mkPackageOption pkgs "apacheHttpd" { };
 
       configFile = mkOption {
         type = types.path;
@@ -557,14 +550,7 @@ in
         description = lib.mdDoc "Whether to enable the PHP module.";
       };
 
-      phpPackage = mkOption {
-        type = types.package;
-        default = pkgs.php;
-        defaultText = literalExpression "pkgs.php";
-        description = lib.mdDoc ''
-          Overridable attribute of the PHP package to use.
-        '';
-      };
+      phpPackage = mkPackageOption pkgs "php" { };
 
       enablePerl = mkOption {
         type = types.bool;
diff --git a/nixpkgs/nixos/modules/services/web-servers/caddy/default.nix b/nixpkgs/nixos/modules/services/web-servers/caddy/default.nix
index dcacb40e4681..497aa9ba956e 100644
--- a/nixpkgs/nixos/modules/services/web-servers/caddy/default.nix
+++ b/nixpkgs/nixos/modules/services/web-servers/caddy/default.nix
@@ -94,14 +94,7 @@ in
       '';
     };
 
-    package = mkOption {
-      default = pkgs.caddy;
-      defaultText = literalExpression "pkgs.caddy";
-      type = types.package;
-      description = lib.mdDoc ''
-        Caddy package to use.
-      '';
-    };
+    package = mkPackageOption pkgs "caddy" { };
 
     dataDir = mkOption {
       type = types.path;
@@ -378,7 +371,7 @@ in
         LogsDirectory = mkIf (cfg.logDir == "/var/log/caddy") [ "caddy" ];
         Restart = "on-failure";
         RestartPreventExitStatus = 1;
-        RestartSecs = "5s";
+        RestartSec = "5s";
 
         # TODO: attempt to upstream these options
         NoNewPrivileges = true;
diff --git a/nixpkgs/nixos/modules/services/web-servers/lighttpd/default.nix b/nixpkgs/nixos/modules/services/web-servers/lighttpd/default.nix
index eaa113c0d52c..3a33137b27d2 100644
--- a/nixpkgs/nixos/modules/services/web-servers/lighttpd/default.nix
+++ b/nixpkgs/nixos/modules/services/web-servers/lighttpd/default.nix
@@ -135,14 +135,7 @@ in
         '';
       };
 
-      package = mkOption {
-        default = pkgs.lighttpd;
-        defaultText = lib.literalExpression "pkgs.lighttpd";
-        type = types.package;
-        description = lib.mdDoc ''
-          lighttpd package to use.
-        '';
-      };
+      package = mkPackageOption pkgs "lighttpd" { };
 
       port = mkOption {
         default = 80;
diff --git a/nixpkgs/nixos/modules/services/web-servers/minio.nix b/nixpkgs/nixos/modules/services/web-servers/minio.nix
index 0bc7421a0e32..6431db250476 100644
--- a/nixpkgs/nixos/modules/services/web-servers/minio.nix
+++ b/nixpkgs/nixos/modules/services/web-servers/minio.nix
@@ -85,12 +85,7 @@ in
       description = lib.mdDoc "Enable or disable access to web UI.";
     };
 
-    package = mkOption {
-      default = pkgs.minio;
-      defaultText = literalExpression "pkgs.minio";
-      type = types.package;
-      description = lib.mdDoc "Minio package to use.";
-    };
+    package = mkPackageOption pkgs "minio" { };
   };
 
   config = mkIf cfg.enable {
diff --git a/nixpkgs/nixos/modules/services/web-servers/phpfpm/default.nix b/nixpkgs/nixos/modules/services/web-servers/phpfpm/default.nix
index 0bd1d5b29b31..4132a97b9543 100644
--- a/nixpkgs/nixos/modules/services/web-servers/phpfpm/default.nix
+++ b/nixpkgs/nixos/modules/services/web-servers/phpfpm/default.nix
@@ -179,14 +179,7 @@ in {
         '';
       };
 
-      phpPackage = mkOption {
-        type = types.package;
-        default = pkgs.php;
-        defaultText = literalExpression "pkgs.php";
-        description = lib.mdDoc ''
-          The PHP package to use for running the PHP-FPM service.
-        '';
-      };
+      phpPackage = mkPackageOption pkgs "php" { };
 
       phpOptions = mkOption {
         type = types.lines;
diff --git a/nixpkgs/nixos/modules/services/web-servers/tomcat.nix b/nixpkgs/nixos/modules/services/web-servers/tomcat.nix
index 30d6b99fcfda..54ea7b66151f 100644
--- a/nixpkgs/nixos/modules/services/web-servers/tomcat.nix
+++ b/nixpkgs/nixos/modules/services/web-servers/tomcat.nix
@@ -8,7 +8,7 @@ in
 
 {
   meta = {
-    maintainers = with lib.maintainers; [ danbst ];
+    maintainers = with lib.maintainers; [ danbst anthonyroussel ];
   };
 
   ###### interface
@@ -17,7 +17,9 @@ in
     services.tomcat = {
       enable = lib.mkEnableOption (lib.mdDoc "Apache Tomcat");
 
-      package = lib.mkPackageOptionMD pkgs "tomcat9" { };
+      package = lib.mkPackageOption pkgs "tomcat9" {
+        example = "tomcat10";
+      };
 
       purifyOnStart = lib.mkOption {
         type = lib.types.bool;
@@ -151,7 +153,7 @@ in
         description = lib.mdDoc "Whether to enable logging per virtual host.";
       };
 
-      jdk = lib.mkPackageOptionMD pkgs "jdk" { };
+      jdk = lib.mkPackageOption pkgs "jdk" { };
 
       axis2 = {
         enable = lib.mkEnableOption "Apache Axis2 container";
diff --git a/nixpkgs/nixos/modules/services/web-servers/traefik.nix b/nixpkgs/nixos/modules/services/web-servers/traefik.nix
index 42fb95a52200..cc2c680b3342 100644
--- a/nixpkgs/nixos/modules/services/web-servers/traefik.nix
+++ b/nixpkgs/nixos/modules/services/web-servers/traefik.nix
@@ -126,12 +126,7 @@ in {
       '';
     };
 
-    package = mkOption {
-      default = pkgs.traefik;
-      defaultText = literalExpression "pkgs.traefik";
-      type = types.package;
-      description = lib.mdDoc "Traefik package to use.";
-    };
+    package = mkPackageOption pkgs "traefik" { };
 
     environmentFiles = mkOption {
       default = [];
diff --git a/nixpkgs/nixos/modules/services/web-servers/unit/default.nix b/nixpkgs/nixos/modules/services/web-servers/unit/default.nix
index 1515779c9064..a5f1a872ce81 100644
--- a/nixpkgs/nixos/modules/services/web-servers/unit/default.nix
+++ b/nixpkgs/nixos/modules/services/web-servers/unit/default.nix
@@ -11,12 +11,7 @@ in {
   options = {
     services.unit = {
       enable = mkEnableOption (lib.mdDoc "Unit App Server");
-      package = mkOption {
-        type = types.package;
-        default = pkgs.unit;
-        defaultText = literalExpression "pkgs.unit";
-        description = lib.mdDoc "Unit package to use.";
-      };
+      package = mkPackageOption pkgs "unit" { };
       user = mkOption {
         type = types.str;
         default = "unit";
diff --git a/nixpkgs/nixos/modules/services/web-servers/varnish/default.nix b/nixpkgs/nixos/modules/services/web-servers/varnish/default.nix
index d7f19be0cec4..857dd64c01be 100644
--- a/nixpkgs/nixos/modules/services/web-servers/varnish/default.nix
+++ b/nixpkgs/nixos/modules/services/web-servers/varnish/default.nix
@@ -15,14 +15,7 @@ in
 
       enableConfigCheck = mkEnableOption (lib.mdDoc "checking the config during build time") // { default = true; };
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.varnish;
-        defaultText = literalExpression "pkgs.varnish";
-        description = lib.mdDoc ''
-          The package to use
-        '';
-      };
+      package = mkPackageOption pkgs "varnish" { };
 
       http_address = mkOption {
         type = types.str;
diff --git a/nixpkgs/nixos/modules/services/x11/desktop-managers/budgie.nix b/nixpkgs/nixos/modules/services/x11/desktop-managers/budgie.nix
index a4f8bd5051ec..de4b2c0e50f5 100644
--- a/nixpkgs/nixos/modules/services/x11/desktop-managers/budgie.nix
+++ b/nixpkgs/nixos/modules/services/x11/desktop-managers/budgie.nix
@@ -202,6 +202,7 @@ in {
     xdg.portal.extraPortals = with pkgs; [
       xdg-desktop-portal-gtk # provides a XDG Portals implementation.
     ];
+    xdg.portal.configPackages = mkDefault [ pkgs.budgie.budgie-desktop ];
 
     services.geoclue2.enable = mkDefault true; # for BCC's Privacy > Location Services panel.
     services.upower.enable = config.powerManagement.enable; # for Budgie's Status Indicator and BCC's Power panel.
diff --git a/nixpkgs/nixos/modules/services/x11/desktop-managers/cinnamon.nix b/nixpkgs/nixos/modules/services/x11/desktop-managers/cinnamon.nix
index f1e4d9304021..a882bb140d21 100644
--- a/nixpkgs/nixos/modules/services/x11/desktop-managers/cinnamon.nix
+++ b/nixpkgs/nixos/modules/services/x11/desktop-managers/cinnamon.nix
@@ -200,6 +200,9 @@ in
         })
       ];
 
+      # https://salsa.debian.org/cinnamon-team/cinnamon/-/commit/f87c64f8d35ba406eb11ad442989a0716f6620cf#
+      xdg.portal.config.x-cinnamon.default = mkDefault [ "xapp" "gtk" ];
+
       # Override GSettings schemas
       environment.sessionVariables.NIX_GSETTINGS_OVERRIDES_DIR = "${nixos-gsettings-overrides}/share/gsettings-schemas/nixos-gsettings-overrides/glib-2.0/schemas";
 
diff --git a/nixpkgs/nixos/modules/services/x11/desktop-managers/deepin.nix b/nixpkgs/nixos/modules/services/x11/desktop-managers/deepin.nix
index 28d751305892..7fdd50b1ed26 100644
--- a/nixpkgs/nixos/modules/services/x11/desktop-managers/deepin.nix
+++ b/nixpkgs/nixos/modules/services/x11/desktop-managers/deepin.nix
@@ -38,8 +38,8 @@ in
 
   config = mkIf cfg.enable
     {
-      services.xserver.displayManager.sessionPackages = [ pkgs.deepin.startdde ];
-      services.xserver.displayManager.defaultSession = mkDefault "deepin";
+      services.xserver.displayManager.sessionPackages = [ pkgs.deepin.dde-session ];
+      services.xserver.displayManager.defaultSession = mkDefault "dde-x11";
 
       # Update the DBus activation environment after launching the desktop manager.
       services.xserver.displayManager.sessionCommands = ''
@@ -78,6 +78,9 @@ in
         })
       ];
 
+      # https://github.com/NixOS/nixpkgs/pull/247766#issuecomment-1722839259
+      xdg.portal.config.deepin.default = mkDefault [ "gtk" ];
+
       environment.sessionVariables = {
         NIX_GSETTINGS_OVERRIDES_DIR = "${nixos-gsettings-overrides}/share/gsettings-schemas/nixos-gsettings-overrides/glib-2.0/schemas";
         DDE_POLKIT_AGENT_PLUGINS_DIRS = [ "${pkgs.deepin.dpa-ext-gnomekeyring}/lib/polkit-1-dde/plugins" ];
@@ -90,6 +93,9 @@ in
         "/lib/dde-file-manager"
         "/share/backgrounds"
         "/share/wallpapers"
+        "/share/dde-daemon"
+        "/share/dsg"
+        "/share/deepin-themes"
       ];
 
       environment.etc = {
@@ -135,19 +141,25 @@ in
             libsForQt5.kde-gtk-config # deepin-api/gtk-thumbnailer need
             libsForQt5.kglobalaccel
             xsettingsd # lightdm-deepin-greeter
+            dtkcommon
+            dtkcore
+            dtkgui
+            dtkwidget
+            dtkdeclarative
             qt5platform-plugins
             deepin-pw-check
             deepin-turbo
 
             dde-account-faces
             deepin-icon-theme
+            deepin-desktop-theme
             deepin-sound-theme
             deepin-gtk-theme
             deepin-wallpapers
 
             startdde
             dde-dock
-            dde-launcher
+            dde-launchpad
             dde-session-ui
             dde-session-shell
             dde-file-manager
@@ -159,8 +171,12 @@ in
             dpa-ext-gnomekeyring
             deepin-desktop-schemas
             deepin-terminal
-            dde-kwin
             deepin-kwin
+            dde-session
+            dde-widgets
+            dde-appearance
+            dde-application-manager
+            deepin-service-manager
           ];
           optionalPackages = [
             onboard # dde-dock plugin
@@ -184,24 +200,33 @@ in
 
       services.dbus.packages = with pkgs.deepin; [
         dde-dock
-        dde-launcher
+        dde-launchpad
         dde-session-ui
         dde-session-shell
         dde-file-manager
         dde-control-center
         dde-calendar
         dde-clipboard
-        dde-kwin
         deepin-kwin
         deepin-pw-check
+        dde-widgets
+        dde-session
+        dde-appearance
+        dde-application-manager
+        deepin-service-manager
       ];
 
       systemd.packages = with pkgs.deepin; [
-        dde-launcher
+        dde-launchpad
         dde-file-manager
         dde-calendar
         dde-clipboard
         deepin-kwin
+        dde-appearance
+        dde-widgets
+        dde-session
+        dde-application-manager
+        deepin-service-manager
       ];
     };
 }
diff --git a/nixpkgs/nixos/modules/services/x11/desktop-managers/gnome.md b/nixpkgs/nixos/modules/services/x11/desktop-managers/gnome.md
index d9e75bfe6bdd..aa36f66970ec 100644
--- a/nixpkgs/nixos/modules/services/x11/desktop-managers/gnome.md
+++ b/nixpkgs/nixos/modules/services/x11/desktop-managers/gnome.md
@@ -145,7 +145,7 @@ services.xserver.desktopManager.gnome = {
 
     # Favorite apps in gnome-shell
     [org.gnome.shell]
-    favorite-apps=['org.gnome.Photos.desktop', 'org.gnome.Nautilus.desktop']
+    favorite-apps=['org.gnome.Console.desktop', 'org.gnome.Nautilus.desktop']
   '';
 
   extraGSettingsOverridePackages = [
diff --git a/nixpkgs/nixos/modules/services/x11/desktop-managers/gnome.nix b/nixpkgs/nixos/modules/services/x11/desktop-managers/gnome.nix
index 12bdd9333377..20eca7746447 100644
--- a/nixpkgs/nixos/modules/services/x11/desktop-managers/gnome.nix
+++ b/nixpkgs/nixos/modules/services/x11/desktop-managers/gnome.nix
@@ -19,7 +19,7 @@ let
 
   defaultFavoriteAppsOverride = ''
     [org.gnome.shell]
-    favorite-apps=[ 'org.gnome.Epiphany.desktop', 'org.gnome.Geary.desktop', 'org.gnome.Calendar.desktop', 'org.gnome.Music.desktop', 'org.gnome.Photos.desktop', 'org.gnome.Nautilus.desktop' ]
+    favorite-apps=[ 'org.gnome.Epiphany.desktop', 'org.gnome.Geary.desktop', 'org.gnome.Calendar.desktop', 'org.gnome.Music.desktop', 'org.gnome.Nautilus.desktop' ]
   '';
 
   nixos-background-light = pkgs.nixos-artwork.wallpapers.simple-blue;
@@ -353,6 +353,7 @@ in
           buildPortalsInGnome = false;
         })
       ];
+      xdg.portal.configPackages = mkDefault [ pkgs.gnome.gnome-session ];
 
       networking.networkmanager.enable = mkDefault true;
 
@@ -462,15 +463,13 @@ in
         ++ utils.removePackagesByName optionalPackages config.environment.gnome.excludePackages;
     })
 
-    # Adapt from https://gitlab.gnome.org/GNOME/gnome-build-meta/blob/gnome-3-38/elements/core/meta-gnome-core-utilities.bst
+    # Adapt from https://gitlab.gnome.org/GNOME/gnome-build-meta/-/blob/gnome-45/elements/core/meta-gnome-core-utilities.bst
     (mkIf serviceCfg.core-utilities.enable {
       environment.systemPackages =
         with pkgs.gnome;
         utils.removePackagesByName
           ([
             baobab
-            cheese
-            eog
             epiphany
             pkgs.gnome-text-editor
             gnome-calculator
@@ -483,12 +482,13 @@ in
             gnome-logs
             gnome-maps
             gnome-music
-            pkgs.gnome-photos
             gnome-system-monitor
             gnome-weather
+            pkgs.loupe
             nautilus
             pkgs.gnome-connections
             simple-scan
+            pkgs.snapshot
             totem
             yelp
           ] ++ lib.optionals config.services.flatpak.enable [
diff --git a/nixpkgs/nixos/modules/services/x11/desktop-managers/kodi.nix b/nixpkgs/nixos/modules/services/x11/desktop-managers/kodi.nix
index 43904cd00e84..452f571d49e6 100644
--- a/nixpkgs/nixos/modules/services/x11/desktop-managers/kodi.nix
+++ b/nixpkgs/nixos/modules/services/x11/desktop-managers/kodi.nix
@@ -15,14 +15,8 @@ in
         description = lib.mdDoc "Enable the kodi multimedia center.";
       };
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.kodi;
-        defaultText = literalExpression "pkgs.kodi";
-        example = literalExpression "pkgs.kodi.withPackages (p: with p; [ jellyfin pvr-iptvsimple vfs-sftp ])";
-        description = lib.mdDoc ''
-          Package that should be used for Kodi.
-        '';
+      package = mkPackageOption pkgs "kodi" {
+        example = "kodi.withPackages (p: with p; [ jellyfin pvr-iptvsimple vfs-sftp ])";
       };
     };
   };
diff --git a/nixpkgs/nixos/modules/services/x11/desktop-managers/lxqt.nix b/nixpkgs/nixos/modules/services/x11/desktop-managers/lxqt.nix
index b69da41c9fc9..50ad72dc7388 100644
--- a/nixpkgs/nixos/modules/services/x11/desktop-managers/lxqt.nix
+++ b/nixpkgs/nixos/modules/services/x11/desktop-managers/lxqt.nix
@@ -70,6 +70,9 @@ in
     services.xserver.libinput.enable = mkDefault true;
 
     xdg.portal.lxqt.enable = true;
+
+    # https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1050804
+    xdg.portal.config.lxqt.default = mkDefault [ "lxqt" "gtk" ];
   };
 
 }
diff --git a/nixpkgs/nixos/modules/services/x11/desktop-managers/mate.nix b/nixpkgs/nixos/modules/services/x11/desktop-managers/mate.nix
index c93f120bed7f..f535a1d298b9 100644
--- a/nixpkgs/nixos/modules/services/x11/desktop-managers/mate.nix
+++ b/nixpkgs/nixos/modules/services/x11/desktop-managers/mate.nix
@@ -77,6 +77,8 @@ in
 
     security.pam.services.mate-screensaver.unixAuth = true;
 
+    xdg.portal.configPackages = mkDefault [ pkgs.mate.mate-desktop ];
+
     environment.pathsToLink = [ "/share" ];
   };
 
diff --git a/nixpkgs/nixos/modules/services/x11/desktop-managers/pantheon.nix b/nixpkgs/nixos/modules/services/x11/desktop-managers/pantheon.nix
index d82d19b26cda..59bc142eeb7f 100644
--- a/nixpkgs/nixos/modules/services/x11/desktop-managers/pantheon.nix
+++ b/nixpkgs/nixos/modules/services/x11/desktop-managers/pantheon.nix
@@ -229,9 +229,6 @@ in
 
       xdg.portal.enable = true;
       xdg.portal.extraPortals = [
-        # Some Pantheon apps enforce portal usage, we need this for e.g. notifications.
-        # Currently we have buildPortalsInGnome enabled, if you run into issues related
-        # to https://github.com/flatpak/xdg-desktop-portal/issues/656 please report to us.
         pkgs.xdg-desktop-portal-gtk
       ] ++ (with pkgs.pantheon; [
         elementary-files
@@ -239,6 +236,8 @@ in
         xdg-desktop-portal-pantheon
       ]);
 
+      xdg.portal.configPackages = mkDefault [ pkgs.pantheon.elementary-default-settings ];
+
       # Override GSettings schemas
       environment.sessionVariables.NIX_GSETTINGS_OVERRIDES_DIR = "${nixos-gsettings-desktop-schemas}/share/gsettings-schemas/nixos-gsettings-overrides/glib-2.0/schemas";
 
diff --git a/nixpkgs/nixos/modules/services/x11/desktop-managers/phosh.nix b/nixpkgs/nixos/modules/services/x11/desktop-managers/phosh.nix
index e4cd9fd99e40..5392ab73aeb8 100644
--- a/nixpkgs/nixos/modules/services/x11/desktop-managers/phosh.nix
+++ b/nixpkgs/nixos/modules/services/x11/desktop-managers/phosh.nix
@@ -135,15 +135,7 @@ in
         description = lib.mdDoc "Enable the Phone Shell.";
       };
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.phosh;
-        defaultText = literalExpression "pkgs.phosh";
-        example = literalExpression "pkgs.phosh";
-        description = lib.mdDoc ''
-          Package that should be used for Phosh.
-        '';
-      };
+      package = mkPackageOption pkgs "phosh" { };
 
       user = mkOption {
         description = lib.mdDoc "The user to run the Phosh service.";
diff --git a/nixpkgs/nixos/modules/services/x11/desktop-managers/plasma5.nix b/nixpkgs/nixos/modules/services/x11/desktop-managers/plasma5.nix
index 361dbe879a18..9cc7c4381620 100644
--- a/nixpkgs/nixos/modules/services/x11/desktop-managers/plasma5.nix
+++ b/nixpkgs/nixos/modules/services/x11/desktop-managers/plasma5.nix
@@ -31,7 +31,7 @@ let
   inherit (lib)
     getBin optionalAttrs optionalString literalExpression
     mkRemovedOptionModule mkRenamedOptionModule
-    mkDefault mkIf mkMerge mkOption mkPackageOptionMD types;
+    mkDefault mkIf mkMerge mkOption mkPackageOption types;
 
   activationScript = ''
     ${set_XDG_CONFIG_HOME}
@@ -108,7 +108,7 @@ in
         default = true;
       };
 
-      notoPackage = mkPackageOptionMD pkgs "Noto fonts" {
+      notoPackage = mkPackageOption pkgs "Noto fonts" {
         default = [ "noto-fonts" ];
         example = "noto-fonts-lgc-plus";
       };
@@ -372,6 +372,7 @@ in
 
       xdg.portal.enable = true;
       xdg.portal.extraPortals = [ plasma5.xdg-desktop-portal-kde ];
+      xdg.portal.configPackages = mkDefault [ plasma5.xdg-desktop-portal-kde ];
       # xdg-desktop-portal-kde expects PipeWire to be running.
       # This does not, by default, replace PulseAudio.
       services.pipewire.enable = mkDefault true;
diff --git a/nixpkgs/nixos/modules/services/x11/desktop-managers/retroarch.nix b/nixpkgs/nixos/modules/services/x11/desktop-managers/retroarch.nix
index 5552f37612a2..9db637191b54 100644
--- a/nixpkgs/nixos/modules/services/x11/desktop-managers/retroarch.nix
+++ b/nixpkgs/nixos/modules/services/x11/desktop-managers/retroarch.nix
@@ -8,12 +8,8 @@ in {
   options.services.xserver.desktopManager.retroarch = {
     enable = mkEnableOption (lib.mdDoc "RetroArch");
 
-    package = mkOption {
-      type = types.package;
-      default = pkgs.retroarch;
-      defaultText = literalExpression "pkgs.retroarch";
-      example = literalExpression "pkgs.retroarch-full";
-      description = lib.mdDoc "RetroArch package to use.";
+    package = mkPackageOption pkgs "retroarch" {
+      example = "retroarch-full";
     };
 
     extraArgs = mkOption {
diff --git a/nixpkgs/nixos/modules/services/x11/desktop-managers/xfce.nix b/nixpkgs/nixos/modules/services/x11/desktop-managers/xfce.nix
index 191b3690c02f..e28486bcc12d 100644
--- a/nixpkgs/nixos/modules/services/x11/desktop-managers/xfce.nix
+++ b/nixpkgs/nixos/modules/services/x11/desktop-managers/xfce.nix
@@ -178,5 +178,7 @@ in
     ]) excludePackages;
 
     security.pam.services.xfce4-screensaver.unixAuth = cfg.enableScreensaver;
+
+    xdg.portal.configPackages = mkDefault [ pkgs.xfce.xfce4-session ];
   };
 }
diff --git a/nixpkgs/nixos/modules/services/x11/picom.nix b/nixpkgs/nixos/modules/services/x11/picom.nix
index 3df0ea9e60bb..de0a8f4d5bcd 100644
--- a/nixpkgs/nixos/modules/services/x11/picom.nix
+++ b/nixpkgs/nixos/modules/services/x11/picom.nix
@@ -61,7 +61,7 @@ in {
       '';
     };
 
-    package = mkPackageOptionMD pkgs "picom" { };
+    package = mkPackageOption pkgs "picom" { };
 
     fade = mkOption {
       type = types.bool;
diff --git a/nixpkgs/nixos/modules/services/x11/redshift.nix b/nixpkgs/nixos/modules/services/x11/redshift.nix
index 3eb9e28edae9..80605eb11407 100644
--- a/nixpkgs/nixos/modules/services/x11/redshift.nix
+++ b/nixpkgs/nixos/modules/services/x11/redshift.nix
@@ -73,14 +73,7 @@ in {
       };
     };
 
-    package = mkOption {
-      type = types.package;
-      default = pkgs.redshift;
-      defaultText = literalExpression "pkgs.redshift";
-      description = lib.mdDoc ''
-        redshift derivation to use.
-      '';
-    };
+    package = mkPackageOption pkgs "redshift" { };
 
     executable = mkOption {
       type = types.str;
diff --git a/nixpkgs/nixos/modules/services/x11/touchegg.nix b/nixpkgs/nixos/modules/services/x11/touchegg.nix
index f1103c054c57..54918245f156 100644
--- a/nixpkgs/nixos/modules/services/x11/touchegg.nix
+++ b/nixpkgs/nixos/modules/services/x11/touchegg.nix
@@ -13,12 +13,7 @@ in {
   options.services.touchegg = {
     enable = mkEnableOption (lib.mdDoc "touchegg, a multi-touch gesture recognizer");
 
-    package = mkOption {
-      type = types.package;
-      default = pkgs.touchegg;
-      defaultText = literalExpression "pkgs.touchegg";
-      description = lib.mdDoc "touchegg derivation to use.";
-    };
+    package = mkPackageOption pkgs "touchegg" { };
   };
 
   ###### implementation
diff --git a/nixpkgs/nixos/modules/services/x11/unclutter-xfixes.nix b/nixpkgs/nixos/modules/services/x11/unclutter-xfixes.nix
index 4a35176c5833..9255c8124788 100644
--- a/nixpkgs/nixos/modules/services/x11/unclutter-xfixes.nix
+++ b/nixpkgs/nixos/modules/services/x11/unclutter-xfixes.nix
@@ -13,12 +13,7 @@ in {
       default = false;
     };
 
-    package = mkOption {
-      description = lib.mdDoc "unclutter-xfixes derivation to use.";
-      type = types.package;
-      default = pkgs.unclutter-xfixes;
-      defaultText = literalExpression "pkgs.unclutter-xfixes";
-    };
+    package = mkPackageOption pkgs "unclutter-xfixes" { };
 
     timeout = mkOption {
       description = lib.mdDoc "Number of seconds before the cursor is marked inactive.";
diff --git a/nixpkgs/nixos/modules/services/x11/unclutter.nix b/nixpkgs/nixos/modules/services/x11/unclutter.nix
index 039214a575a7..ecf7e2668cec 100644
--- a/nixpkgs/nixos/modules/services/x11/unclutter.nix
+++ b/nixpkgs/nixos/modules/services/x11/unclutter.nix
@@ -13,12 +13,7 @@ in {
       default = false;
     };
 
-    package = mkOption {
-      type = types.package;
-      default = pkgs.unclutter;
-      defaultText = literalExpression "pkgs.unclutter";
-      description = lib.mdDoc "unclutter derivation to use.";
-    };
+    package = mkPackageOption pkgs "unclutter" { };
 
     keystroke = mkOption {
       description = lib.mdDoc "Wait for a keystroke before hiding the cursor";
diff --git a/nixpkgs/nixos/modules/services/x11/urxvtd.nix b/nixpkgs/nixos/modules/services/x11/urxvtd.nix
index fedcb6c7293e..bab9f43b0952 100644
--- a/nixpkgs/nixos/modules/services/x11/urxvtd.nix
+++ b/nixpkgs/nixos/modules/services/x11/urxvtd.nix
@@ -17,14 +17,7 @@ in {
       '';
     };
 
-    package = mkOption {
-      default = pkgs.rxvt-unicode;
-      defaultText = literalExpression "pkgs.rxvt-unicode";
-      description = lib.mdDoc ''
-        Package to install. Usually pkgs.rxvt-unicode.
-      '';
-      type = types.package;
-    };
+    package = mkPackageOption pkgs "rxvt-unicode" { };
   };
 
   config = mkIf cfg.enable {
diff --git a/nixpkgs/nixos/modules/services/x11/window-managers/awesome.nix b/nixpkgs/nixos/modules/services/x11/window-managers/awesome.nix
index c1231d3fbf38..0478f326825f 100644
--- a/nixpkgs/nixos/modules/services/x11/window-managers/awesome.nix
+++ b/nixpkgs/nixos/modules/services/x11/window-managers/awesome.nix
@@ -30,12 +30,7 @@ in
         example = literalExpression "[ pkgs.luaPackages.vicious ]";
       };
 
-      package = mkOption {
-        default = null;
-        type = types.nullOr types.package;
-        description = lib.mdDoc "Package to use for running the Awesome WM.";
-        apply = pkg: if pkg == null then pkgs.awesome else pkg;
-      };
+      package = mkPackageOption pkgs "awesome" { };
 
       noArgb = mkOption {
         default = false;
diff --git a/nixpkgs/nixos/modules/services/x11/window-managers/bspwm.nix b/nixpkgs/nixos/modules/services/x11/window-managers/bspwm.nix
index c403f744cd43..cd8852cdfdee 100644
--- a/nixpkgs/nixos/modules/services/x11/window-managers/bspwm.nix
+++ b/nixpkgs/nixos/modules/services/x11/window-managers/bspwm.nix
@@ -11,14 +11,8 @@ in
     services.xserver.windowManager.bspwm = {
       enable = mkEnableOption (lib.mdDoc "bspwm");
 
-      package = mkOption {
-        type        = types.package;
-        default     = pkgs.bspwm;
-        defaultText = literalExpression "pkgs.bspwm";
-        example     = literalExpression "pkgs.bspwm-unstable";
-        description = lib.mdDoc ''
-          bspwm package to use.
-        '';
+      package = mkPackageOption pkgs "bspwm" {
+        example = "bspwm-unstable";
       };
       configFile = mkOption {
         type        = with types; nullOr path;
@@ -31,14 +25,8 @@ in
       };
 
       sxhkd = {
-        package = mkOption {
-          type        = types.package;
-          default     = pkgs.sxhkd;
-          defaultText = literalExpression "pkgs.sxhkd";
-          example     = literalExpression "pkgs.sxhkd-unstable";
-          description = lib.mdDoc ''
-            sxhkd package to use.
-          '';
+        package = mkPackageOption pkgs "sxhkd" {
+          example = "sxhkd-unstable";
         };
         configFile = mkOption {
           type        = with types; nullOr path;
diff --git a/nixpkgs/nixos/modules/services/x11/window-managers/clfswm.nix b/nixpkgs/nixos/modules/services/x11/window-managers/clfswm.nix
index f2e4c2f91c9d..4d47c50c87ef 100644
--- a/nixpkgs/nixos/modules/services/x11/window-managers/clfswm.nix
+++ b/nixpkgs/nixos/modules/services/x11/window-managers/clfswm.nix
@@ -10,14 +10,7 @@ in
   options = {
     services.xserver.windowManager.clfswm = {
       enable = mkEnableOption (lib.mdDoc "clfswm");
-      package = mkOption {
-        type        = types.package;
-        default     = pkgs.lispPackages.clfswm;
-        defaultText = literalExpression "pkgs.lispPackages.clfswm";
-        description = lib.mdDoc ''
-          clfswm package to use.
-        '';
-      };
+      package = mkPackageOption pkgs [ "lispPackages" "clfswm" ] { };
     };
   };
 
diff --git a/nixpkgs/nixos/modules/services/x11/window-managers/dk.nix b/nixpkgs/nixos/modules/services/x11/window-managers/dk.nix
index 152c7bc8117b..441fc18af4b1 100644
--- a/nixpkgs/nixos/modules/services/x11/window-managers/dk.nix
+++ b/nixpkgs/nixos/modules/services/x11/window-managers/dk.nix
@@ -9,7 +9,7 @@ in
     services.xserver.windowManager.dk = {
       enable = lib.mkEnableOption (lib.mdDoc "dk");
 
-      package = lib.mkPackageOptionMD pkgs "dk" { };
+      package = lib.mkPackageOption pkgs "dk" { };
     };
   };
 
diff --git a/nixpkgs/nixos/modules/services/x11/window-managers/dwm.nix b/nixpkgs/nixos/modules/services/x11/window-managers/dwm.nix
index 82900fd30540..b5c7d37653ed 100644
--- a/nixpkgs/nixos/modules/services/x11/window-managers/dwm.nix
+++ b/nixpkgs/nixos/modules/services/x11/window-managers/dwm.nix
@@ -15,11 +15,8 @@ in
   options = {
     services.xserver.windowManager.dwm = {
       enable = mkEnableOption (lib.mdDoc "dwm");
-      package = mkOption {
-        type        = types.package;
-        default     = pkgs.dwm;
-        defaultText = literalExpression "pkgs.dwm";
-        example     = literalExpression ''
+      package = mkPackageOption pkgs "dwm" {
+        example = ''
           pkgs.dwm.overrideAttrs (oldAttrs: rec {
             patches = [
               (super.fetchpatch {
@@ -29,9 +26,6 @@ in
             ];
           })
         '';
-        description = lib.mdDoc ''
-          dwm package to use.
-        '';
       };
     };
   };
diff --git a/nixpkgs/nixos/modules/services/x11/window-managers/herbstluftwm.nix b/nixpkgs/nixos/modules/services/x11/window-managers/herbstluftwm.nix
index 93705ada116d..16ebc2bfe1d3 100644
--- a/nixpkgs/nixos/modules/services/x11/window-managers/herbstluftwm.nix
+++ b/nixpkgs/nixos/modules/services/x11/window-managers/herbstluftwm.nix
@@ -11,14 +11,7 @@ in
     services.xserver.windowManager.herbstluftwm = {
       enable = mkEnableOption (lib.mdDoc "herbstluftwm");
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.herbstluftwm;
-        defaultText = literalExpression "pkgs.herbstluftwm";
-        description = lib.mdDoc ''
-          Herbstluftwm package to use.
-        '';
-      };
+      package = mkPackageOption pkgs "herbstluftwm" { };
 
       configFile = mkOption {
         default     = null;
diff --git a/nixpkgs/nixos/modules/services/x11/window-managers/i3.nix b/nixpkgs/nixos/modules/services/x11/window-managers/i3.nix
index 5bb73cd0bfb1..e824d91812a7 100644
--- a/nixpkgs/nixos/modules/services/x11/window-managers/i3.nix
+++ b/nixpkgs/nixos/modules/services/x11/window-managers/i3.nix
@@ -4,6 +4,10 @@ with lib;
 
 let
   cfg = config.services.xserver.windowManager.i3;
+  updateSessionEnvironmentScript = ''
+    systemctl --user import-environment PATH DISPLAY XAUTHORITY DESKTOP_SESSION XDG_CONFIG_DIRS XDG_DATA_DIRS XDG_RUNTIME_DIR XDG_SESSION_ID DBUS_SESSION_BUS_ADDRESS || true
+    dbus-update-activation-environment --systemd --all || true
+  '';
 in
 
 {
@@ -19,6 +23,15 @@ in
       '';
     };
 
+    updateSessionEnvironment = mkOption {
+      default = true;
+      type = types.bool;
+      description = lib.mdDoc ''
+        Whether to run dbus-update-activation-environment and systemctl import-environment before session start.
+        Required for xdg portals to function properly.
+      '';
+    };
+
     extraSessionCommands = mkOption {
       default     = "";
       type        = types.lines;
@@ -27,14 +40,7 @@ in
       '';
     };
 
-    package = mkOption {
-      type        = types.package;
-      default     = pkgs.i3;
-      defaultText = literalExpression "pkgs.i3";
-      description = lib.mdDoc ''
-        i3 package to use.
-      '';
-    };
+    package = mkPackageOption pkgs "i3" { };
 
     extraPackages = mkOption {
       type = with types; listOf package;
@@ -58,6 +64,8 @@ in
       start = ''
         ${cfg.extraSessionCommands}
 
+        ${lib.optionalString cfg.updateSessionEnvironment updateSessionEnvironmentScript}
+
         ${cfg.package}/bin/i3 ${optionalString (cfg.configFile != null)
           "-c /etc/i3/config"
         } &
diff --git a/nixpkgs/nixos/modules/services/x11/window-managers/katriawm.nix b/nixpkgs/nixos/modules/services/x11/window-managers/katriawm.nix
index 9a3fd5f3ca44..106631792ff4 100644
--- a/nixpkgs/nixos/modules/services/x11/window-managers/katriawm.nix
+++ b/nixpkgs/nixos/modules/services/x11/window-managers/katriawm.nix
@@ -1,7 +1,7 @@
 { config, lib, pkgs, ... }:
 
 let
-  inherit (lib) mdDoc mkEnableOption mkIf mkPackageOptionMD singleton;
+  inherit (lib) mdDoc mkEnableOption mkIf mkPackageOption singleton;
   cfg = config.services.xserver.windowManager.katriawm;
 in
 {
@@ -9,7 +9,7 @@ in
   options = {
     services.xserver.windowManager.katriawm = {
       enable = mkEnableOption (mdDoc "katriawm");
-      package = mkPackageOptionMD pkgs "katriawm" {};
+      package = mkPackageOption pkgs "katriawm" {};
     };
   };
 
diff --git a/nixpkgs/nixos/modules/services/x11/window-managers/qtile.nix b/nixpkgs/nixos/modules/services/x11/window-managers/qtile.nix
index a362d5cdbeee..1da61f5fa5e7 100644
--- a/nixpkgs/nixos/modules/services/x11/window-managers/qtile.nix
+++ b/nixpkgs/nixos/modules/services/x11/window-managers/qtile.nix
@@ -11,7 +11,7 @@ in
   options.services.xserver.windowManager.qtile = {
     enable = mkEnableOption (lib.mdDoc "qtile");
 
-    package = mkPackageOptionMD pkgs "qtile-unwrapped" { };
+    package = mkPackageOption pkgs "qtile-unwrapped" { };
 
     configFile = mkOption {
       type = with types; nullOr path;
diff --git a/nixpkgs/nixos/modules/services/x11/window-managers/ragnarwm.nix b/nixpkgs/nixos/modules/services/x11/window-managers/ragnarwm.nix
index 0843b872dba5..7242c8b1324c 100644
--- a/nixpkgs/nixos/modules/services/x11/window-managers/ragnarwm.nix
+++ b/nixpkgs/nixos/modules/services/x11/window-managers/ragnarwm.nix
@@ -11,14 +11,7 @@ in
   options = {
     services.xserver.windowManager.ragnarwm = {
       enable = mkEnableOption (lib.mdDoc "ragnarwm");
-      package = mkOption {
-        type = types.package;
-        default = pkgs.ragnarwm;
-        defaultText = literalExpression "pkgs.ragnarwm";
-        description = lib.mdDoc ''
-          The ragnar package to use.
-        '';
-      };
+      package = mkPackageOption pkgs "ragnarwm" { };
     };
   };
 
diff --git a/nixpkgs/nixos/modules/services/x11/xscreensaver.nix b/nixpkgs/nixos/modules/services/x11/xscreensaver.nix
new file mode 100644
index 000000000000..dc269b892ebc
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/x11/xscreensaver.nix
@@ -0,0 +1,40 @@
+{ config, lib, pkgs, ... }:
+
+let
+  cfg = config.services.xscreensaver;
+in
+{
+  options.services.xscreensaver = {
+    enable = lib.mkEnableOption "xscreensaver user service";
+
+    package = lib.mkOption {
+      type = lib.types.package;
+      default = pkgs.xscreensaver;
+      defaultText = lib.literalExpression "pkgs.xscreensaver";
+      description = "Which xscreensaver package to use.";
+    };
+  };
+
+  config = lib.mkIf cfg.enable {
+    # Make xscreensaver-auth setuid root so that it can (try to) prevent the OOM
+    # killer from unlocking the screen.
+    security.wrappers.xscreensaver-auth = {
+      setuid = true;
+      owner = "root";
+      group = "root";
+      source = "${pkgs.xscreensaver}/libexec/xscreensaver/xscreensaver-auth";
+    };
+
+    systemd.user.services.xscreensaver = {
+      enable = true;
+      description = "XScreenSaver";
+      after = [ "graphical-session-pre.target" ];
+      partOf = [ "graphical-session.target" ];
+      wantedBy = [ "graphical-session.target" ];
+      path = [ cfg.package ];
+      serviceConfig.ExecStart = "${cfg.package}/bin/xscreensaver -no-splash";
+    };
+  };
+
+  meta.maintainers = with lib.maintainers; [ vancluever AndersonTorres ];
+}
diff --git a/nixpkgs/nixos/modules/system/boot/systemd.nix b/nixpkgs/nixos/modules/system/boot/systemd.nix
index 68a8c1f37ed5..87333999313e 100644
--- a/nixpkgs/nixos/modules/system/boot/systemd.nix
+++ b/nixpkgs/nixos/modules/system/boot/systemd.nix
@@ -177,189 +177,190 @@ in
 {
   ###### interface
 
-  options = {
+  options.systemd = {
 
-    systemd.package = mkOption {
-      default = pkgs.systemd;
-      defaultText = literalExpression "pkgs.systemd";
-      type = types.package;
-      description = lib.mdDoc "The systemd package.";
-    };
+    package = mkPackageOption pkgs "systemd" {};
 
-    systemd.units = mkOption {
-      description = lib.mdDoc "Definition of systemd units.";
+    units = mkOption {
+      description = "Definition of systemd units; see {manpage}`systemd.unit(5)`.";
       default = {};
       type = systemdUtils.types.units;
     };
 
-    systemd.packages = mkOption {
+    packages = mkOption {
       default = [];
       type = types.listOf types.package;
       example = literalExpression "[ pkgs.systemd-cryptsetup-generator ]";
-      description = lib.mdDoc "Packages providing systemd units and hooks.";
+      description = "Packages providing systemd units and hooks.";
     };
 
-    systemd.targets = mkOption {
+    targets = mkOption {
       default = {};
       type = systemdUtils.types.targets;
-      description = lib.mdDoc "Definition of systemd target units.";
+      description = "Definition of systemd target units; see {manpage}`systemd.target(5)`";
     };
 
-    systemd.services = mkOption {
+    services = mkOption {
       default = {};
       type = systemdUtils.types.services;
-      description = lib.mdDoc "Definition of systemd service units.";
+      description = "Definition of systemd service units; see {manpage}`systemd.service(5)`.";
     };
 
-    systemd.sockets = mkOption {
+    sockets = mkOption {
       default = {};
       type = systemdUtils.types.sockets;
-      description = lib.mdDoc "Definition of systemd socket units.";
+      description = "Definition of systemd socket units; see {manpage}`systemd.socket(5)`.";
     };
 
-    systemd.timers = mkOption {
+    timers = mkOption {
       default = {};
       type = systemdUtils.types.timers;
-      description = lib.mdDoc "Definition of systemd timer units.";
+      description = "Definition of systemd timer units; see {manpage}`systemd.timer(5)`.";
     };
 
-    systemd.paths = mkOption {
+    paths = mkOption {
       default = {};
       type = systemdUtils.types.paths;
-      description = lib.mdDoc "Definition of systemd path units.";
+      description = "Definition of systemd path units; see {manpage}`systemd.path(5)`.";
     };
 
-    systemd.mounts = mkOption {
+    mounts = mkOption {
       default = [];
       type = systemdUtils.types.mounts;
-      description = lib.mdDoc ''
-        Definition of systemd mount units.
-        This is a list instead of an attrSet, because systemd mandates the names to be derived from
-        the 'where' attribute.
+      description = ''
+        Definition of systemd mount units; see {manpage}`systemd.mount(5)`.
+
+        This is a list instead of an attrSet, because systemd mandates
+        the names to be derived from the `where` attribute.
       '';
     };
 
-    systemd.automounts = mkOption {
+    automounts = mkOption {
       default = [];
       type = systemdUtils.types.automounts;
-      description = lib.mdDoc ''
-        Definition of systemd automount units.
-        This is a list instead of an attrSet, because systemd mandates the names to be derived from
-        the 'where' attribute.
+      description = ''
+        Definition of systemd automount units; see {manpage}`systemd.automount(5)`.
+
+        This is a list instead of an attrSet, because systemd mandates
+        the names to be derived from the `where` attribute.
       '';
     };
 
-    systemd.slices = mkOption {
+    slices = mkOption {
       default = {};
       type = systemdUtils.types.slices;
-      description = lib.mdDoc "Definition of slice configurations.";
+      description = "Definition of slice configurations; see {manpage}`systemd.slice(5)`.";
     };
 
-    systemd.generators = mkOption {
+    generators = mkOption {
       type = types.attrsOf types.path;
       default = {};
       example = { systemd-gpt-auto-generator = "/dev/null"; };
-      description = lib.mdDoc ''
-        Definition of systemd generators.
+      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/system-generators/NAME` to `VALUE`.
       '';
     };
 
-    systemd.shutdown = mkOption {
+    shutdown = mkOption {
       type = types.attrsOf types.path;
       default = {};
-      description = lib.mdDoc ''
+      description = ''
         Definition of systemd shutdown executables.
         For each `NAME = VALUE` pair of the attrSet, a link is generated from
         `/etc/systemd/system-shutdown/NAME` to `VALUE`.
       '';
     };
 
-    systemd.defaultUnit = mkOption {
+    defaultUnit = mkOption {
       default = "multi-user.target";
       type = types.str;
-      description = lib.mdDoc "Default unit started when the system boots.";
+      description = ''
+        Default unit started when the system boots; see {manpage}`systemd.special(7)`.
+      '';
     };
 
-    systemd.ctrlAltDelUnit = mkOption {
+    ctrlAltDelUnit = mkOption {
       default = "reboot.target";
       type = types.str;
       example = "poweroff.target";
-      description = lib.mdDoc ''
-        Target that should be started when Ctrl-Alt-Delete is pressed.
+      description = ''
+        Target that should be started when Ctrl-Alt-Delete is pressed;
+        see {manpage}`systemd.special(7)`.
       '';
     };
 
-    systemd.globalEnvironment = mkOption {
+    globalEnvironment = mkOption {
       type = with types; attrsOf (nullOr (oneOf [ str path package ]));
       default = {};
       example = { TZ = "CET"; };
-      description = lib.mdDoc ''
+      description = ''
         Environment variables passed to *all* systemd units.
       '';
     };
 
-    systemd.managerEnvironment = mkOption {
+    managerEnvironment = mkOption {
       type = with types; attrsOf (nullOr (oneOf [ str path package ]));
       default = {};
       example = { SYSTEMD_LOG_LEVEL = "debug"; };
-      description = lib.mdDoc ''
+      description = ''
         Environment variables of PID 1. These variables are
         *not* passed to started units.
       '';
     };
 
-    systemd.enableCgroupAccounting = mkOption {
+    enableCgroupAccounting = mkOption {
       default = true;
       type = types.bool;
-      description = lib.mdDoc ''
-        Whether to enable cgroup accounting.
+      description = ''
+        Whether to enable cgroup accounting; see {manpage}`cgroups(7)`.
       '';
     };
 
-    systemd.enableUnifiedCgroupHierarchy = mkOption {
+    enableUnifiedCgroupHierarchy = mkOption {
       default = true;
       type = types.bool;
-      description = lib.mdDoc ''
-        Whether to enable the unified cgroup hierarchy (cgroupsv2).
+      description = ''
+        Whether to enable the unified cgroup hierarchy (cgroupsv2); see {manpage}`cgroups(7)`.
       '';
     };
 
-    systemd.extraConfig = mkOption {
+    extraConfig = mkOption {
       default = "";
       type = types.lines;
       example = "DefaultLimitCORE=infinity";
-      description = lib.mdDoc ''
-        Extra config options for systemd. See systemd-system.conf(5) man page
+      description = ''
+        Extra config options for systemd. See {manpage}`systemd-system.conf(5)` man page
         for available options.
       '';
     };
 
-    systemd.sleep.extraConfig = mkOption {
+    sleep.extraConfig = mkOption {
       default = "";
       type = types.lines;
       example = "HibernateDelaySec=1h";
-      description = lib.mdDoc ''
+      description = ''
         Extra config options for systemd sleep state logic.
-        See sleep.conf.d(5) man page for available options.
+        See {manpage}`sleep.conf.d(5)` man page for available options.
       '';
     };
 
-    systemd.additionalUpstreamSystemUnits = mkOption {
+    additionalUpstreamSystemUnits = mkOption {
       default = [ ];
       type = types.listOf types.str;
       example = [ "debug-shell.service" "systemd-quotacheck.service" ];
-      description = lib.mdDoc ''
+      description = ''
         Additional units shipped with systemd that shall be enabled.
       '';
     };
 
-    systemd.suppressedSystemUnits = mkOption {
+    suppressedSystemUnits = mkOption {
       default = [ ];
       type = types.listOf types.str;
       example = [ "systemd-backlight@.service" ];
-      description = lib.mdDoc ''
+      description = ''
         A list of units to skip when generating system systemd configuration directory. This has
         priority over upstream units, {option}`systemd.units`, and
         {option}`systemd.additionalUpstreamSystemUnits`. The main purpose of this is to
@@ -368,49 +369,56 @@ in
       '';
     };
 
-    systemd.watchdog.device = mkOption {
+    watchdog.device = mkOption {
       type = types.nullOr types.path;
       default = null;
       example = "/dev/watchdog";
-      description = lib.mdDoc ''
+      description = ''
         The path to a hardware watchdog device which will be managed by systemd.
-        If not specified, systemd will default to /dev/watchdog.
+        If not specified, systemd will default to `/dev/watchdog`.
       '';
     };
 
-    systemd.watchdog.runtimeTime = mkOption {
+    watchdog.runtimeTime = mkOption {
       type = types.nullOr types.str;
       default = null;
       example = "30s";
-      description = lib.mdDoc ''
+      description = ''
         The amount of time which can elapse before a watchdog hardware device
-        will automatically reboot the system. Valid time units include "ms",
-        "s", "min", "h", "d", and "w".
+        will automatically reboot the system.
+
+        Valid time units include "ms", "s", "min", "h", "d", and "w";
+        see {manpage}`systemd.time(7)`.
       '';
     };
 
-    systemd.watchdog.rebootTime = mkOption {
+    watchdog.rebootTime = mkOption {
       type = types.nullOr types.str;
       default = null;
       example = "10m";
-      description = lib.mdDoc ''
+      description = ''
         The amount of time which can elapse after a reboot has been triggered
         before a watchdog hardware device will automatically reboot the system.
-        Valid time units include "ms", "s", "min", "h", "d", and "w". If left
-        `null`, systemd will use its default of `10min`; see also {command}`man
-        5 systemd-system.conf`.
+        If left `null`, systemd will use its default of 10 minutes;
+        see {manpage}`systemd-system.conf(5)`.
+
+        Valid time units include "ms", "s", "min", "h", "d", and "w";
+        see also {manpage}`systemd.time(7)`.
       '';
     };
 
-    systemd.watchdog.kexecTime = mkOption {
+    watchdog.kexecTime = mkOption {
       type = types.nullOr types.str;
       default = null;
       example = "10m";
-      description = lib.mdDoc ''
-        The amount of time which can elapse when kexec is being executed before
+      description = ''
+        The amount of time which can elapse when `kexec` is being executed before
         a watchdog hardware device will automatically reboot the system. This
-        option should only be enabled if reloadTime is also enabled. Valid
-        time units include "ms", "s", "min", "h", "d", and "w".
+        option should only be enabled if `reloadTime` is also enabled;
+        see {manpage}`kexec(8)`.
+
+        Valid time units include "ms", "s", "min", "h", "d", and "w";
+        see also {manpage}`systemd.time(7)`.
       '';
     };
   };
@@ -493,32 +501,32 @@ in
       "systemd/system.conf".text = ''
         [Manager]
         ManagerEnvironment=${lib.concatStringsSep " " (lib.mapAttrsToList (n: v: "${n}=${lib.escapeShellArg v}") cfg.managerEnvironment)}
-        ${optionalString config.systemd.enableCgroupAccounting ''
+        ${optionalString cfg.enableCgroupAccounting ''
           DefaultCPUAccounting=yes
           DefaultIOAccounting=yes
           DefaultBlockIOAccounting=yes
           DefaultIPAccounting=yes
         ''}
         DefaultLimitCORE=infinity
-        ${optionalString (config.systemd.watchdog.device != null) ''
-          WatchdogDevice=${config.systemd.watchdog.device}
+        ${optionalString (cfg.watchdog.device != null) ''
+          WatchdogDevice=${cfg.watchdog.device}
         ''}
-        ${optionalString (config.systemd.watchdog.runtimeTime != null) ''
-          RuntimeWatchdogSec=${config.systemd.watchdog.runtimeTime}
+        ${optionalString (cfg.watchdog.runtimeTime != null) ''
+          RuntimeWatchdogSec=${cfg.watchdog.runtimeTime}
         ''}
-        ${optionalString (config.systemd.watchdog.rebootTime != null) ''
-          RebootWatchdogSec=${config.systemd.watchdog.rebootTime}
+        ${optionalString (cfg.watchdog.rebootTime != null) ''
+          RebootWatchdogSec=${cfg.watchdog.rebootTime}
         ''}
-        ${optionalString (config.systemd.watchdog.kexecTime != null) ''
-          KExecWatchdogSec=${config.systemd.watchdog.kexecTime}
+        ${optionalString (cfg.watchdog.kexecTime != null) ''
+          KExecWatchdogSec=${cfg.watchdog.kexecTime}
         ''}
 
-        ${config.systemd.extraConfig}
+        ${cfg.extraConfig}
       '';
 
       "systemd/sleep.conf".text = ''
         [Sleep]
-        ${config.systemd.sleep.extraConfig}
+        ${cfg.sleep.extraConfig}
       '';
 
       "systemd/system-generators" = { source = hooks "generators" cfg.generators; };
diff --git a/nixpkgs/nixos/modules/system/boot/unl0kr.nix b/nixpkgs/nixos/modules/system/boot/unl0kr.nix
new file mode 100644
index 000000000000..8d9af37382e0
--- /dev/null
+++ b/nixpkgs/nixos/modules/system/boot/unl0kr.nix
@@ -0,0 +1,89 @@
+{ config, lib, pkgs, ... }:
+
+let
+  cfg = config.boot.initrd.unl0kr;
+in
+{
+  options.boot.initrd.unl0kr = {
+    enable = lib.mkEnableOption (lib.mdDoc "unl0kr in initrd") // {
+      description = lib.mdDoc ''
+        Whether to enable the unl0kr on-screen keyboard in initrd to unlock LUKS.
+      '';
+    };
+  };
+
+  config = lib.mkIf cfg.enable {
+    meta.maintainers = with lib.maintainers; [ tomfitzhenry ];
+    assertions = [
+      {
+        assertion = cfg.enable -> config.boot.initrd.systemd.enable;
+        message = "boot.initrd.unl0kr is only supported with boot.initrd.systemd.";
+      }
+    ];
+
+    boot.initrd.systemd = {
+      storePaths = with pkgs; [
+        "${pkgs.gnugrep}/bin/grep"
+        libinput
+        xkeyboard_config
+        "${config.boot.initrd.systemd.package}/lib/systemd/systemd-reply-password"
+        "${pkgs.unl0kr}/bin/unl0kr"
+      ];
+      services = {
+        unl0kr-ask-password = {
+          description = "Forward Password Requests to unl0kr";
+          conflicts = [
+            "emergency.service"
+            "initrd-switch-root.target"
+            "shutdown.target"
+          ];
+          unitConfig.DefaultDependencies = false;
+          after = [
+            "systemd-vconsole-setup.service"
+            "udev.service"
+          ];
+          before = [
+            "shutdown.target"
+          ];
+          script = ''
+            # This script acts as a Password Agent: https://systemd.io/PASSWORD_AGENTS/
+
+            DIR=/run/systemd/ask-password/
+            # If a user has multiple encrypted disks, the requests might come in different times,
+            # so make sure to answer as many requests as we can. Once boot succeeds, other
+            # password agents will be responsible for watching for requests.
+            while [ -d $DIR ] && [ "$(ls -A $DIR/ask.*)" ];
+            do
+              for file in `ls $DIR/ask.*`; do
+                socket="$(cat "$file" | ${pkgs.gnugrep}/bin/grep "Socket=" | cut -d= -f2)"
+                ${pkgs.unl0kr}/bin/unl0kr | ${config.boot.initrd.systemd.package}/lib/systemd/systemd-reply-password 1 "$socket"
+              done
+            done
+          '';
+        };
+      };
+
+      paths = {
+        unl0kr-ask-password = {
+          description = "Forward Password Requests to unl0kr";
+          conflicts = [
+            "emergency.service"
+            "initrd-switch-root.target"
+            "shutdown.target"
+          ];
+          unitConfig.DefaultDependencies = false;
+          before = [
+            "shutdown.target"
+            "paths.target"
+            "cryptsetup.target"
+          ];
+          wantedBy = [ "sysinit.target" ];
+          pathConfig = {
+            DirectoryNotEmpty = "/run/systemd/ask-password";
+            MakeDirectory = true;
+          };
+        };
+      };
+    };
+  };
+}
diff --git a/nixpkgs/nixos/modules/tasks/filesystems/bcachefs.nix b/nixpkgs/nixos/modules/tasks/filesystems/bcachefs.nix
index d144ce62dc27..f28fd5cde9c1 100644
--- a/nixpkgs/nixos/modules/tasks/filesystems/bcachefs.nix
+++ b/nixpkgs/nixos/modules/tasks/filesystems/bcachefs.nix
@@ -20,6 +20,7 @@ let
         printf "waiting for device to appear $path"
         for try in $(seq 10); do
           if [ -e $path ]; then
+              target=$(readlink -f $path)
               success=true
               break
           else
@@ -97,7 +98,7 @@ let
           lib.elem (kernel.structuredExtraConfig.BCACHEFS_FS or null) [
             lib.kernel.module
             lib.kernel.yes
-            lib.kernel.option.yes
+            (lib.kernel.option lib.kernel.yes)
           ]
         )
       );
diff --git a/nixpkgs/nixos/modules/tasks/filesystems/zfs.nix b/nixpkgs/nixos/modules/tasks/filesystems/zfs.nix
index 4b6a5b6c12c1..72bc79f31b68 100644
--- a/nixpkgs/nixos/modules/tasks/filesystems/zfs.nix
+++ b/nixpkgs/nixos/modules/tasks/filesystems/zfs.nix
@@ -16,6 +16,7 @@ let
   cfgTrim = config.services.zfs.trim;
   cfgZED = config.services.zfs.zed;
 
+  selectModulePackage = package: config.boot.kernelPackages.${package.kernelModuleAttribute};
   inInitrd = any (fs: fs == "zfs") config.boot.initrd.supportedFilesystems;
   inSystem = any (fs: fs == "zfs") config.boot.supportedFilesystems;
 
@@ -210,11 +211,17 @@ in
   options = {
     boot.zfs = {
       package = mkOption {
-        readOnly = true;
         type = types.package;
-        default = if config.boot.zfs.enableUnstable then pkgs.zfsUnstable else pkgs.zfs;
-        defaultText = literalExpression "if config.boot.zfs.enableUnstable then pkgs.zfsUnstable else pkgs.zfs";
-        description = lib.mdDoc "Configured ZFS userland tools package.";
+        default = if cfgZfs.enableUnstable then pkgs.zfsUnstable else pkgs.zfs;
+        defaultText = literalExpression "if zfsUnstable is enabled then pkgs.zfsUnstable else pkgs.zfs";
+        description = lib.mdDoc "Configured ZFS userland tools package, use `pkgs.zfsUnstable` if you want to track the latest staging ZFS branch.";
+      };
+
+      modulePackage = mkOption {
+        internal = true; # It is supposed to be selected automatically, but can be overridden by expert users.
+        default = selectModulePackage cfgZfs.package;
+        type = types.package;
+        description = lib.mdDoc "Configured ZFS kernel module package.";
       };
 
       enabled = mkOption {
@@ -534,6 +541,10 @@ in
     (mkIf cfgZfs.enabled {
       assertions = [
         {
+          assertion = cfgZfs.modulePackage.version == cfgZfs.package.version;
+          message = "The kernel module and the userspace tooling versions are not matching, this is an unsupported usecase.";
+        }
+        {
           assertion = cfgZED.enableMail -> cfgZfs.package.enableMail;
           message = ''
             To allow ZED to send emails, ZFS needs to be configured to enable
@@ -571,18 +582,14 @@ in
         # https://github.com/NixOS/nixpkgs/issues/106093
         kernelParams = lib.optionals (!config.boot.zfs.allowHibernation) [ "nohibernate" ];
 
-        extraModulePackages = let
-          kernelPkg = if config.boot.zfs.enableUnstable then
-            config.boot.kernelPackages.zfsUnstable
-           else
-            config.boot.kernelPackages.zfs;
-        in [
-          (kernelPkg.override { inherit (cfgZfs) removeLinuxDRM; })
+        extraModulePackages = [
+          (cfgZfs.modulePackage.override { inherit (cfgZfs) removeLinuxDRM; })
         ];
       };
 
       boot.initrd = mkIf inInitrd {
-        kernelModules = [ "zfs" ] ++ optional (!cfgZfs.enableUnstable) "spl";
+        # spl has been removed in ≥ 2.2.0.
+        kernelModules = [ "zfs" ] ++ lib.optional (lib.versionOlder "2.2.0" version) "spl";
         extraUtilsCommands =
           mkIf (!config.boot.initrd.systemd.enable) ''
             copy_bin_and_libs ${cfgZfs.package}/sbin/zfs
diff --git a/nixpkgs/nixos/modules/tasks/snapraid.nix b/nixpkgs/nixos/modules/tasks/snapraid.nix
index 243d25f88423..9570c6b76123 100644
--- a/nixpkgs/nixos/modules/tasks/snapraid.nix
+++ b/nixpkgs/nixos/modules/tasks/snapraid.nix
@@ -217,9 +217,13 @@ in
               # to remove them if they are stale
               let
                 contentDirs = map dirOf contentFiles;
+                # Multiple "split" parity files can be specified in a single
+                # "parityFile", separated by a comma.
+                # https://www.snapraid.it/manual#7.1
+                splitParityFiles = map (s: splitString "," s) parityFiles;
               in
               unique (
-                attrValues dataDisks ++ parityFiles ++ contentDirs
+                attrValues dataDisks ++ splitParityFiles ++ contentDirs
               );
           } // optionalAttrs touchBeforeSync {
             ExecStartPre = "${pkgs.snapraid}/bin/snapraid touch";
diff --git a/nixpkgs/nixos/modules/virtualisation/docker-rootless.nix b/nixpkgs/nixos/modules/virtualisation/docker-rootless.nix
index f4e4bdc0963a..1cdb98b704ce 100644
--- a/nixpkgs/nixos/modules/virtualisation/docker-rootless.nix
+++ b/nixpkgs/nixos/modules/virtualisation/docker-rootless.nix
@@ -47,14 +47,7 @@ in
       '';
     };
 
-    package = mkOption {
-      default = pkgs.docker;
-      defaultText = literalExpression "pkgs.docker";
-      type = types.package;
-      description = lib.mdDoc ''
-        Docker package to be used in the module.
-      '';
-    };
+    package = mkPackageOption pkgs "docker" { };
   };
 
   ###### implementation
diff --git a/nixpkgs/nixos/modules/virtualisation/docker.nix b/nixpkgs/nixos/modules/virtualisation/docker.nix
index 6fe460316091..b0d61ee06091 100644
--- a/nixpkgs/nixos/modules/virtualisation/docker.nix
+++ b/nixpkgs/nixos/modules/virtualisation/docker.nix
@@ -150,14 +150,7 @@ in
       };
     };
 
-    package = mkOption {
-      default = pkgs.docker;
-      defaultText = literalExpression "pkgs.docker";
-      type = types.package;
-      description = lib.mdDoc ''
-        Docker package to be used in the module.
-      '';
-    };
+    package = mkPackageOption pkgs "docker" { };
 
     extraPackages = mkOption {
       type = types.listOf types.package;
diff --git a/nixpkgs/nixos/modules/virtualisation/ecs-agent.nix b/nixpkgs/nixos/modules/virtualisation/ecs-agent.nix
index dd87df9a2780..76bdccca9872 100644
--- a/nixpkgs/nixos/modules/virtualisation/ecs-agent.nix
+++ b/nixpkgs/nixos/modules/virtualisation/ecs-agent.nix
@@ -8,12 +8,7 @@ in {
   options.services.ecs-agent = {
     enable = mkEnableOption (lib.mdDoc "Amazon ECS agent");
 
-    package = mkOption {
-      type = types.path;
-      description = lib.mdDoc "The ECS agent package to use";
-      default = pkgs.ecs-agent;
-      defaultText = literalExpression "pkgs.ecs-agent";
-    };
+    package = mkPackageOption pkgs "ecs-agent" { };
 
     extra-environment = mkOption {
       type = types.attrsOf types.str;
diff --git a/nixpkgs/nixos/modules/virtualisation/incus.nix b/nixpkgs/nixos/modules/virtualisation/incus.nix
index 3a4f0d7157a0..47a5e462262d 100644
--- a/nixpkgs/nixos/modules/virtualisation/incus.nix
+++ b/nixpkgs/nixos/modules/virtualisation/incus.nix
@@ -17,9 +17,9 @@ in
         {command}`incus` command line tool, among others.
       '');
 
-      package = lib.mkPackageOptionMD pkgs "incus" { };
+      package = lib.mkPackageOption pkgs "incus" { };
 
-      lxcPackage = lib.mkPackageOptionMD pkgs "lxc" { };
+      lxcPackage = lib.mkPackageOption pkgs "lxc" { };
 
       preseed = lib.mkOption {
         type = lib.types.nullOr (
diff --git a/nixpkgs/nixos/modules/virtualisation/libvirtd.nix b/nixpkgs/nixos/modules/virtualisation/libvirtd.nix
index 708c577ec1ed..e195ff937d68 100644
--- a/nixpkgs/nixos/modules/virtualisation/libvirtd.nix
+++ b/nixpkgs/nixos/modules/virtualisation/libvirtd.nix
@@ -64,25 +64,14 @@ let
         '';
       };
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.swtpm;
-        defaultText = literalExpression "pkgs.swtpm";
-        description = lib.mdDoc ''
-          swtpm package to use.
-        '';
-      };
+      package = mkPackageOption pkgs "swtpm" { };
     };
   };
 
   qemuModule = types.submodule {
     options = {
-      package = mkOption {
-        type = types.package;
-        default = pkgs.qemu;
-        defaultText = literalExpression "pkgs.qemu";
-        description = lib.mdDoc ''
-          Qemu package to use with libvirt.
+      package = mkPackageOption pkgs "qemu" {
+        extraDescription = ''
           `pkgs.qemu` can emulate alien architectures (e.g. aarch64 on x86)
           `pkgs.qemu_kvm` saves disk space allowing to emulate only host architectures.
         '';
@@ -183,6 +172,31 @@ let
       };
     };
   };
+
+  nssModule = types.submodule {
+    options = {
+      enable = mkOption {
+        type = types.bool;
+        default = false;
+        description = lib.mdDoc ''
+          This option enables the older libvirt NSS module. This method uses
+          DHCP server records, therefore is dependent on the hostname provided
+          by the guest.
+          Please see https://libvirt.org/nss.html for more information.
+        '';
+      };
+
+      enableGuest = mkOption {
+        type = types.bool;
+        default = false;
+        description = lib.mdDoc ''
+          This option enables the newer libvirt_guest NSS module. This module
+          uses the libvirt guest name instead of the hostname of the guest.
+          Please see https://libvirt.org/nss.html for more information.
+        '';
+      };
+    };
+  };
 in
 {
 
@@ -224,14 +238,7 @@ in
       '';
     };
 
-    package = mkOption {
-      type = types.package;
-      default = pkgs.libvirt;
-      defaultText = literalExpression "pkgs.libvirt";
-      description = lib.mdDoc ''
-        libvirt package to use.
-      '';
-    };
+    package = mkPackageOption pkgs "libvirt" { };
 
     extraConfig = mkOption {
       type = types.lines;
@@ -308,6 +315,14 @@ in
         Hooks related options.
       '';
     };
+
+    nss = mkOption {
+      type = nssModule;
+      default = { };
+      description = lib.mdDoc ''
+        libvirt NSS module options.
+      '';
+    };
   };
 
 
@@ -434,7 +449,7 @@ in
         ] ++ cfg.extraOptions
       );
 
-      path = [ cfg.qemu.package ] # libvirtd requires qemu-img to manage disk images
+      path = [ cfg.qemu.package pkgs.netcat ] # libvirtd requires qemu-img to manage disk images
         ++ optional vswitch.enable vswitch.package
         ++ optional cfg.qemu.swtpm.enable cfg.qemu.swtpm.package;
 
@@ -498,5 +513,11 @@ in
         });
       '';
     };
+
+    system.nssModules = optional (cfg.nss.enable or cfg.nss.enableGuest) cfg.package;
+    system.nssDatabases.hosts = builtins.concatLists [
+      (optional cfg.nss.enable "libvirt")
+      (optional cfg.nss.enableGuest "libvirt_guest")
+    ];
   };
 }
diff --git a/nixpkgs/nixos/modules/virtualisation/lxc-container.nix b/nixpkgs/nixos/modules/virtualisation/lxc-container.nix
index 61d7c4cb73fe..4db4df02fe8c 100644
--- a/nixpkgs/nixos/modules/virtualisation/lxc-container.nix
+++ b/nixpkgs/nixos/modules/virtualisation/lxc-container.nix
@@ -1,26 +1,16 @@
 { lib, config, pkgs, ... }:
 
-let
-  cfg = config.virtualisation.lxc;
-in {
+{
+  meta.maintainers = with lib.maintainers; [ adamcstephens ];
+
   imports = [
     ./lxc-instance-common.nix
+
+    (lib.mkRemovedOptionModule [ "virtualisation" "lxc" "nestedContainer" ] "")
+    (lib.mkRemovedOptionModule [ "virtualisation" "lxc" "privilegedContainer" ] "")
   ];
 
-  options = {
-    virtualisation.lxc = {
-      nestedContainer = lib.mkEnableOption (lib.mdDoc ''
-        Whether this container is configured as a nested container. On LXD containers this is recommended
-        for all containers and is enabled with `security.nesting = true`.
-      '');
-
-      privilegedContainer = lib.mkEnableOption (lib.mdDoc ''
-        Whether this LXC container will be running as a privileged container or not. If set to `true` then
-        additional configuration will be applied to the `systemd` instance running within the container as
-        recommended by [distrobuilder](https://linuxcontainers.org/distrobuilder/introduction/).
-      '');
-    };
-  };
+  options = { };
 
   config = {
     boot.isContainer = true;
@@ -85,34 +75,10 @@ in {
       ${pkgs.coreutils}/bin/ln -fs "$1/init" /sbin/init
     '';
 
-    systemd.additionalUpstreamSystemUnits = lib.mkIf cfg.nestedContainer ["systemd-udev-trigger.service"];
-
-    # Add the overrides from lxd distrobuilder
-    # https://github.com/lxc/distrobuilder/blob/05978d0d5a72718154f1525c7d043e090ba7c3e0/distrobuilder/main.go#L630
-    systemd.packages = [
-      (pkgs.writeTextFile {
-        name = "systemd-lxc-service-overrides";
-        destination = "/etc/systemd/system/service.d/zzz-lxc-service.conf";
-        text = ''
-          [Service]
-          ProcSubset=all
-          ProtectProc=default
-          ProtectControlGroups=no
-          ProtectKernelTunables=no
-          NoNewPrivileges=no
-          LoadCredential=
-        '' + lib.optionalString cfg.privilegedContainer ''
-          # Additional settings for privileged containers
-          ProtectHome=no
-          ProtectSystem=no
-          PrivateDevices=no
-          PrivateTmp=no
-          ProtectKernelLogs=no
-          ProtectKernelModules=no
-          ReadWritePaths=
-        '';
-      })
-    ];
+    # networkd depends on this, but systemd module disables this for containers
+    systemd.additionalUpstreamSystemUnits = ["systemd-udev-trigger.service"];
+
+    systemd.packages = [ pkgs.distrobuilder.generator ];
 
     system.activationScripts.installInitScript = lib.mkForce ''
       ln -fs $systemConfig/init /sbin/init
diff --git a/nixpkgs/nixos/modules/virtualisation/multipass.nix b/nixpkgs/nixos/modules/virtualisation/multipass.nix
index b331b3be7ea5..5aae48e21386 100644
--- a/nixpkgs/nixos/modules/virtualisation/multipass.nix
+++ b/nixpkgs/nixos/modules/virtualisation/multipass.nix
@@ -22,7 +22,7 @@ in
         '';
       };
 
-      package = lib.mkPackageOptionMD pkgs "multipass" { };
+      package = lib.mkPackageOption pkgs "multipass" { };
     };
   };
 
diff --git a/nixpkgs/nixos/modules/virtualisation/nixos-containers.nix b/nixpkgs/nixos/modules/virtualisation/nixos-containers.nix
index 6fdb177b968b..d4fa707b2dd5 100644
--- a/nixpkgs/nixos/modules/virtualisation/nixos-containers.nix
+++ b/nixpkgs/nixos/modules/virtualisation/nixos-containers.nix
@@ -771,141 +771,147 @@ in
   };
 
 
-  config = mkIf (config.boot.enableContainers) (let
+  config = mkMerge [
+    {
+      warnings = optional (!config.boot.enableContainers && config.containers != {})
+        "containers.<name> is used, but boot.enableContainers is false. To use containers.<name>, set boot.enableContainers to true.";
+    }
 
-    unit = {
-      description = "Container '%i'";
+    (mkIf (config.boot.enableContainers) (let
+      unit = {
+        description = "Container '%i'";
 
-      unitConfig.RequiresMountsFor = "${stateDirectory}/%i";
+        unitConfig.RequiresMountsFor = "${stateDirectory}/%i";
 
-      path = [ pkgs.iproute2 ];
+        path = [ pkgs.iproute2 ];
 
-      environment = {
-        root = "${stateDirectory}/%i";
-        INSTANCE = "%i";
-      };
+        environment = {
+          root = "${stateDirectory}/%i";
+          INSTANCE = "%i";
+        };
 
-      preStart = preStartScript dummyConfig;
+        preStart = preStartScript dummyConfig;
 
-      script = startScript dummyConfig;
+        script = startScript dummyConfig;
 
-      postStart = postStartScript dummyConfig;
+        postStart = postStartScript dummyConfig;
 
-      restartIfChanged = false;
+        restartIfChanged = false;
 
-      serviceConfig = serviceDirectives dummyConfig;
-    };
-  in {
-    warnings =
-      (optional (config.virtualisation.containers.enable && versionOlder config.system.stateVersion "22.05") ''
-        Enabling both boot.enableContainers & virtualisation.containers on system.stateVersion < 22.05 is unsupported.
-      '');
-
-    systemd.targets.multi-user.wants = [ "machines.target" ];
-
-    systemd.services = listToAttrs (filter (x: x.value != null) (
-      # The generic container template used by imperative containers
-      [{ name = "container@"; value = unit; }]
-      # declarative containers
-      ++ (mapAttrsToList (name: cfg: nameValuePair "container@${name}" (let
-          containerConfig = cfg // (
-          optionalAttrs cfg.enableTun
-            {
-              allowedDevices = cfg.allowedDevices
-                ++ [ { node = "/dev/net/tun"; modifier = "rw"; } ];
-              additionalCapabilities = cfg.additionalCapabilities
-                ++ [ "CAP_NET_ADMIN" ];
-            }
-          );
-        in
-          recursiveUpdate unit {
-            preStart = preStartScript containerConfig;
-            script = startScript containerConfig;
-            postStart = postStartScript containerConfig;
-            serviceConfig = serviceDirectives containerConfig;
-            unitConfig.RequiresMountsFor = lib.optional (!containerConfig.ephemeral) "${stateDirectory}/%i";
-            environment.root = if containerConfig.ephemeral then "/run/nixos-containers/%i" else "${stateDirectory}/%i";
-          } // (
-          optionalAttrs containerConfig.autoStart
-            {
-              wantedBy = [ "machines.target" ];
-              wants = [ "network.target" ];
-              after = [ "network.target" ];
-              restartTriggers = [
-                containerConfig.path
-                config.environment.etc."${configurationDirectoryName}/${name}.conf".source
-              ];
-              restartIfChanged = containerConfig.restartIfChanged;
-            }
-          )
-      )) config.containers)
-    ));
-
-    # Generate a configuration file in /etc/nixos-containers for each
-    # container so that container@.target can get the container
-    # configuration.
-    environment.etc =
-      let mkPortStr = p: p.protocol + ":" + (toString p.hostPort) + ":" + (if p.containerPort == null then toString p.hostPort else toString p.containerPort);
-      in mapAttrs' (name: cfg: nameValuePair "${configurationDirectoryName}/${name}.conf"
-      { text =
-          ''
-            SYSTEM_PATH=${cfg.path}
-            ${optionalString cfg.privateNetwork ''
-              PRIVATE_NETWORK=1
-              ${optionalString (cfg.hostBridge != null) ''
-                HOST_BRIDGE=${cfg.hostBridge}
-              ''}
-              ${optionalString (length cfg.forwardPorts > 0) ''
-                HOST_PORT=${concatStringsSep "," (map mkPortStr cfg.forwardPorts)}
-              ''}
-              ${optionalString (cfg.hostAddress != null) ''
-                HOST_ADDRESS=${cfg.hostAddress}
-              ''}
-              ${optionalString (cfg.hostAddress6 != null) ''
-                HOST_ADDRESS6=${cfg.hostAddress6}
-              ''}
-              ${optionalString (cfg.localAddress != null) ''
-                LOCAL_ADDRESS=${cfg.localAddress}
+        serviceConfig = serviceDirectives dummyConfig;
+      };
+    in {
+      warnings =
+        (optional (config.virtualisation.containers.enable && versionOlder config.system.stateVersion "22.05") ''
+          Enabling both boot.enableContainers & virtualisation.containers on system.stateVersion < 22.05 is unsupported.
+        '');
+
+      systemd.targets.multi-user.wants = [ "machines.target" ];
+
+      systemd.services = listToAttrs (filter (x: x.value != null) (
+        # The generic container template used by imperative containers
+        [{ name = "container@"; value = unit; }]
+        # declarative containers
+        ++ (mapAttrsToList (name: cfg: nameValuePair "container@${name}" (let
+            containerConfig = cfg // (
+            optionalAttrs cfg.enableTun
+              {
+                allowedDevices = cfg.allowedDevices
+                  ++ [ { node = "/dev/net/tun"; modifier = "rw"; } ];
+                additionalCapabilities = cfg.additionalCapabilities
+                  ++ [ "CAP_NET_ADMIN" ];
+              }
+            );
+          in
+            recursiveUpdate unit {
+              preStart = preStartScript containerConfig;
+              script = startScript containerConfig;
+              postStart = postStartScript containerConfig;
+              serviceConfig = serviceDirectives containerConfig;
+              unitConfig.RequiresMountsFor = lib.optional (!containerConfig.ephemeral) "${stateDirectory}/%i";
+              environment.root = if containerConfig.ephemeral then "/run/nixos-containers/%i" else "${stateDirectory}/%i";
+            } // (
+            optionalAttrs containerConfig.autoStart
+              {
+                wantedBy = [ "machines.target" ];
+                wants = [ "network.target" ];
+                after = [ "network.target" ];
+                restartTriggers = [
+                  containerConfig.path
+                  config.environment.etc."${configurationDirectoryName}/${name}.conf".source
+                ];
+                restartIfChanged = containerConfig.restartIfChanged;
+              }
+            )
+        )) config.containers)
+      ));
+
+      # Generate a configuration file in /etc/nixos-containers for each
+      # container so that container@.target can get the container
+      # configuration.
+      environment.etc =
+        let mkPortStr = p: p.protocol + ":" + (toString p.hostPort) + ":" + (if p.containerPort == null then toString p.hostPort else toString p.containerPort);
+        in mapAttrs' (name: cfg: nameValuePair "${configurationDirectoryName}/${name}.conf"
+        { text =
+            ''
+              SYSTEM_PATH=${cfg.path}
+              ${optionalString cfg.privateNetwork ''
+                PRIVATE_NETWORK=1
+                ${optionalString (cfg.hostBridge != null) ''
+                  HOST_BRIDGE=${cfg.hostBridge}
+                ''}
+                ${optionalString (length cfg.forwardPorts > 0) ''
+                  HOST_PORT=${concatStringsSep "," (map mkPortStr cfg.forwardPorts)}
+                ''}
+                ${optionalString (cfg.hostAddress != null) ''
+                  HOST_ADDRESS=${cfg.hostAddress}
+                ''}
+                ${optionalString (cfg.hostAddress6 != null) ''
+                  HOST_ADDRESS6=${cfg.hostAddress6}
+                ''}
+                ${optionalString (cfg.localAddress != null) ''
+                  LOCAL_ADDRESS=${cfg.localAddress}
+                ''}
+                ${optionalString (cfg.localAddress6 != null) ''
+                  LOCAL_ADDRESS6=${cfg.localAddress6}
+                ''}
               ''}
-              ${optionalString (cfg.localAddress6 != null) ''
-                LOCAL_ADDRESS6=${cfg.localAddress6}
+              INTERFACES="${toString cfg.interfaces}"
+              MACVLANS="${toString cfg.macvlans}"
+              ${optionalString cfg.autoStart ''
+                AUTO_START=1
               ''}
-            ''}
-            INTERFACES="${toString cfg.interfaces}"
-            MACVLANS="${toString cfg.macvlans}"
-            ${optionalString cfg.autoStart ''
-              AUTO_START=1
-            ''}
-            EXTRA_NSPAWN_FLAGS="${mkBindFlags cfg.bindMounts +
-              optionalString (cfg.extraFlags != [])
-                (" " + concatStringsSep " " cfg.extraFlags)}"
-          '';
-      }) config.containers;
-
-    # Generate /etc/hosts entries for the containers.
-    networking.extraHosts = concatStrings (mapAttrsToList (name: cfg: optionalString (cfg.localAddress != null)
-      ''
-        ${head (splitString "/" cfg.localAddress)} ${name}.containers
-      '') config.containers);
+              EXTRA_NSPAWN_FLAGS="${mkBindFlags cfg.bindMounts +
+                optionalString (cfg.extraFlags != [])
+                  (" " + concatStringsSep " " cfg.extraFlags)}"
+            '';
+        }) config.containers;
+
+      # Generate /etc/hosts entries for the containers.
+      networking.extraHosts = concatStrings (mapAttrsToList (name: cfg: optionalString (cfg.localAddress != null)
+        ''
+          ${head (splitString "/" cfg.localAddress)} ${name}.containers
+        '') config.containers);
 
-    networking.dhcpcd.denyInterfaces = [ "ve-*" "vb-*" ];
+      networking.dhcpcd.denyInterfaces = [ "ve-*" "vb-*" ];
 
-    services.udev.extraRules = optionalString config.networking.networkmanager.enable ''
-      # Don't manage interfaces created by nixos-container.
-      ENV{INTERFACE}=="v[eb]-*", ENV{NM_UNMANAGED}="1"
-    '';
+      services.udev.extraRules = optionalString config.networking.networkmanager.enable ''
+        # Don't manage interfaces created by nixos-container.
+        ENV{INTERFACE}=="v[eb]-*", ENV{NM_UNMANAGED}="1"
+      '';
 
-    environment.systemPackages = [
-      nixos-container
-    ];
-
-    boot.kernelModules = [
-      "bridge"
-      "macvlan"
-      "tap"
-      "tun"
-    ];
-  });
+      environment.systemPackages = [
+        nixos-container
+      ];
+
+      boot.kernelModules = [
+        "bridge"
+        "macvlan"
+        "tap"
+        "tun"
+      ];
+    }))
+  ];
 
   meta.buildDocsInSandbox = false;
 }
diff --git a/nixpkgs/nixos/modules/virtualisation/openvswitch.nix b/nixpkgs/nixos/modules/virtualisation/openvswitch.nix
index 32646f60f8e0..a968c732f8f7 100644
--- a/nixpkgs/nixos/modules/virtualisation/openvswitch.nix
+++ b/nixpkgs/nixos/modules/virtualisation/openvswitch.nix
@@ -28,14 +28,7 @@ in {
         '';
     };
 
-    package = mkOption {
-      type = types.package;
-      default = pkgs.openvswitch;
-      defaultText = literalExpression "pkgs.openvswitch";
-      description = lib.mdDoc ''
-        Open vSwitch package to use.
-      '';
-    };
+    package = mkPackageOption pkgs "openvswitch" { };
   };
 
   config = mkIf cfg.enable (let
diff --git a/nixpkgs/nixos/modules/virtualisation/qemu-guest-agent.nix b/nixpkgs/nixos/modules/virtualisation/qemu-guest-agent.nix
index 650fb2419160..aeab0ceac3cc 100644
--- a/nixpkgs/nixos/modules/virtualisation/qemu-guest-agent.nix
+++ b/nixpkgs/nixos/modules/virtualisation/qemu-guest-agent.nix
@@ -12,12 +12,7 @@ in {
         default = false;
         description = lib.mdDoc "Whether to enable the qemu guest agent.";
       };
-      package = mkOption {
-        type = types.package;
-        default = pkgs.qemu_kvm.ga;
-        defaultText = literalExpression "pkgs.qemu_kvm.ga";
-        description = lib.mdDoc "The QEMU guest agent package.";
-      };
+      package = mkPackageOption pkgs [ "qemu_kvm" "ga" ] { };
   };
 
   config = mkIf cfg.enable (
diff --git a/nixpkgs/nixos/modules/virtualisation/qemu-vm.nix b/nixpkgs/nixos/modules/virtualisation/qemu-vm.nix
index 6f275baf60dc..d92fd48a6103 100644
--- a/nixpkgs/nixos/modules/virtualisation/qemu-vm.nix
+++ b/nixpkgs/nixos/modules/virtualisation/qemu-vm.nix
@@ -899,7 +899,7 @@ in
     virtualisation.tpm = {
       enable = mkEnableOption "a TPM device in the virtual machine with a driver, using swtpm.";
 
-      package = mkPackageOptionMD cfg.host.pkgs "swtpm" { };
+      package = mkPackageOption cfg.host.pkgs "swtpm" { };
 
       deviceModel = mkOption {
         type = types.str;
diff --git a/nixpkgs/nixos/modules/virtualisation/virtualbox-host.nix b/nixpkgs/nixos/modules/virtualisation/virtualbox-host.nix
index 9741ea090f79..50a8f8189590 100644
--- a/nixpkgs/nixos/modules/virtualisation/virtualbox-host.nix
+++ b/nixpkgs/nixos/modules/virtualisation/virtualbox-host.nix
@@ -40,14 +40,7 @@ in
       '';
     };
 
-    package = mkOption {
-      type = types.package;
-      default = pkgs.virtualbox;
-      defaultText = literalExpression "pkgs.virtualbox";
-      description = lib.mdDoc ''
-        Which VirtualBox package to use.
-      '';
-    };
+    package = mkPackageOption pkgs "virtualbox" { };
 
     addNetworkInterface = mkOption {
       type = types.bool;
diff --git a/nixpkgs/nixos/modules/virtualisation/vmware-host.nix b/nixpkgs/nixos/modules/virtualisation/vmware-host.nix
index 4b2dc28aeac7..1eaa896fe096 100644
--- a/nixpkgs/nixos/modules/virtualisation/vmware-host.nix
+++ b/nixpkgs/nixos/modules/virtualisation/vmware-host.nix
@@ -37,12 +37,7 @@ in
           :::
         '';
       };
-      package = mkOption {
-        type = types.package;
-        default = pkgs.vmware-workstation;
-        defaultText = literalExpression "pkgs.vmware-workstation";
-        description = lib.mdDoc "VMware host virtualisation package to use";
-      };
+      package = mkPackageOption pkgs "vmware-workstation" { };
       extraPackages = mkOption {
         type = with types; listOf package;
         default = with pkgs; [ ];
diff --git a/nixpkgs/nixos/modules/virtualisation/waydroid.nix b/nixpkgs/nixos/modules/virtualisation/waydroid.nix
index 46e5f901015d..b0e85b685083 100644
--- a/nixpkgs/nixos/modules/virtualisation/waydroid.nix
+++ b/nixpkgs/nixos/modules/virtualisation/waydroid.nix
@@ -1,10 +1,8 @@
 { config, lib, pkgs, ... }:
 
-with lib;
-
 let
-
   cfg = config.virtualisation.waydroid;
+  kCfg = config.lib.kernelConfig;
   kernelPackages = config.boot.kernelPackages;
   waydroidGbinderConf = pkgs.writeText "waydroid.conf" ''
     [Protocol]
@@ -22,19 +20,19 @@ in
 {
 
   options.virtualisation.waydroid = {
-    enable = mkEnableOption (lib.mdDoc "Waydroid");
+    enable = lib.mkEnableOption (lib.mdDoc "Waydroid");
   };
 
-  config = mkIf cfg.enable {
-    assertions = singleton {
-      assertion = versionAtLeast (getVersion config.boot.kernelPackages.kernel) "4.18";
+  config = lib.mkIf cfg.enable {
+    assertions = lib.singleton {
+      assertion = lib.versionAtLeast (lib.getVersion config.boot.kernelPackages.kernel) "4.18";
       message = "Waydroid needs user namespace support to work properly";
     };
 
-    system.requiredKernelConfig = with config.lib.kernelConfig; [
-      (isEnabled "ANDROID_BINDER_IPC")
-      (isEnabled "ANDROID_BINDERFS")
-      (isEnabled "ASHMEM") # FIXME Needs memfd support instead on Linux 5.18 and waydroid 1.2.1
+    system.requiredKernelConfig = [
+      (kCfg.isEnabled "ANDROID_BINDER_IPC")
+      (kCfg.isEnabled "ANDROID_BINDERFS")
+      (kCfg.isEnabled "ASHMEM") # FIXME Needs memfd support instead on Linux 5.18 and waydroid 1.2.1
     ];
 
     /* NOTE: we always enable this flag even if CONFIG_PSI_DEFAULT_DISABLED is not on
diff --git a/nixpkgs/nixos/tests/all-tests.nix b/nixpkgs/nixos/tests/all-tests.nix
index 367e3da29336..1ed0f760c9a2 100644
--- a/nixpkgs/nixos/tests/all-tests.nix
+++ b/nixpkgs/nixos/tests/all-tests.nix
@@ -120,6 +120,7 @@ in {
   amazon-ssm-agent = handleTest ./amazon-ssm-agent.nix {};
   amd-sev = runTest ./amd-sev.nix;
   anbox = runTest ./anbox.nix;
+  anki-sync-server = handleTest ./anki-sync-server.nix {};
   anuko-time-tracker = handleTest ./anuko-time-tracker.nix {};
   apcupsd = handleTest ./apcupsd.nix {};
   apfs = runTest ./apfs.nix;
@@ -174,6 +175,7 @@ in {
   cassandra_3_0 = handleTest ./cassandra.nix { testPackage = pkgs.cassandra_3_0; };
   cassandra_3_11 = handleTest ./cassandra.nix { testPackage = pkgs.cassandra_3_11; };
   cassandra_4 = handleTest ./cassandra.nix { testPackage = pkgs.cassandra_4; };
+  centrifugo = runTest ./centrifugo.nix;
   ceph-multi-node = handleTestOn [ "aarch64-linux" "x86_64-linux" ] ./ceph-multi-node.nix {};
   ceph-single-node = handleTestOn [ "aarch64-linux" "x86_64-linux" ] ./ceph-single-node.nix {};
   ceph-single-node-bluestore = handleTestOn [ "aarch64-linux" "x86_64-linux" ] ./ceph-single-node-bluestore.nix {};
@@ -252,6 +254,7 @@ in {
   domination = handleTest ./domination.nix {};
   dovecot = handleTest ./dovecot.nix {};
   drbd = handleTest ./drbd.nix {};
+  dublin-traceroute = handleTest ./dublin-traceroute.nix {};
   earlyoom = handleTestOn ["x86_64-linux"] ./earlyoom.nix {};
   early-mount-options = handleTest ./early-mount-options.nix {};
   ec2-config = (handleTestOn ["x86_64-linux"] ./ec2.nix {}).boot-ec2-config or {};
@@ -320,6 +323,7 @@ in {
   mimir = handleTest ./mimir.nix {};
   garage = handleTest ./garage {};
   gemstash = handleTest ./gemstash.nix {};
+  geoserver = runTest ./geoserver.nix;
   gerrit = handleTest ./gerrit.nix {};
   geth = handleTest ./geth.nix {};
   ghostunnel = handleTest ./ghostunnel.nix {};
@@ -331,6 +335,7 @@ in {
   gitolite-fcgiwrap = handleTest ./gitolite-fcgiwrap.nix {};
   glusterfs = handleTest ./glusterfs.nix {};
   gnome = handleTest ./gnome.nix {};
+  gnome-extensions = handleTest ./gnome-extensions.nix {};
   gnome-flashback = handleTest ./gnome-flashback.nix {};
   gnome-xorg = handleTest ./gnome-xorg.nix {};
   gnupg = handleTest ./gnupg.nix {};
@@ -740,6 +745,7 @@ in {
   sddm = handleTest ./sddm.nix {};
   seafile = handleTest ./seafile.nix {};
   searx = handleTest ./searx.nix {};
+  seatd = handleTest ./seatd.nix {};
   service-runner = handleTest ./service-runner.nix {};
   sftpgo = runTest ./sftpgo.nix;
   sfxr-qt = handleTest ./sfxr-qt.nix {};
@@ -762,6 +768,7 @@ in {
   sogo = handleTest ./sogo.nix {};
   solanum = handleTest ./solanum.nix {};
   sonarr = handleTest ./sonarr.nix {};
+  sonic-server = handleTest ./sonic-server.nix {};
   sourcehut = handleTest ./sourcehut.nix {};
   spacecookie = handleTest ./spacecookie.nix {};
   spark = handleTestOn [ "x86_64-linux" "aarch64-linux" ] ./spark {};
@@ -808,6 +815,7 @@ in {
   systemd-initrd-luks-empty-passphrase = handleTest ./initrd-luks-empty-passphrase.nix { systemdStage1 = true; };
   systemd-initrd-luks-password = handleTest ./systemd-initrd-luks-password.nix {};
   systemd-initrd-luks-tpm2 = handleTest ./systemd-initrd-luks-tpm2.nix {};
+  systemd-initrd-luks-unl0kr = handleTest ./systemd-initrd-luks-unl0kr.nix {};
   systemd-initrd-modprobe = handleTest ./systemd-initrd-modprobe.nix {};
   systemd-initrd-shutdown = handleTest ./systemd-shutdown.nix { systemdStage1 = true; };
   systemd-initrd-simple = handleTest ./systemd-initrd-simple.nix {};
@@ -924,6 +932,7 @@ in {
   xmonad-xdg-autostart = handleTest ./xmonad-xdg-autostart.nix {};
   xpadneo = handleTest ./xpadneo.nix {};
   xrdp = handleTest ./xrdp.nix {};
+  xscreensaver = handleTest ./xscreensaver.nix {};
   xss-lock = handleTest ./xss-lock.nix {};
   xterm = handleTest ./xterm.nix {};
   xxh = handleTest ./xxh.nix {};
diff --git a/nixpkgs/nixos/tests/anki-sync-server.nix b/nixpkgs/nixos/tests/anki-sync-server.nix
new file mode 100644
index 000000000000..7d08cc9cb878
--- /dev/null
+++ b/nixpkgs/nixos/tests/anki-sync-server.nix
@@ -0,0 +1,71 @@
+import ./make-test-python.nix ({ pkgs, ... }:
+  let
+    ankiSyncTest = pkgs.writeScript "anki-sync-test.py" ''
+      #!${pkgs.python3}/bin/python
+
+      import sys
+
+      # get site paths from anki itself
+      from runpy import run_path
+      run_path("${pkgs.anki}/bin/.anki-wrapped")
+      import anki
+
+      col = anki.collection.Collection('test_collection')
+      endpoint = 'http://localhost:27701'
+
+      # Sanity check: verify bad login fails
+      try:
+         col.sync_login('baduser', 'badpass', endpoint)
+         print("bad user login worked?!")
+         sys.exit(1)
+      except anki.errors.SyncError:
+          pass
+
+      # test logging in to users
+      col.sync_login('user', 'password', endpoint)
+      col.sync_login('passfileuser', 'passfilepassword', endpoint)
+
+      # Test actual sync. login apparently doesn't remember the endpoint...
+      login = col.sync_login('user', 'password', endpoint)
+      login.endpoint = endpoint
+      sync = col.sync_collection(login, False)
+      assert sync.required == sync.NO_CHANGES
+      # TODO: create an archive with server content including a test card
+      # and check we got it?
+    '';
+    testPasswordFile = pkgs.writeText "anki-password" "passfilepassword";
+  in
+  {
+  name = "anki-sync-server";
+  meta = with pkgs.lib.maintainers; {
+    maintainers = [ martinetd ];
+  };
+
+  nodes.machine = { pkgs, ...}: {
+    services.anki-sync-server = {
+      enable = true;
+      users = [
+        { username = "user";
+          password = "password";
+        }
+        { username = "passfileuser";
+          passwordFile = testPasswordFile;
+        }
+      ];
+    };
+  };
+
+
+  testScript =
+    ''
+      start_all()
+
+      with subtest("Server starts successfully"):
+          # service won't start without users
+          machine.wait_for_unit("anki-sync-server.service")
+          machine.wait_for_open_port(27701)
+
+      with subtest("Can sync"):
+          machine.succeed("${ankiSyncTest}")
+    '';
+})
diff --git a/nixpkgs/nixos/tests/centrifugo.nix b/nixpkgs/nixos/tests/centrifugo.nix
new file mode 100644
index 000000000000..45c2904f5585
--- /dev/null
+++ b/nixpkgs/nixos/tests/centrifugo.nix
@@ -0,0 +1,80 @@
+let
+  redisPort = 6379;
+  centrifugoPort = 8080;
+  nodes = [
+    "centrifugo1"
+    "centrifugo2"
+    "centrifugo3"
+  ];
+in
+{ lib, ... }: {
+  name = "centrifugo";
+  meta.maintainers = [ lib.maintainers.tie ];
+
+  nodes = lib.listToAttrs (lib.imap0
+    (index: name: {
+      inherit name;
+      value = { config, ... }: {
+        services.centrifugo = {
+          enable = true;
+          settings = {
+            inherit name;
+            port = centrifugoPort;
+            # See https://centrifugal.dev/docs/server/engines#redis-sharding
+            engine = "redis";
+            # Connect to local Redis shard via Unix socket.
+            redis_address =
+              let
+                otherNodes = lib.take index nodes ++ lib.drop (index + 1) nodes;
+              in
+              map (name: "${name}:${toString redisPort}") otherNodes ++ [
+                "unix://${config.services.redis.servers.centrifugo.unixSocket}"
+              ];
+            usage_stats_disable = true;
+            api_insecure = true;
+          };
+          extraGroups = [
+            config.services.redis.servers.centrifugo.user
+          ];
+        };
+        services.redis.servers.centrifugo = {
+          enable = true;
+          bind = null; # all interfaces
+          port = redisPort;
+          openFirewall = true;
+          settings.protected-mode = false;
+        };
+      };
+    })
+    nodes);
+
+  testScript = ''
+    import json
+
+    redisPort = ${toString redisPort}
+    centrifugoPort = ${toString centrifugoPort}
+
+    start_all()
+
+    for machine in machines:
+      machine.wait_for_unit("redis-centrifugo.service")
+      machine.wait_for_open_port(redisPort)
+
+    for machine in machines:
+      machine.wait_for_unit("centrifugo.service")
+      machine.wait_for_open_port(centrifugoPort)
+
+    # See https://centrifugal.dev/docs/server/server_api#info
+    def list_nodes(machine):
+      curl = "curl --fail-with-body --silent"
+      body = "{}"
+      resp = json.loads(machine.succeed(f"{curl} -d '{body}' http://localhost:{centrifugoPort}/api/info"))
+      return resp["result"]["nodes"]
+    machineNames = {m.name for m in machines}
+    for machine in machines:
+      nodes = list_nodes(machine)
+      assert len(nodes) == len(machines)
+      nodeNames = {n['name'] for n in nodes}
+      assert machineNames == nodeNames
+  '';
+}
diff --git a/nixpkgs/nixos/tests/containers-ip.nix b/nixpkgs/nixos/tests/containers-ip.nix
index ecead5c22f75..ecff99a3f0c2 100644
--- a/nixpkgs/nixos/tests/containers-ip.nix
+++ b/nixpkgs/nixos/tests/containers-ip.nix
@@ -19,10 +19,7 @@ in import ./make-test-python.nix ({ pkgs, lib, ... }: {
 
   nodes.machine =
     { pkgs, ... }: {
-      imports = [ ../modules/installer/cd-dvd/channel.nix ];
-      virtualisation = {
-        writableStore = true;
-      };
+      virtualisation.writableStore = true;
 
       containers.webserver4 = webserverFor "10.231.136.1" "10.231.136.2";
       containers.webserver6 = webserverFor "fc00::2" "fc00::1";
diff --git a/nixpkgs/nixos/tests/convos.nix b/nixpkgs/nixos/tests/convos.nix
index 8fe5892da9e5..06d8d30fcb14 100644
--- a/nixpkgs/nixos/tests/convos.nix
+++ b/nixpkgs/nixos/tests/convos.nix
@@ -22,7 +22,6 @@ in
   testScript = ''
     machine.wait_for_unit("convos")
     machine.wait_for_open_port(${toString port})
-    machine.succeed("journalctl -u convos | grep -q 'application available at.*${toString port}'")
     machine.succeed("curl -f http://localhost:${toString port}/")
   '';
 })
diff --git a/nixpkgs/nixos/tests/deepin.nix b/nixpkgs/nixos/tests/deepin.nix
index 7b2e2430f31c..d3ce79a535c1 100644
--- a/nixpkgs/nixos/tests/deepin.nix
+++ b/nixpkgs/nixos/tests/deepin.nix
@@ -36,12 +36,6 @@ import ./make-test-python.nix ({ pkgs, lib, ... }: {
       with subtest("Check that logging in has given the user ownership of devices"):
           machine.succeed("getfacl -p /dev/snd/timer | grep -q ${user.name}")
 
-      with subtest("Check if DDE wm chooser actually start"):
-          machine.wait_until_succeeds("pgrep -f dde-wm-chooser")
-          machine.wait_for_window("dde-wm-chooser")
-          machine.execute("pkill dde-wm-chooser")
-
-
       with subtest("Check if Deepin session components actually start"):
           machine.wait_until_succeeds("pgrep -f dde-session-daemon")
           machine.wait_for_window("dde-session-daemon")
diff --git a/nixpkgs/nixos/tests/dublin-traceroute.nix b/nixpkgs/nixos/tests/dublin-traceroute.nix
new file mode 100644
index 000000000000..b359b7fcdd6f
--- /dev/null
+++ b/nixpkgs/nixos/tests/dublin-traceroute.nix
@@ -0,0 +1,63 @@
+# This is a simple distributed test involving a topology with two
+# separate virtual networks - the "inside" and the "outside" - with a
+# client on the inside network, a server on the outside network, and a
+# router connected to both that performs Network Address Translation
+# for the client.
+import ./make-test-python.nix ({ pkgs, lib, ... }:
+  let
+    routerBase =
+      lib.mkMerge [
+        { virtualisation.vlans = [ 2 1 ];
+          networking.nftables.enable = true;
+          networking.nat.internalIPs = [ "192.168.1.0/24" ];
+          networking.nat.externalInterface = "eth1";
+        }
+      ];
+  in
+  {
+    name = "dublin-traceroute";
+    meta = with pkgs.lib.maintainers; {
+      maintainers = [ baloo ];
+    };
+
+    nodes.client = { nodes, ... }: {
+      imports = [ ./common/user-account.nix ];
+      virtualisation.vlans = [ 1 ];
+
+      networking.defaultGateway =
+        (builtins.head nodes.router.networking.interfaces.eth2.ipv4.addresses).address;
+      networking.nftables.enable = true;
+
+      programs.dublin-traceroute.enable = true;
+    };
+
+    nodes.router = { ... }: {
+      virtualisation.vlans = [ 2 1 ];
+      networking.nftables.enable = true;
+      networking.nat.internalIPs = [ "192.168.1.0/24" ];
+      networking.nat.externalInterface = "eth1";
+      networking.nat.enable = true;
+    };
+
+    nodes.server = { ... }: {
+      virtualisation.vlans = [ 2 ];
+      networking.firewall.enable = false;
+      services.httpd.enable = true;
+      services.httpd.adminAddr = "foo@example.org";
+      services.vsftpd.enable = true;
+      services.vsftpd.anonymousUser = true;
+    };
+
+    testScript = ''
+      client.start()
+      router.start()
+      server.start()
+
+      server.wait_for_unit("network.target")
+      router.wait_for_unit("network.target")
+      client.wait_for_unit("network.target")
+
+      # Make sure we can trace from an unprivileged user
+      client.succeed("sudo -u alice dublin-traceroute server")
+    '';
+  })
diff --git a/nixpkgs/nixos/tests/eris-server.nix b/nixpkgs/nixos/tests/eris-server.nix
index a50db3afebf5..b9d2b57401e0 100644
--- a/nixpkgs/nixos/tests/eris-server.nix
+++ b/nixpkgs/nixos/tests/eris-server.nix
@@ -3,7 +3,7 @@ import ./make-test-python.nix ({ pkgs, lib, ... }: {
   meta.maintainers = with lib.maintainers; [ ehmry ];
 
   nodes.server = {
-    environment.systemPackages = [ pkgs.eris-go pkgs.nim.pkgs.eris ];
+    environment.systemPackages = [ pkgs.eris-go pkgs.eriscmd ];
     services.eris-server = {
       enable = true;
       decode = true;
diff --git a/nixpkgs/nixos/tests/geoserver.nix b/nixpkgs/nixos/tests/geoserver.nix
new file mode 100644
index 000000000000..7e5507a296ea
--- /dev/null
+++ b/nixpkgs/nixos/tests/geoserver.nix
@@ -0,0 +1,24 @@
+{ pkgs, lib, ... }: {
+
+  name = "geoserver";
+  meta = {
+    maintainers = with lib; [ teams.geospatial.members ];
+  };
+
+  nodes = {
+    machine = { pkgs, ... }: {
+      virtualisation.diskSize = 2 * 1024;
+
+      environment.systemPackages = [ pkgs.geoserver ];
+    };
+  };
+
+  testScript = ''
+    start_all()
+
+    machine.execute("${pkgs.geoserver}/bin/geoserver-startup > /dev/null 2>&1 &")
+    machine.wait_until_succeeds("curl --fail --connect-timeout 2 http://localhost:8080/geoserver", timeout=60)
+
+    machine.succeed("curl --fail --connect-timeout 2 http://localhost:8080/geoserver/ows?service=WMS&version=1.3.0&request=GetCapabilities")
+  '';
+}
diff --git a/nixpkgs/nixos/tests/gnome-extensions.nix b/nixpkgs/nixos/tests/gnome-extensions.nix
new file mode 100644
index 000000000000..2faff9a4a80d
--- /dev/null
+++ b/nixpkgs/nixos/tests/gnome-extensions.nix
@@ -0,0 +1,151 @@
+import ./make-test-python.nix (
+{ pkgs, lib, ...}:
+{
+  name = "gnome-extensions";
+  meta.maintainers = [ lib.maintainers.piegames ];
+
+  nodes.machine =
+    { pkgs, ... }:
+    {
+      imports = [ ./common/user-account.nix ];
+
+      # Install all extensions
+      environment.systemPackages = lib.filter (e: e ? extensionUuid) (lib.attrValues pkgs.gnomeExtensions);
+
+      # Some extensions are broken, but that's kind of the point of a testing VM
+      nixpkgs.config.allowBroken = true;
+      # There are some aliases which throw exceptions; ignore them.
+      # Also prevent duplicate extensions under different names.
+      nixpkgs.config.allowAliases = false;
+
+      # Configure GDM
+      services.xserver.enable = true;
+      services.xserver.displayManager = {
+        gdm = {
+          enable = true;
+          debug = true;
+          wayland = true;
+        };
+        autoLogin = {
+          enable = true;
+          user = "alice";
+        };
+      };
+
+      # Configure Gnome
+      services.xserver.desktopManager.gnome.enable = true;
+      services.xserver.desktopManager.gnome.debug = true;
+
+      systemd.user.services = {
+        "org.gnome.Shell@wayland" = {
+          serviceConfig = {
+            ExecStart = [
+              # Clear the list before overriding it.
+              ""
+              # Eval API is now internal so Shell needs to run in unsafe mode.
+              # TODO: improve test driver so that it supports openqa-like manipulation
+              # that would allow us to drop this mess.
+              "${pkgs.gnome.gnome-shell}/bin/gnome-shell --unsafe-mode"
+            ];
+          };
+        };
+      };
+
+    };
+
+  testScript = { nodes, ... }: let
+    # Keep line widths somewhat manageable
+    user = nodes.machine.users.users.alice;
+    uid = toString user.uid;
+    bus = "DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/${uid}/bus";
+    # Run a command in the appropriate user environment
+    run = command: "su - ${user.name} -c '${bus} ${command}'";
+
+    # Call javascript in gnome shell, returns a tuple (success, output), where
+    # `success` is true if the dbus call was successful and output is what the
+    # javascript evaluates to.
+    eval = command: run "gdbus call --session -d org.gnome.Shell -o /org/gnome/Shell -m org.gnome.Shell.Eval ${command}";
+
+    # False when startup is done
+    startingUp = eval "Main.layoutManager._startingUp";
+
+    # Extensions to keep always enabled together
+    # Those are extensions that are usually always on for many users, and that we expect to work
+    # well together with most others without conflicts
+    alwaysOnExtensions = map (name: pkgs.gnomeExtensions.${name}.extensionUuid) [
+      "applications-menu"
+      "user-themes"
+    ];
+
+    # Extensions to enable and disable individually
+    # Extensions like dash-to-dock and dash-to-panel cannot be enabled at the same time.
+    testExtensions = map (name: pkgs.gnomeExtensions.${name}.extensionUuid) [
+      "appindicator"
+      "dash-to-dock"
+      "dash-to-panel"
+      "ddterm"
+      "emoji-selector"
+      "gsconnect"
+      "system-monitor"
+      "desktop-icons-ng-ding"
+      "workspace-indicator"
+      "vitals"
+    ];
+  in
+  ''
+    with subtest("Login to GNOME with GDM"):
+        # wait for gdm to start
+        machine.wait_for_unit("display-manager.service")
+        # wait for the wayland server
+        machine.wait_for_file("/run/user/${uid}/wayland-0")
+        # wait for alice to be logged in
+        machine.wait_for_unit("default.target", "${user.name}")
+        # check that logging in has given the user ownership of devices
+        assert "alice" in machine.succeed("getfacl -p /dev/snd/timer")
+
+    with subtest("Wait for GNOME Shell"):
+        # correct output should be (true, 'false')
+        machine.wait_until_succeeds(
+            "${startingUp} | grep -q 'true,..false'"
+        )
+
+        # Close the Activities view so that Shell can correctly track the focused window.
+        machine.send_key("esc")
+        # # Disable extension version validation (only use for manual testing)
+        # machine.succeed(
+        #   "${run "gsettings set org.gnome.shell disable-extension-version-validation true"}"
+        # )
+
+    # Assert that some extension is in a specific state
+    def checkState(target, extension):
+        state = machine.succeed(
+            f"${run "gnome-extensions info {extension}"} | grep '^  State: .*$'"
+        )
+        assert target in state, f"{state} instead of {target}"
+
+    def checkExtension(extension, disable):
+        with subtest(f"Enable extension '{extension}'"):
+            # Check that the extension is properly initialized; skip out of date ones
+            state = machine.succeed(
+                f"${run "gnome-extensions info {extension}"} | grep '^  State: .*$'"
+            )
+            if "OUT OF DATE" in state:
+                machine.log(f"Extension {extension} will be skipped because out of date")
+                return
+
+            assert "INITIALIZED" in state, f"{state} instead of INITIALIZED"
+
+            # Enable and optionally disable
+
+            machine.succeed(f"${run "gnome-extensions enable {extension}"}")
+            checkState("ENABLED", extension)
+
+            if disable:
+                machine.succeed(f"${run "gnome-extensions disable {extension}"}")
+                checkState("DISABLED", extension)
+    ''
+    + lib.concatLines (map (e: ''checkExtension("${e}", False)'') alwaysOnExtensions)
+    + lib.concatLines (map (e: ''checkExtension("${e}", True)'') testExtensions)
+  ;
+}
+)
diff --git a/nixpkgs/nixos/tests/gnome-xorg.nix b/nixpkgs/nixos/tests/gnome-xorg.nix
index 7762fff5c3a2..6ca700edcac3 100644
--- a/nixpkgs/nixos/tests/gnome-xorg.nix
+++ b/nixpkgs/nixos/tests/gnome-xorg.nix
@@ -5,7 +5,7 @@ import ./make-test-python.nix ({ pkgs, lib, ...} : {
   };
 
   nodes.machine = { nodes, ... }: let
-    user = nodes.machine.config.users.users.alice;
+    user = nodes.machine.users.users.alice;
   in
 
     { imports = [ ./common/user-account.nix ];
@@ -43,28 +43,28 @@ import ./make-test-python.nix ({ pkgs, lib, ...} : {
     };
 
   testScript = { nodes, ... }: let
-    user = nodes.machine.config.users.users.alice;
+    user = nodes.machine.users.users.alice;
     uid = toString user.uid;
     bus = "DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/${uid}/bus";
     xauthority = "/run/user/${uid}/gdm/Xauthority";
     display = "DISPLAY=:0.0";
     env = "${bus} XAUTHORITY=${xauthority} ${display}";
-    gdbus = "${env} gdbus";
-    su = command: "su - ${user.name} -c '${env} ${command}'";
+    # Run a command in the appropriate user environment
+    run = command: "su - ${user.name} -c '${bus} ${command}'";
 
     # Call javascript in gnome shell, returns a tuple (success, output), where
     # `success` is true if the dbus call was successful and output is what the
     # javascript evaluates to.
-    eval = "call --session -d org.gnome.Shell -o /org/gnome/Shell -m org.gnome.Shell.Eval";
+    eval = command: run "gdbus call --session -d org.gnome.Shell -o /org/gnome/Shell -m org.gnome.Shell.Eval ${command}";
 
     # False when startup is done
-    startingUp = su "${gdbus} ${eval} Main.layoutManager._startingUp";
+    startingUp = eval "Main.layoutManager._startingUp";
 
     # Start Console
-    launchConsole = su "${bus} gapplication launch org.gnome.Console";
+    launchConsole = run "gapplication launch org.gnome.Console";
 
     # Hopefully Console's wm class
-    wmClass = su "${gdbus} ${eval} global.display.focus_window.wm_class";
+    wmClass = eval "global.display.focus_window.wm_class";
   in ''
       with subtest("Login to GNOME Xorg with GDM"):
           machine.wait_for_x()
diff --git a/nixpkgs/nixos/tests/gnome.nix b/nixpkgs/nixos/tests/gnome.nix
index 448a3350240c..91182790cb24 100644
--- a/nixpkgs/nixos/tests/gnome.nix
+++ b/nixpkgs/nixos/tests/gnome.nix
@@ -40,25 +40,25 @@ import ./make-test-python.nix ({ pkgs, lib, ...} : {
 
   testScript = { nodes, ... }: let
     # Keep line widths somewhat manageable
-    user = nodes.machine.config.users.users.alice;
+    user = nodes.machine.users.users.alice;
     uid = toString user.uid;
     bus = "DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/${uid}/bus";
-    gdbus = "${bus} gdbus";
-    su = command: "su - ${user.name} -c '${command}'";
+    # Run a command in the appropriate user environment
+    run = command: "su - ${user.name} -c '${bus} ${command}'";
 
     # Call javascript in gnome shell, returns a tuple (success, output), where
     # `success` is true if the dbus call was successful and output is what the
     # javascript evaluates to.
-    eval = "call --session -d org.gnome.Shell -o /org/gnome/Shell -m org.gnome.Shell.Eval";
+    eval = command: run "gdbus call --session -d org.gnome.Shell -o /org/gnome/Shell -m org.gnome.Shell.Eval ${command}";
 
     # False when startup is done
-    startingUp = su "${gdbus} ${eval} Main.layoutManager._startingUp";
+    startingUp = eval "Main.layoutManager._startingUp";
 
     # Start Console
-    launchConsole = su "${bus} gapplication launch org.gnome.Console";
+    launchConsole = run "gapplication launch org.gnome.Console";
 
     # Hopefully Console's wm class
-    wmClass = su "${gdbus} ${eval} global.display.focus_window.wm_class";
+    wmClass = eval "global.display.focus_window.wm_class";
   in ''
       with subtest("Login to GNOME with GDM"):
           # wait for gdm to start
diff --git a/nixpkgs/nixos/tests/gvisor.nix b/nixpkgs/nixos/tests/gvisor.nix
index 77ff29341bed..7f130b709fc9 100644
--- a/nixpkgs/nixos/tests/gvisor.nix
+++ b/nixpkgs/nixos/tests/gvisor.nix
@@ -1,6 +1,6 @@
 # This test runs a container through gvisor and checks if simple container starts
 
-import ./make-test-python.nix ({ pkgs, ...} : {
+import ./make-test-python.nix ({ pkgs, ... }: {
   name = "gvisor";
   meta = with pkgs.lib.maintainers; {
     maintainers = [ andrew-d ];
@@ -9,21 +9,21 @@ import ./make-test-python.nix ({ pkgs, ...} : {
   nodes = {
     gvisor =
       { pkgs, ... }:
-        {
-          virtualisation.docker = {
-            enable = true;
-            extraOptions = "--add-runtime runsc=${pkgs.gvisor}/bin/runsc";
-          };
+      {
+        virtualisation.docker = {
+          enable = true;
+          extraOptions = "--add-runtime runsc=${pkgs.gvisor}/bin/runsc";
+        };
 
-          networking = {
-            dhcpcd.enable = false;
-            defaultGateway = "192.168.1.1";
-            interfaces.eth1.ipv4.addresses = pkgs.lib.mkOverride 0 [
-              { address = "192.168.1.2"; prefixLength = 24; }
-            ];
-          };
+        networking = {
+          dhcpcd.enable = false;
+          defaultGateway = "192.168.1.1";
+          interfaces.eth1.ipv4.addresses = pkgs.lib.mkOverride 0 [
+            { address = "192.168.1.2"; prefixLength = 24; }
+          ];
         };
-    };
+      };
+  };
 
   testScript = ''
     start_all()
@@ -31,13 +31,7 @@ import ./make-test-python.nix ({ pkgs, ...} : {
     gvisor.wait_for_unit("network.target")
     gvisor.wait_for_unit("sockets.target")
 
-    # Start by verifying that gvisor itself works
-    output = gvisor.succeed(
-        "${pkgs.gvisor}/bin/runsc -alsologtostderr do ${pkgs.coreutils}/bin/echo hello world"
-    )
-    assert output.strip() == "hello world"
-
-    # Also test the Docker runtime
+    # Test the Docker runtime
     gvisor.succeed("tar cv --files-from /dev/null | docker import - scratchimg")
     gvisor.succeed(
         "docker run -d --name=sleeping --runtime=runsc -v /nix/store:/nix/store -v /run/current-system/sw/bin:/bin scratchimg /bin/sleep 10"
diff --git a/nixpkgs/nixos/tests/incus/container.nix b/nixpkgs/nixos/tests/incus/container.nix
index 79b9e2fbabdc..49a22c08aad1 100644
--- a/nixpkgs/nixos/tests/incus/container.nix
+++ b/nixpkgs/nixos/tests/incus/container.nix
@@ -73,5 +73,33 @@ in
         meminfo = machine.succeed("incus exec container grep -- MemTotal /proc/meminfo").strip()
         meminfo_bytes = " ".join(meminfo.split(' ')[-2:])
         assert meminfo_bytes == "125000 kB", f"Wrong amount of memory reported from /proc/meminfo, want: '125000 kB', got: '{meminfo_bytes}'"
+
+    with subtest("lxc-container generator configures plain container"):
+        machine.execute("incus delete --force container")
+        machine.succeed("incus launch nixos container")
+        with machine.nested("Waiting for instance to start and be usable"):
+          retry(instance_is_up)
+
+        machine.succeed("incus exec container test -- -e /run/systemd/system/service.d/zzz-lxc-service.conf")
+
+    with subtest("lxc-container generator configures nested container"):
+        machine.execute("incus delete --force container")
+        machine.succeed("incus launch nixos container --config security.nesting=true")
+        with machine.nested("Waiting for instance to start and be usable"):
+          retry(instance_is_up)
+
+        machine.fail("incus exec container test -- -e /run/systemd/system/service.d/zzz-lxc-service.conf")
+        target = machine.succeed("incus exec container readlink -- -f /run/systemd/system/systemd-binfmt.service").strip()
+        assert target == "/dev/null", "lxc generator did not correctly mask /run/systemd/system/systemd-binfmt.service"
+
+    with subtest("lxc-container generator configures privileged container"):
+        machine.execute("incus delete --force container")
+        machine.succeed("incus launch nixos container --config security.privileged=true")
+        with machine.nested("Waiting for instance to start and be usable"):
+          retry(instance_is_up)
+        # give generator an extra second to run
+        machine.sleep(1)
+
+        machine.succeed("incus exec container test -- -e /run/systemd/system/service.d/zzz-lxc-service.conf")
   '';
 })
diff --git a/nixpkgs/nixos/tests/jitsi-meet.nix b/nixpkgs/nixos/tests/jitsi-meet.nix
index c39cd19e1f0a..fc6654f2c076 100644
--- a/nixpkgs/nixos/tests/jitsi-meet.nix
+++ b/nixpkgs/nixos/tests/jitsi-meet.nix
@@ -24,10 +24,23 @@ import ./make-test-python.nix ({ pkgs, ... }: {
       security.acme.acceptTerms = true;
       security.acme.defaults.email = "me@example.org";
       security.acme.defaults.server = "https://example.com"; # self-signed only
+
+      specialisation.caddy = {
+        inheritParentConfig = true;
+        configuration = {
+          services.jitsi-meet = {
+            caddy.enable = true;
+            nginx.enable = false;
+          };
+          services.caddy.virtualHosts.${config.services.jitsi-meet.hostName}.extraConfig = ''
+            tls internal
+          '';
+        };
+      };
     };
   };
 
-  testScript = ''
+  testScript = { nodes, ... }: ''
     server.wait_for_unit("jitsi-videobridge2.service")
     server.wait_for_unit("jicofo.service")
     server.wait_for_unit("nginx.service")
@@ -41,6 +54,15 @@ import ./make-test-python.nix ({ pkgs, ... }: {
     )
 
     client.wait_for_unit("network.target")
-    assert "<title>Jitsi Meet</title>" in client.succeed("curl -sSfkL http://server/")
+
+    def client_curl():
+        assert "<title>Jitsi Meet</title>" in client.succeed("curl -sSfkL http://server/")
+
+    client_curl()
+
+    with subtest("Testing backup service"):
+        server.succeed("${nodes.server.system.build.toplevel}/specialisation/caddy/bin/switch-to-configuration test")
+        server.wait_for_unit("caddy.service")
+        client_curl()
   '';
 })
diff --git a/nixpkgs/nixos/tests/kafka.nix b/nixpkgs/nixos/tests/kafka.nix
index 864253fd8c73..f4f9827ab7b5 100644
--- a/nixpkgs/nixos/tests/kafka.nix
+++ b/nixpkgs/nixos/tests/kafka.nix
@@ -6,13 +6,62 @@
 with pkgs.lib;
 
 let
-  makeKafkaTest = name: kafkaPackage: (import ./make-test-python.nix ({
+  makeKafkaTest = name: { kafkaPackage, mode ? "zookeeper" }: (import ./make-test-python.nix ({
     inherit name;
     meta = with pkgs.lib.maintainers; {
       maintainers = [ nequissimus ];
     };
 
     nodes = {
+      kafka = { ... }: {
+        services.apache-kafka = mkMerge [
+          ({
+            enable = true;
+            package = kafkaPackage;
+            settings = {
+              "offsets.topic.replication.factor" = 1;
+              "log.dirs" = [
+                "/var/lib/kafka/logdir1"
+                "/var/lib/kafka/logdir2"
+              ];
+            };
+          })
+          (mkIf (mode == "zookeeper") {
+            settings = {
+              "zookeeper.session.timeout.ms" = 600000;
+              "zookeeper.connect" = [ "zookeeper1:2181" ];
+            };
+          })
+          (mkIf (mode == "kraft") {
+            clusterId = "ak2fIHr4S8WWarOF_ODD0g";
+            formatLogDirs = true;
+            settings = {
+              "node.id" = 1;
+              "process.roles" = [
+                "broker"
+                "controller"
+              ];
+              "listeners" = [
+                "PLAINTEXT://:9092"
+                "CONTROLLER://:9093"
+              ];
+              "listener.security.protocol.map" = [
+                "PLAINTEXT:PLAINTEXT"
+                "CONTROLLER:PLAINTEXT"
+              ];
+              "controller.quorum.voters" = [
+                "1@kafka:9093"
+              ];
+              "controller.listener.names" = [ "CONTROLLER" ];
+            };
+          })
+        ];
+
+        networking.firewall.allowedTCPPorts = [ 9092 9093 ];
+        # i686 tests: qemu-system-i386 can simulate max 2047MB RAM (not 2048)
+        virtualisation.memorySize = 2047;
+      };
+    } // optionalAttrs (mode == "zookeeper") {
       zookeeper1 = { ... }: {
         services.zookeeper = {
           enable = true;
@@ -20,29 +69,16 @@ let
 
         networking.firewall.allowedTCPPorts = [ 2181 ];
       };
-      kafka = { ... }: {
-        services.apache-kafka = {
-          enable = true;
-          extraProperties = ''
-            offsets.topic.replication.factor = 1
-            zookeeper.session.timeout.ms = 600000
-          '';
-          package = kafkaPackage;
-          zookeeper = "zookeeper1:2181";
-        };
-
-        networking.firewall.allowedTCPPorts = [ 9092 ];
-        # i686 tests: qemu-system-i386 can simulate max 2047MB RAM (not 2048)
-        virtualisation.memorySize = 2047;
-      };
     };
 
     testScript = ''
       start_all()
 
+      ${optionalString (mode == "zookeeper") ''
       zookeeper1.wait_for_unit("default.target")
       zookeeper1.wait_for_unit("zookeeper.service")
       zookeeper1.wait_for_open_port(2181)
+      ''}
 
       kafka.wait_for_unit("default.target")
       kafka.wait_for_unit("apache-kafka.service")
@@ -67,12 +103,13 @@ let
   }) { inherit system; });
 
 in with pkgs; {
-  kafka_2_8  = makeKafkaTest "kafka_2_8"  apacheKafka_2_8;
-  kafka_3_0  = makeKafkaTest "kafka_3_0"  apacheKafka_3_0;
-  kafka_3_1  = makeKafkaTest "kafka_3_1"  apacheKafka_3_1;
-  kafka_3_2  = makeKafkaTest "kafka_3_2"  apacheKafka_3_2;
-  kafka_3_3  = makeKafkaTest "kafka_3_3"  apacheKafka_3_3;
-  kafka_3_4  = makeKafkaTest "kafka_3_4"  apacheKafka_3_4;
-  kafka_3_5  = makeKafkaTest "kafka_3_5"  apacheKafka_3_5;
-  kafka  = makeKafkaTest "kafka"  apacheKafka;
+  kafka_2_8 = makeKafkaTest "kafka_2_8" { kafkaPackage = apacheKafka_2_8; };
+  kafka_3_0 = makeKafkaTest "kafka_3_0" { kafkaPackage = apacheKafka_3_0; };
+  kafka_3_1 = makeKafkaTest "kafka_3_1" { kafkaPackage = apacheKafka_3_1; };
+  kafka_3_2 = makeKafkaTest "kafka_3_2" { kafkaPackage = apacheKafka_3_2; };
+  kafka_3_3 = makeKafkaTest "kafka_3_3" { kafkaPackage = apacheKafka_3_3; };
+  kafka_3_4 = makeKafkaTest "kafka_3_4" { kafkaPackage = apacheKafka_3_4; };
+  kafka_3_5 = makeKafkaTest "kafka_3_5" { kafkaPackage = apacheKafka_3_5; };
+  kafka = makeKafkaTest "kafka" { kafkaPackage = apacheKafka; };
+  kafka_kraft = makeKafkaTest "kafka_kraft" { kafkaPackage = apacheKafka; mode = "kraft"; };
 }
diff --git a/nixpkgs/nixos/tests/lanraragi.nix b/nixpkgs/nixos/tests/lanraragi.nix
index f513ac9d252b..7a4a1a489bdf 100644
--- a/nixpkgs/nixos/tests/lanraragi.nix
+++ b/nixpkgs/nixos/tests/lanraragi.nix
@@ -10,19 +10,17 @@ import ./make-test-python.nix ({ pkgs, lib, ... }: {
       services.lanraragi = {
         enable = true;
         passwordFile = pkgs.writeText "lrr-test-pass" ''
-          ultra-secure-password
+          Ultra-secure-p@ssword-"with-spec1al\chars
         '';
         port = 4000;
         redis = {
           port = 4001;
           passwordFile = pkgs.writeText "redis-lrr-test-pass" ''
-            still-a-very-secure-password
+            123-redis-PASS
           '';
         };
       };
     };
-
-
   };
 
   testScript = ''
@@ -34,7 +32,7 @@ import ./make-test-python.nix ({ pkgs, lib, ... }: {
 
     machine2.wait_for_unit("lanraragi.service")
     machine2.wait_until_succeeds("curl -f localhost:4000")
-    machine2.succeed("[ $(curl -o /dev/null -X post 'http://localhost:4000/login' --data-raw 'password=ultra-secure-password' -w '%{http_code}') -eq 302 ]")
+    machine2.succeed("[ $(curl -o /dev/null -X post 'http://localhost:4000/login' --data-raw 'password=Ultra-secure-p@ssword-\"with-spec1al\\chars' -w '%{http_code}') -eq 302 ]")
   '';
 })
 
diff --git a/nixpkgs/nixos/tests/libvirtd.nix b/nixpkgs/nixos/tests/libvirtd.nix
index 41d06cc9643f..df80dcc21a2e 100644
--- a/nixpkgs/nixos/tests/libvirtd.nix
+++ b/nixpkgs/nixos/tests/libvirtd.nix
@@ -14,10 +14,10 @@ import ./make-test-python.nix ({ pkgs, ... }: {
           libvirtd.hooks.qemu.is_working = "${pkgs.writeShellScript "testHook.sh" ''
             touch /tmp/qemu_hook_is_working
           ''}";
+          libvirtd.nss.enable = true;
         };
         boot.supportedFilesystems = [ "zfs" ];
         networking.hostId = "deadbeef"; # needed for zfs
-        networking.nameservers = [ "192.168.122.1" ];
         security.polkit.enable = true;
         environment.systemPackages = with pkgs; [ virt-manager ];
       };
diff --git a/nixpkgs/nixos/tests/lxd/ui.nix b/nixpkgs/nixos/tests/lxd/ui.nix
index 86cb30d8c2b6..ff651725ba70 100644
--- a/nixpkgs/nixos/tests/lxd/ui.nix
+++ b/nixpkgs/nixos/tests/lxd/ui.nix
@@ -11,9 +11,37 @@ import ../make-test-python.nix ({ pkgs, lib, ... }: {
       lxd.ui.enable = true;
     };
 
-    environment.systemPackages = [ pkgs.curl ];
+    environment.systemPackages =
+      let
+        seleniumScript = pkgs.writers.writePython3Bin "selenium-script"
+          {
+            libraries = with pkgs.python3Packages; [ selenium ];
+          } ''
+          from selenium import webdriver
+          from selenium.webdriver.common.by import By
+          from selenium.webdriver.firefox.options import Options
+          from selenium.webdriver.support.ui import WebDriverWait
+
+          options = Options()
+          options.add_argument("--headless")
+          service = webdriver.FirefoxService(executable_path="${lib.getExe pkgs.geckodriver}")  # noqa: E501
+
+          driver = webdriver.Firefox(options=options, service=service)
+          driver.implicitly_wait(10)
+          driver.get("https://localhost:8443/ui")
+
+          wait = WebDriverWait(driver, 60)
+
+          assert len(driver.find_elements(By.CLASS_NAME, "l-application")) > 0
+          assert len(driver.find_elements(By.CLASS_NAME, "l-navigation__drawer")) > 0
+
+          driver.close()
+        '';
+      in
+      with pkgs; [ curl firefox-unwrapped geckodriver seleniumScript ];
   };
 
+
   testScript = ''
     machine.wait_for_unit("sockets.target")
     machine.wait_for_unit("lxd.service")
@@ -31,5 +59,8 @@ import ../make-test-python.nix ({ pkgs, lib, ... }: {
 
     # Ensure the endpoint returns an HTML page with 'LXD UI' in the title
     machine.succeed("curl -kLs https://localhost:8443/ui | grep '<title>LXD UI</title>'")
+
+    # Ensure the application is actually rendered by the Javascript
+    machine.succeed("PYTHONUNBUFFERED=1 selenium-script")
   '';
 })
diff --git a/nixpkgs/nixos/tests/matrix/synapse.nix b/nixpkgs/nixos/tests/matrix/synapse.nix
index 98b077469192..8c10a575ffbd 100644
--- a/nixpkgs/nixos/tests/matrix/synapse.nix
+++ b/nixpkgs/nixos/tests/matrix/synapse.nix
@@ -1,31 +1,15 @@
 import ../make-test-python.nix ({ pkgs, ... } : let
 
-
-  runWithOpenSSL = file: cmd: pkgs.runCommand file {
-    buildInputs = [ pkgs.openssl ];
-  } cmd;
-
-
-  ca_key = runWithOpenSSL "ca-key.pem" "openssl genrsa -out $out 2048";
-  ca_pem = runWithOpenSSL "ca.pem" ''
-    openssl req \
-      -x509 -new -nodes -key ${ca_key} \
-      -days 10000 -out $out -subj "/CN=snakeoil-ca"
+  ca_key = mailerCerts.ca.key;
+  ca_pem = mailerCerts.ca.cert;
+
+  bundle = pkgs.runCommand "bundle" {
+    nativeBuildInputs = [ pkgs.minica ];
+  } ''
+    minica -ca-cert ${ca_pem} -ca-key ${ca_key} \
+      -domains localhost
+    install -Dm444 -t $out localhost/{key,cert}.pem
   '';
-  key = runWithOpenSSL "matrix_key.pem" "openssl genrsa -out $out 2048";
-  csr = runWithOpenSSL "matrix.csr" ''
-    openssl req \
-       -new -key ${key} \
-       -out $out -subj "/CN=localhost" \
-  '';
-  cert = runWithOpenSSL "matrix_cert.pem" ''
-    openssl x509 \
-      -req -in ${csr} \
-      -CA ${ca_pem} -CAkey ${ca_key} \
-      -CAcreateserial -out $out \
-      -days 365
-  '';
-
 
   mailerCerts = import ../common/acme/server/snakeoil-certs.nix;
   mailerDomain = mailerCerts.domain;
@@ -82,8 +66,8 @@ in {
             host = "localhost";
             port = config.services.redis.servers.matrix-synapse.port;
           };
-          tls_certificate_path = "${cert}";
-          tls_private_key_path = "${key}";
+          tls_certificate_path = "${bundle}/cert.pem";
+          tls_private_key_path = "${bundle}/key.pem";
           registration_shared_secret = registrationSharedSecret;
           public_baseurl = "https://example.com";
           email = {
@@ -203,8 +187,8 @@ in {
         settings = {
           inherit listeners;
           database.name = "sqlite3";
-          tls_certificate_path = "${cert}";
-          tls_private_key_path = "${key}";
+          tls_certificate_path = "${bundle}/cert.pem";
+          tls_private_key_path = "${bundle}/key.pem";
         };
       };
     };
@@ -222,7 +206,7 @@ in {
         "journalctl -u matrix-synapse.service | grep -q 'Connected to redis'"
     )
     serverpostgres.require_unit_state("postgresql.service")
-    serverpostgres.succeed("register_new_matrix_user -u ${testUser} -p ${testPassword} -a -k ${registrationSharedSecret} https://localhost:8448/")
+    serverpostgres.succeed("REQUESTS_CA_BUNDLE=${ca_pem} register_new_matrix_user -u ${testUser} -p ${testPassword} -a -k ${registrationSharedSecret} https://localhost:8448/")
     serverpostgres.succeed("obtain-token-and-register-email")
     serversqlite.wait_for_unit("matrix-synapse.service")
     serversqlite.wait_until_succeeds(
diff --git a/nixpkgs/nixos/tests/nextcloud/with-declarative-redis-and-secrets.nix b/nixpkgs/nixos/tests/nextcloud/with-declarative-redis-and-secrets.nix
index e638f2e5b861..addc898bd760 100644
--- a/nixpkgs/nixos/tests/nextcloud/with-declarative-redis-and-secrets.nix
+++ b/nixpkgs/nixos/tests/nextcloud/with-declarative-redis-and-secrets.nix
@@ -41,10 +41,13 @@ in {
         };
         secretFile = "/etc/nextcloud-secrets.json";
 
-        extraOptions.redis = {
-          dbindex = 0;
-          timeout = 1.5;
-          # password handled via secretfile below
+        extraOptions = {
+          allow_local_remote_servers = true;
+          redis = {
+            dbindex = 0;
+            timeout = 1.5;
+            # password handled via secretfile below
+          };
         };
         configureRedis = true;
       };
@@ -62,6 +65,7 @@ in {
 
       services.postgresql = {
         enable = true;
+        package = pkgs.postgresql_14;
       };
       systemd.services.postgresql.postStart = pkgs.lib.mkAfter ''
         password=$(cat ${passFile})
diff --git a/nixpkgs/nixos/tests/nixops/default.nix b/nixpkgs/nixos/tests/nixops/default.nix
index b8f747b2a19f..f7a26f2461c4 100644
--- a/nixpkgs/nixos/tests/nixops/default.nix
+++ b/nixpkgs/nixos/tests/nixops/default.nix
@@ -1,4 +1,6 @@
-{ pkgs, ... }:
+{ pkgs
+, testers
+, ... }:
 let
   inherit (pkgs) lib;
 
@@ -19,7 +21,7 @@ let
     passthru.override = args': testsForPackage (args // args');
   };
 
-  testLegacyNetwork = { nixopsPkg, ... }: pkgs.nixosTest ({
+  testLegacyNetwork = { nixopsPkg, ... }: testers.nixosTest ({
     name = "nixops-legacy-network";
     nodes = {
       deployer = { config, lib, nodes, pkgs, ... }: {
diff --git a/nixpkgs/nixos/tests/seatd.nix b/nixpkgs/nixos/tests/seatd.nix
new file mode 100644
index 000000000000..138a6cb1cf44
--- /dev/null
+++ b/nixpkgs/nixos/tests/seatd.nix
@@ -0,0 +1,51 @@
+import ./make-test-python.nix ({ pkgs, lib, ... }:
+
+let
+  seatd-test = pkgs.writeShellApplication {
+    name = "seatd-client-pid";
+    text = ''
+      journalctl -u seatd --no-pager -b | while read -r line; do
+          case "$line" in
+          *"New client connected"*)
+              line="''${line##*pid: }"
+              pid="''${line%%,*}"
+              ;;
+          *"Opened client"*)
+              echo "$pid"
+              exit
+          esac
+      done;
+    '';
+  };
+in
+{
+  name = "seatd";
+  meta.maintainers = with lib.maintainers; [ sinanmohd ];
+
+  nodes.machine = { ... }: {
+    imports = [ ./common/user-account.nix ];
+    services.getty.autologinUser = "alice";
+    users.users.alice.extraGroups = [ "seat" "wheel" ];
+
+    fonts.enableDefaultPackages = true;
+    environment.systemPackages = with pkgs; [
+      dwl
+      foot
+      seatd-test
+    ];
+
+    programs.bash.loginShellInit = ''
+      [ "$(tty)" = "/dev/tty1" ] &&
+          dwl -s 'foot touch /tmp/foot_started'
+    '';
+
+    hardware.opengl.enable = true;
+    virtualisation.qemu.options = [ "-vga none -device virtio-gpu-pci" ];
+    services.seatd.enable = true;
+  };
+
+  testScript = ''
+    machine.wait_for_file("/tmp/foot_started")
+    machine.succeed("test $(seatd-client-pid) = $(pgrep dwl)")
+  '';
+})
diff --git a/nixpkgs/nixos/tests/sonic-server.nix b/nixpkgs/nixos/tests/sonic-server.nix
new file mode 100644
index 000000000000..bb98047619b2
--- /dev/null
+++ b/nixpkgs/nixos/tests/sonic-server.nix
@@ -0,0 +1,22 @@
+import ./make-test-python.nix ({ pkgs, lib, ... }: {
+  name = "sonic-server";
+
+  meta = {
+    maintainers = with lib.maintainers; [ anthonyroussel ];
+  };
+
+  nodes.machine = { pkgs, ... }: {
+    services.sonic-server.enable = true;
+  };
+
+  testScript = ''
+    machine.start()
+
+    machine.wait_for_unit("sonic-server.service")
+    machine.wait_for_open_port(1491)
+
+    with subtest("Check control mode"):
+      result = machine.succeed('(echo START control; sleep 1; echo PING; echo QUIT) | nc localhost 1491').splitlines()
+      assert result[2] == "PONG", f"expected 'PONG', got '{result[2]}'"
+  '';
+})
diff --git a/nixpkgs/nixos/tests/sudo-rs.nix b/nixpkgs/nixos/tests/sudo-rs.nix
index 6006863217b6..753e00686e95 100644
--- a/nixpkgs/nixos/tests/sudo-rs.nix
+++ b/nixpkgs/nixos/tests/sudo-rs.nix
@@ -22,11 +22,8 @@ in
           test5 = { isNormalUser = true; };
         };
 
-        security.sudo.enable = false;
-
         security.sudo-rs = {
           enable = true;
-          package = pkgs.sudo-rs;
           wheelNeedsPassword = false;
 
           extraRules = [
@@ -56,10 +53,7 @@ in
         noadmin = { isNormalUser = true; };
       };
 
-      security.sudo.enable = false;
-
       security.sudo-rs = {
-        package = pkgs.sudo-rs;
         enable = true;
         wheelNeedsPassword = false;
         execWheelOnly = true;
diff --git a/nixpkgs/nixos/tests/systemd-initrd-luks-unl0kr.nix b/nixpkgs/nixos/tests/systemd-initrd-luks-unl0kr.nix
new file mode 100644
index 000000000000..0658a098cfa2
--- /dev/null
+++ b/nixpkgs/nixos/tests/systemd-initrd-luks-unl0kr.nix
@@ -0,0 +1,75 @@
+import ./make-test-python.nix ({ lib, pkgs, ... }: let
+  passphrase = "secret";
+in {
+  name = "systemd-initrd-luks-unl0kr";
+  meta = with pkgs.lib.maintainers; {
+    maintainers = [ tomfitzhenry ];
+  };
+
+  enableOCR = true;
+
+  nodes.machine = { pkgs, ... }: {
+    virtualisation = {
+      emptyDiskImages = [ 512 512 ];
+      useBootLoader = true;
+      mountHostNixStore = true;
+      useEFIBoot = true;
+      qemu.options = [
+        "-vga virtio"
+      ];
+    };
+    boot.loader.systemd-boot.enable = true;
+
+    boot.initrd.availableKernelModules = [
+      "evdev" # for entering pw
+      "bochs"
+    ];
+
+    environment.systemPackages = with pkgs; [ cryptsetup ];
+    boot.initrd = {
+      systemd = {
+        enable = true;
+        emergencyAccess = true;
+      };
+      unl0kr.enable = true;
+    };
+
+    specialisation.boot-luks.configuration = {
+      boot.initrd.luks.devices = lib.mkVMOverride {
+        # We have two disks and only type one password - key reuse is in place
+        cryptroot.device = "/dev/vdb";
+        cryptroot2.device = "/dev/vdc";
+      };
+      virtualisation.rootDevice = "/dev/mapper/cryptroot";
+      virtualisation.fileSystems."/".autoFormat = true;
+      # test mounting device unlocked in initrd after switching root
+      virtualisation.fileSystems."/cryptroot2".device = "/dev/mapper/cryptroot2";
+    };
+  };
+
+  testScript = ''
+    # Create encrypted volume
+    machine.wait_for_unit("multi-user.target")
+    machine.succeed("echo -n ${passphrase} | cryptsetup luksFormat -q --iter-time=1 /dev/vdb -")
+    machine.succeed("echo -n ${passphrase} | cryptsetup luksFormat -q --iter-time=1 /dev/vdc -")
+    machine.succeed("echo -n ${passphrase} | cryptsetup luksOpen   -q               /dev/vdc cryptroot2")
+    machine.succeed("mkfs.ext4 /dev/mapper/cryptroot2")
+
+    # Boot from the encrypted disk
+    machine.succeed("bootctl set-default nixos-generation-1-specialisation-boot-luks.conf")
+    machine.succeed("sync")
+    machine.crash()
+
+    # Boot and decrypt the disk
+    machine.start()
+    machine.wait_for_text("Password required for booting")
+    machine.screenshot("prompt")
+    machine.send_chars("${passphrase}")
+    machine.screenshot("pw")
+    machine.send_chars("\n")
+    machine.wait_for_unit("multi-user.target")
+
+    assert "/dev/mapper/cryptroot on / type ext4" in machine.succeed("mount"), "/dev/mapper/cryptroot do not appear in mountpoints list"
+    assert "/dev/mapper/cryptroot2 on /cryptroot2 type ext4" in machine.succeed("mount")
+  '';
+})
diff --git a/nixpkgs/nixos/tests/systemd-timesyncd.nix b/nixpkgs/nixos/tests/systemd-timesyncd.nix
index f38d06be1516..02f49f49b8a5 100644
--- a/nixpkgs/nixos/tests/systemd-timesyncd.nix
+++ b/nixpkgs/nixos/tests/systemd-timesyncd.nix
@@ -15,13 +15,14 @@ in {
       # create the path that should be migrated by our activation script when
       # upgrading to a newer nixos version
       system.stateVersion = "19.03";
-      systemd.tmpfiles.rules = [
-        "r /var/lib/systemd/timesync -"
-        "d /var/lib/systemd -"
-        "d /var/lib/private/systemd/timesync -"
-        "L /var/lib/systemd/timesync - - - - /var/lib/private/systemd/timesync"
-        "d /var/lib/private/systemd/timesync - systemd-timesync systemd-timesync -"
-      ];
+      systemd.tmpfiles.settings.systemd-timesyncd-test = {
+        "/var/lib/systemd/timesync".R = { };
+        "/var/lib/systemd/timesync".L.argument = "/var/lib/private/systemd/timesync";
+        "/var/lib/private/systemd/timesync".d = {
+          user = "systemd-timesync";
+          group = "systemd-timesync";
+        };
+      };
     });
   };
 
diff --git a/nixpkgs/nixos/tests/telegraf.nix b/nixpkgs/nixos/tests/telegraf.nix
index c3cdb1645213..af9c5c387a5d 100644
--- a/nixpkgs/nixos/tests/telegraf.nix
+++ b/nixpkgs/nixos/tests/telegraf.nix
@@ -12,6 +12,7 @@ import ./make-test-python.nix ({ pkgs, ...} : {
     services.telegraf.extraConfig = {
       agent.interval = "1s";
       agent.flush_interval = "1s";
+      inputs.procstat = {};
       inputs.exec = {
         commands = [
           "${pkgs.runtimeShell} -c 'echo $SECRET,tag=a i=42i'"
diff --git a/nixpkgs/nixos/tests/terminal-emulators.nix b/nixpkgs/nixos/tests/terminal-emulators.nix
index b52801c898eb..2306c03c18e7 100644
--- a/nixpkgs/nixos/tests/terminal-emulators.nix
+++ b/nixpkgs/nixos/tests/terminal-emulators.nix
@@ -76,7 +76,7 @@ let tests = {
 
       rio.pkg = p: p.rio;
       rio.cmd = "rio -e $command";
-      rio.pinkValue = "#FF1261";
+      rio.colourTest = false; # the rendering is changing too much so colors change every release.
 
       roxterm.pkg = p: p.roxterm;
       roxterm.cmd = "roxterm -e $command";
diff --git a/nixpkgs/nixos/tests/tomcat.nix b/nixpkgs/nixos/tests/tomcat.nix
index a5f219e104ad..ff58ca8ac618 100644
--- a/nixpkgs/nixos/tests/tomcat.nix
+++ b/nixpkgs/nixos/tests/tomcat.nix
@@ -1,5 +1,6 @@
 import ./make-test-python.nix ({ pkgs, ... }: {
   name = "tomcat";
+  meta.maintainers = [ lib.maintainers.anthonyroussel ];
 
   nodes.machine = { pkgs, ... }: {
     services.tomcat = {
diff --git a/nixpkgs/nixos/tests/web-servers/stargazer.nix b/nixpkgs/nixos/tests/web-servers/stargazer.nix
index c522cfee5dbc..6365d6a4fff1 100644
--- a/nixpkgs/nixos/tests/web-servers/stargazer.nix
+++ b/nixpkgs/nixos/tests/web-servers/stargazer.nix
@@ -24,7 +24,7 @@
     geminiserver.wait_for_open_port(1965)
 
     with subtest("check is serving over gemini"):
-      response = geminiserver.succeed("${pkgs.gmni}/bin/gmni -j once -i -N gemini://localhost:1965")
+      response = geminiserver.succeed("${pkgs.gemget}/bin/gemget --header -o - gemini://localhost:1965")
       print(response)
       assert "Hello NixOS!" in response
   '';
diff --git a/nixpkgs/nixos/tests/xscreensaver.nix b/nixpkgs/nixos/tests/xscreensaver.nix
new file mode 100644
index 000000000000..820ddbb0e962
--- /dev/null
+++ b/nixpkgs/nixos/tests/xscreensaver.nix
@@ -0,0 +1,64 @@
+import ./make-test-python.nix ({ pkgs, lib, ... }: {
+  name = "pass-secret-service";
+  meta.maintainers = with lib.maintainers; [ vancluever AndersonTorres ];
+
+  nodes = {
+    ok = { nodes, pkgs, ... }:
+      {
+        imports = [ ./common/x11.nix ./common/user-account.nix ];
+        test-support.displayManager.auto.user = "alice";
+        services.xscreensaver.enable = true;
+      };
+
+    empty_wrapperPrefix = { nodes, pkgs, ... }:
+      {
+        imports = [ ./common/x11.nix ./common/user-account.nix ];
+        test-support.displayManager.auto.user = "alice";
+        services.xscreensaver.enable = true;
+        nixpkgs.overlays = [
+          (self: super: {
+            xscreensaver = super.xscreensaver.override {
+              wrapperPrefix = "";
+            };
+          })
+        ];
+      };
+
+    bad_wrapperPrefix = { nodes, pkgs, ... }:
+      {
+        imports = [ ./common/x11.nix ./common/user-account.nix ];
+        test-support.displayManager.auto.user = "alice";
+        services.xscreensaver.enable = true;
+        nixpkgs.overlays = [
+          (self: super: {
+            xscreensaver = super.xscreensaver.override {
+              wrapperPrefix = "/a/bad/path";
+            };
+          })
+        ];
+      };
+  };
+
+  testScript = ''
+    ok.wait_for_x()
+    ok.wait_for_unit("xscreensaver", "alice")
+    _, output_ok = ok.systemctl("status xscreensaver", "alice")
+    assert 'To prevent the kernel from randomly unlocking' not in output_ok
+    assert 'your screen via the out-of-memory killer' not in output_ok
+    assert '"xscreensaver-auth" must be setuid root' not in output_ok
+
+    empty_wrapperPrefix.wait_for_x()
+    empty_wrapperPrefix.wait_for_unit("xscreensaver", "alice")
+    _, output_empty_wrapperPrefix = empty_wrapperPrefix.systemctl("status xscreensaver", "alice")
+    assert 'To prevent the kernel from randomly unlocking' in output_empty_wrapperPrefix
+    assert 'your screen via the out-of-memory killer' in output_empty_wrapperPrefix
+    assert '"xscreensaver-auth" must be setuid root' in output_empty_wrapperPrefix
+
+    bad_wrapperPrefix.wait_for_x()
+    bad_wrapperPrefix.wait_for_unit("xscreensaver", "alice")
+    _, output_bad_wrapperPrefix = bad_wrapperPrefix.systemctl("status xscreensaver", "alice")
+    assert 'To prevent the kernel from randomly unlocking' in output_bad_wrapperPrefix
+    assert 'your screen via the out-of-memory killer' in output_bad_wrapperPrefix
+    assert '"xscreensaver-auth" must be setuid root' in output_bad_wrapperPrefix
+  '';
+})
diff --git a/nixpkgs/nixos/tests/zfs.nix b/nixpkgs/nixos/tests/zfs.nix
index 3454fbaf78fe..ad4ea254f34d 100644
--- a/nixpkgs/nixos/tests/zfs.nix
+++ b/nixpkgs/nixos/tests/zfs.nix
@@ -13,6 +13,7 @@ let
                       else pkgs.linuxPackages
     , enableUnstable ? false
     , enableSystemdStage1 ? false
+    , zfsPackage ? if enableUnstable then pkgs.zfs else pkgs.zfsUnstable
     , extraTest ? ""
     }:
     makeTest {
@@ -21,7 +22,7 @@ let
         maintainers = [ adisbladis elvishjerricco ];
       };
 
-      nodes.machine = { pkgs, lib, ... }:
+      nodes.machine = { config, pkgs, lib, ... }:
         let
           usersharePath = "/var/lib/samba/usershares";
         in {
@@ -35,8 +36,8 @@ let
         boot.loader.efi.canTouchEfiVariables = true;
         networking.hostId = "deadbeef";
         boot.kernelPackages = kernelPackage;
+        boot.zfs.package = zfsPackage;
         boot.supportedFilesystems = [ "zfs" ];
-        boot.zfs.enableUnstable = enableUnstable;
         boot.initrd.systemd.enable = enableSystemdStage1;
 
         environment.systemPackages = [ pkgs.parted ];
@@ -193,6 +194,11 @@ let
 
 in {
 
+  # maintainer: @raitobezarius
+  series_2_1 = makeZfsTest "2.1-series" {
+    zfsPackage = pkgs.zfs_2_1;
+  };
+
   stable = makeZfsTest "stable" { };
 
   unstable = makeZfsTest "unstable" {